Merge branch 'feat/safe_dds' of github.com:PX4/PX4-Autopilot into feat/safe_dds

This commit is contained in:
Pedro-Roque
2026-03-12 15:07:21 -07:00
52 changed files with 1520 additions and 973 deletions
@@ -44,8 +44,6 @@ param set-default FW_T_SINK_MIN 3
param set-default FW_W_EN 1
param set-default FD_ESCS_EN 0
param set-default MIS_TAKEOFF_ALT 30
param set-default NAV_ACC_RAD 15
@@ -104,4 +104,3 @@ param set-default VT_FWD_THRUST_EN 4
param set-default VT_PITCH_MIN -5
param set-default VT_F_TRANS_THR 1
param set-default VT_TYPE 2
param set-default FD_ESCS_EN 0
@@ -26,7 +26,6 @@ param set-default SENS_EN_GPSSIM 1
param set-default SENS_EN_BAROSIM 1
param set-default SENS_EN_MAGSIM 1
param set-default COM_ARM_CHK_ESCS 0 # We don't have ESCs
param set-default FD_ESCS_EN 0 # We don't have ESCs - but maybe we need this later?
# Set proper failsafes
param set-default COM_ACT_FAIL_ACT 0
@@ -28,7 +28,6 @@ param set-default SIM_GZ_EN 1
param set-default SENS_EN_MAGSIM 1
param set-default COM_ARM_CHK_ESCS 0 # We don't have ESCs
param set-default FD_ESCS_EN 0
param set-default CA_AIRFRAME 14
param set-default MAV_TYPE 45
@@ -28,7 +28,6 @@ param set-default SIM_GZ_EN 1
param set-default SENS_EN_MAGSIM 1
param set-default COM_ARM_CHK_ESCS 0 # We don't have ESCs
param set-default FD_ESCS_EN 0
param set-default CA_AIRFRAME 14
param set-default MAV_TYPE 45
@@ -1,9 +0,0 @@
#!/bin/bash
cd boards/modalai/voxl2/libfc-sensor-api
rm -fR build
mkdir build
cd build
CC=/home/4.1.0.4/tools/linaro64/bin/aarch64-linux-gnu-gcc cmake ..
make
cd ../../../../..
+6 -4
View File
@@ -29,10 +29,12 @@ if /bin/ls /usr/lib/rfsa/adsp/testsig-*.so &> /dev/null; then
/bin/echo "Found DSP signature file"
else
/bin/echo "[WARNING] Could not find DSP signature file"
# Look for the DSP signature generation script
if [ -f /share/modalai/qrb5165-slpi-test-sig/generate-test-sig.sh ]; then
/bin/echo "[INFO] Attempting to generate the DSP signature file"
# Automatically generate the test signature so that px4 can run on SLPI DSP
# Look for the DSP signature generation script (platform-specific)
if [ -f /share/modalai/qcs6490-slpi-test-sig/generate-test-sig.sh ]; then
/bin/echo "[INFO] Attempting to generate the DSP signature file (qcs6490)"
/share/modalai/qcs6490-slpi-test-sig/generate-test-sig.sh
elif [ -f /share/modalai/qrb5165-slpi-test-sig/generate-test-sig.sh ]; then
/bin/echo "[INFO] Attempting to generate the DSP signature file (qrb5165)"
/share/modalai/qrb5165-slpi-test-sig/generate-test-sig.sh
else
/bin/echo "[ERROR] Could not find the DSP signature file generation script"
+6 -4
View File
@@ -6,10 +6,12 @@ if /bin/ls /usr/lib/rfsa/adsp/testsig-*.so &> /dev/null; then
/bin/echo "Found DSP signature file"
else
/bin/echo "[WARNING] Could not find DSP signature file"
# Look for the DSP signature generation script
if [ -f /share/modalai/qrb5165-slpi-test-sig/generate-test-sig.sh ]; then
/bin/echo "[INFO] Attempting to generate the DSP signature file"
# Automatically generate the test signature so that px4 can run on SLPI DSP
# Look for the DSP signature generation script (platform-specific)
if [ -f /share/modalai/qcs6490-slpi-test-sig/generate-test-sig.sh ]; then
/bin/echo "[INFO] Attempting to generate the DSP signature file (qcs6490)"
/share/modalai/qcs6490-slpi-test-sig/generate-test-sig.sh
elif [ -f /share/modalai/qrb5165-slpi-test-sig/generate-test-sig.sh ]; then
/bin/echo "[INFO] Attempting to generate the DSP signature file (qrb5165)"
/share/modalai/qrb5165-slpi-test-sig/generate-test-sig.sh
else
/bin/echo "[ERROR] Could not find the DSP signature file generation script"
+25 -1
View File
@@ -302,4 +302,28 @@ done
# marked as optional will only be logged if they have been advertised when
# this is started. By starting it last it makes sure to see those
# advertisements as the other modules are starting before it.
logger start
#
# Set logger mode based on SDLOG_MODE parameter:
# 0: log when armed until disarm (default)
# 1: log from boot until disarm
# 2: log from boot until shutdown
# 3: log based on AUX1 RC channel
# 4: log from first armed until shutdown
LOGGER_ARGS=""
if param compare SDLOG_MODE 1
then
LOGGER_ARGS="-e"
fi
if param compare SDLOG_MODE 2
then
LOGGER_ARGS="-f"
fi
if param compare SDLOG_MODE 3
then
LOGGER_ARGS="-x"
fi
if param compare SDLOG_MODE 4
then
LOGGER_ARGS="-a"
fi
logger start $LOGGER_ARGS
@@ -2,7 +2,7 @@
#
# Stack: PX4 Pro
# Vehicle: Amovlab F410
# Version: 1.15.4
# Version: 1.15.4
# Git Revision: 99c40407ff000000
#
# Vehicle-Id Component-Id Name Value Type
@@ -479,11 +479,6 @@
1 1 EKF2_WIND_NSD 0.050000000745058060 9
1 1 EV_TSK_RC_LOSS 0 6
1 1 EV_TSK_STAT_DIS 0 6
1 1 FD_ACT_EN 1 6
1 1 FD_ACT_MOT_C2T 2.000000000000000000 9
1 1 FD_ACT_MOT_THR 0.200000002980232239 9
1 1 FD_ACT_MOT_TOUT 100 6
1 1 FD_ESCS_EN 1 6
1 1 FD_EXT_ATS_EN 0 6
1 1 FD_EXT_ATS_TRIG 1900 6
1 1 FD_FAIL_P 60 6
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because it is too large Load Diff
-1
View File
@@ -413,7 +413,6 @@ They recommend sensors, power systems, and other components from the same manufa
- [Holybro Pixhawk 6X Wiring Quickstart](../assembly/quick_start_pixhawk6x.md)
- [Holybro Pixhawk 5X Wiring Quickstart](../assembly/quick_start_pixhawk5x.md)
- [Holybro Pixhawk 4 Wiring Quickstart](../assembly/quick_start_pixhawk4.md)
- [Holybro Pixhawk 4 Mini (Discontinued) Wiring Quickstart](../assembly/quick_start_pixhawk4_mini.md)
- [Holybro Durandal Wiring Quickstart](../assembly/quick_start_durandal.md)
- [Holybro Pix32 v5 Wiring Quickstart](../assembly/quick_start_holybro_pix32_v5.md)
- [Cube Wiring Quickstart](../assembly/quick_start_cube.md) (All cube variants)
@@ -1,161 +0,0 @@
# _Pixhawk 4 Mini_ Wiring Quick Start
:::warning
PX4 does not manufacture this (or any) autopilot.
Contact the [manufacturer](https://holybro.com/) for hardware support or compliance issues.
:::
This quick start guide shows how to power the [_Pixhawk<sup>&reg;</sup> 4 Mini_](../flight_controller/pixhawk4_mini.md) flight controller and connect its most important peripherals.
![Pixhawk4 mini](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_iso_1.png)
## Wiring Chart Overview
The image below shows where to connect the most important sensors and peripherals (except for motors and servos).
![*Pixhawk 4 Mini* Wiring Overview](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_wiring_overview.png)
:::tip
More information about available ports can be found here: [_Pixhawk 4 Mini_ > Interfaces](../flight_controller/pixhawk4_mini.md#interfaces).
:::
## Mount and Orient Controller
_Pixhawk 4 Mini_ should be mounted on your frame using vibration-damping foam pads (included in the kit).
It should be positioned as close to your vehicles center of gravity as possible, oriented top-side up with the arrow pointing towards the front of the vehicle.
![*Pixhawk 4 Mini* Orientation](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_orientation.png)
::: info
If the controller cannot be mounted in the recommended/default orientation (e.g. due to space constraints) you will need to configure the autopilot software with the orientation that you actually used: [Flight Controller Orientation](../config/flight_controller_orientation.md).
:::
## GPS + Compass + Buzzer + Safety Switch + LED
Attach the provided GPS with integrated compass, safety switch, buzzer, and LED to the **GPS MODULE** port. The GPS/Compass should be [mounted on the frame](../assembly/mount_gps_compass.md) as far away from other electronics as possible, with the direction marker towards the front of the vehicle (separating the compass from other electronics will reduce interference).
![Connect compass/GPS to Pixhawk 4](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_gps.png)
::: info
The GPS module's integrated safety switch is enabled _by default_ (when enabled, PX4 will not let you arm the vehicle).
To disable the safety press and hold the safety switch for 1 second.
You can press the safety switch again to enable safety and disarm the vehicle (this can be useful if, for whatever reason, you are unable to disarm the vehicle from your remote control or ground station).
:::
## Power
The Power Management Board (PMB) serves the purpose of a power module as well as a power distribution board.
In addition to providing regulated power to _Pixhawk 4 Mini_ and the ESCs, it sends information to the autopilot about the batterys voltage and current draw.
Connect the output of the PMB that comes with the kit to the **POWER** port of the _Pixhawk 4 Mini_ using a 6-wire cable.
The connections of the PMB, including power supply and signal connections to the ESCs and servos, are explained in the image below.
![Pixhawk 4 - Power Management Board](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_power_management.png)
::: info
The image above only shows the connection of a single ESC and a single servo.
Connect the remaining ESCs and servos similarly.
:::
| Pin(s) or Connector | Function |
| ------------------- | -------------------------------------------------------------------------- |
| B+ | Connect to ESC B+ to power the ESC |
| GND | Connect to ESC Ground |
| PWR | JST-GH 6-pin Connector, 5V 3A output<br> connect to _Pixhawk 4 Mini_ POWER |
| BAT | Power Input, connect to 2~12s LiPo Battery |
The pinout of the _Pixhawk 4 Mini_ **POWER** port is shown below.
The `CURRENT` signal should carry an analog voltage from 0-3.3V for 0-120A as default.
The `VOLTAGE` signal should carry an analog voltage from 0-3.3V for 0-60V as default.
The VCC lines have to offer at least 3A continuous and should default to 5.1V. A lower voltage of 5V is still acceptable, but discouraged.
| Pin | Signal | Volt |
| -------- | ------- | ----- |
| 1(red) | VCC | +5V |
| 2(black) | VCC | +5V |
| 3(black) | CURRENT | +3.3V |
| 4(black) | VOLTAGE | +3.3V |
| 5(black) | GND | GND |
| 6(black) | GND | GND |
::: info
If using a plane or rover, the 8 pin power (+) rail of **MAIN OUT** will need to be separately powered in order to drive servos for rudders, elevons, etc.
To do this, the power rail needs to be connected to a BEC equipped ESC, a standalone 5V BEC, or a 2S LiPo battery.
Be careful with the voltage of servo you are going to use here.
:::
<!--In the future, when Pixhawk 4 kit is available, add wiring images/videos for different airframes.-->
::: info
Using the Power Module that comes with the kit you will need to configure the _Number of Cells_ in the [Power Settings](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/setup_view/power.html) but you won't need to calibrate the _voltage divider_.
You will have to update the _voltage divider_ if you are using any other power module (e.g. the one from the Pixracer).
:::
## Radio Control
A remote control (RC) radio system is required if you want to _manually_ control your vehicle (PX4 does not require a radio system for autonomous flight modes).
You will need to [select a compatible transmitter/receiver](../getting_started/rc_transmitter_receiver.md) and then _bind_ them so that they communicate (read the instructions that come with your specific transmitter/receiver).
The instructions below show how to connect the different types of receivers to _Pixhawk 4 Mini_:
- Spektrum/DSM or S.BUS receivers connect to the **DSM/SBUS RC** input.
![Pixhawk 4 Mini - Radio port for Spektrum receivers](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_rc_dsmsbus.png)
- PPM receivers connect to the **PPM RC** input port.
![Pixhawk 4 Mini - Radio port for PPM receivers](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_rc_ppm.png)
- PPM and PWM receivers that have an _individual wire for each channel_ must connect to the **PPM RC** port _via a PPM encoder_ [like this one](https://www.getfpv.com/radios/radio-accessories/holybro-ppm-encoder-module.html) (PPM-Sum receivers use a single signal wire for all channels).
For more information about selecting a radio system, receiver compatibility, and binding your transmitter/receiver pair, see: [Remote Control Transmitters & Receivers](../getting_started/rc_transmitter_receiver.md).
## Telemetry Radio (Optional)
Telemetry radios may be used to communicate and control a vehicle in flight from a ground station (for example, you can direct the UAV to a particular position, or upload a new mission).
The vehicle-based radio should be connected to the **TELEM1** port as shown below (if connected to this port, no further configuration is required).
The other radio is connected to your ground station computer or mobile device (usually by USB).
![Pixhawk 4 Mini Telemetry](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_telemetry.png)
## microSD Card (Optional)
SD cards are highly recommended as they are needed to [log and analyse flight details](../getting_started/flight_reporting.md), to run missions, and to use UAVCAN-bus hardware.
Insert the card (included in the kit) into _Pixhawk 4 Mini_ as shown below.
![Pixhawk 4 Mini SD Card](../../assets/flight_controller/pixhawk4mini/pixhawk4mini_sdcard.png)
:::tip
For more information see [Basic Concepts > SD Cards (Removable Memory)](../getting_started/px4_basic_concepts.md#sd-cards-removable-memory).
:::
## Motors
Motors/servos are connected to the **MAIN OUT** ports in the order specified for your vehicle in the [Airframe Reference](../airframes/airframe_reference.md). See [_Pixhawk 4 Mini_ > Supported Platforms](../flight_controller/pixhawk4_mini.md#supported-platforms) for more information.
::: info
This reference lists the output port to motor/servo mapping for all supported air and ground frames (if your frame is not listed in the reference then use a "generic" airframe of the correct type).
:::
:::warning
The mapping is not consistent across frames (e.g. you can't rely on the throttle being on the same output for all plane frames).
Make sure to use the correct mapping for your vehicle.
:::
## Other Peripherals
The wiring and configuration of optional/less common components is covered within the topics for individual [peripherals](../peripherals/index.md).
## Configuration
General configuration information is covered in: [Autopilot Configuration](../config/index.md).
QuadPlane specific configuration is covered here: [QuadPlane VTOL Configuration](../config_vtol/vtol_quad_configuration.md)
<!-- Nice to have detailed wiring infographic and instructions for different vehicle types. -->
## Further information
- [_Pixhawk 4 Mini_](../flight_controller/pixhawk4_mini.md)
@@ -28,7 +28,7 @@ In addition you will need:
The _Kopis 2_ comes preinstalled with Betaflight.
Before loading PX4 firmware you must first install the PX4 bootloader.
Instructions for installing the bootloader can be found in the [Kakute F7](../flight_controller/kakutef7.md#bootloader) topic (this is the flight controller board on the _Kopis 2_).
Download the [kakutef7_bl.hex](https://raw.githubusercontent.com/PX4/PX4-Autopilot/release/1.17/docs/assets/flight_controller/kakutef7/kakutef7_bl_0b3fbe2da0.hex?download=true) bootloader binary and read [PX4 Bootloader Flashing onto Betaflight Systems](../advanced_config/bootloader_update_from_betaflight.md) for flashing instructions.
:::tip
You can always [reinstall Betaflight](../advanced_config/bootloader_update_from_betaflight.md#reinstall-betaflight) later if you want!
+3 -9
View File
@@ -23,16 +23,10 @@ The sections below outline/link to the wiring and system console information for
### Board-Specific Wiring
The System Console UART pinouts/debug ports are typically documented in [autopilot overview pages](../flight_controller/index.md) (some are linked below):
The System Console UART pinouts/debug ports are typically documented in the affected [autopilot overview pages](../flight_controller/index.md).
For example, see [mRo Pixhawk](../flight_controller/mro_pixhawk.md#console-port) and [Pixracer](../flight_controller/pixracer.md#debug-port).
- [3DR Pixhawk v1 Flight Controller](../flight_controller/pixhawk.md#console-port) (also applies to
[mRo Pixhawk](../flight_controller/mro_pixhawk.md#debug-ports), [Holybro pix32](../flight_controller/holybro_pix32.md#debug-port))
- [Pixhawk 3](../flight_controller/pixhawk3_pro.md#debug-port)
- [Pixracer](../flight_controller/pixracer.md#debug-port)
<a id="pixhawk_debug_port"></a>
### Pixhawk Debug Port
### Pixhawk Debug Port {#pixhawk_debug_port}
Pixhawk flight controllers usually come with a [Pixhawk Connector Standard Debug Port](../debug/swd_debug.md#pixhawk-connector-standard-debug-ports) which will be either the 10 pin [Pixhawk Debug Full](../debug/swd_debug.md#pixhawk-debug-full) or 6 pin [Pixhawk Debug Mini](../debug/swd_debug.md#pixhawk-debug-mini) port.
@@ -14,10 +14,11 @@ They are listed because you may be using them in an existing drone, and because
- _CUAV Pixhack v3_ (FMUv3) — last published in [PX4 v1.15](https://docs.px4.io/v1.15/en/flight_controller/pixhack_v3) <!-- 202603 removed doc -->
- _Aerotenna OcPoC-Zynq Mini_ — last published in [PX4v1.11](https://docs.px4.io/v1.11/en/flight_controller/ocpoc_zynq#aerotenna-ocpoc-zynq-mini-flight-controller) <!-- 202603 removed doc -->
- _Holybro Pixhawk 4 Mini_ (FMUv5) -— last published in [PX4 v1.16](https://docs.px4.io/v1.16/en/flight_controller/pixhawk4_mini) <!-- 202603 removed doc -->
- _Holybro Kakute F7_ — last published in [PX4 v1.15](https://docs.px4.io/v1.15/en/flight_controller/kakutef7) <!-- 202603 removed doc -->
- _Holybro Pixhawk Mini_ (FMUv3) — last published in [PX4 v1.15](https://docs.px4.io/v1.15/en/flight_controller/pixhawk_mini) <!-- 202603 removed doc -->
- _Holybro Kakute F7_ — Marked as discontinued in PX4 v1.15.
Last published in [PX4 v1.17](https://docs.px4.io/v1.17/en/flight_controller/kakutef7). <!-- 202603 removed doc -->
- _Holybro Pixhawk Mini_ (FMUv3) — last published in [PX4 v1.16](https://docs.px4.io/v1.16/en/flight_controller/pixhawk_mini) <!-- 202603 removed doc -->
- _Holybro Pixfalcon_ (Pixhawk FMUv2) — last published in [PX4 v1.16](https://docs.px4.io/v1.16/en/flight_controller/pixfalcon) <!-- Discontinued around v1.15/2024. -->
- _Holybro Pix32_ (FMUv2) — last published in [PX4 v1.15](https://docs.px4.io/v1.15/en/flight_controller/holybro_pix32) <!-- 202603 removed doc -->
- _Holybro Pix32_ (FMUv2) — last published in [PX4 v1.16](https://docs.px4.io/v1.16/en/flight_controller/holybro_pix32) <!-- 202603 removed doc -->
- _ModalAI VOXL Flight_ — last published in [PX4 v1.16](https://docs.px4.io/v1.16/en/flight_controller/modalai_voxl_flight) <!-- 202603 removed doc -->
- _ModalAI Flight Core v1_ — last published in [PX4 v1.11](https://docs.px4.io/v1.11/en/flight_controller/modalai_fc_v1) <!-- 202603 removed doc -->
- _mRobotics-X2.1_ (FMUv2) — last published in [PX4 v1.16](https://docs.px4.io/v1.16/en/flight_controller/mro_x2.1) <!-- 202507 removed doc -->
+163 -2
View File
@@ -75,11 +75,172 @@ make px4_fmu-v3_default
## Debug Ports
See [3DR Pixhawk 1 > Debug Ports](../flight_controller/pixhawk.md#debug-ports)
### Console Port
The [PX4 System Console](../debug/system_console.md) runs on the port labeled [SERIAL4/5](#serial-4-5-port).
::: tip
A convenient way to connect to the console is to use a [Zubax BugFace BF1](https://github.com/Zubax/bugface_bf1), as it comes with connectors that can be used with several different Pixhawk devices.
Simply connect the 6-pos DF13 1:1 cable on the [Zubax BugFace BF1](https://github.com/Zubax/bugface_bf1) to the Pixhawk `SERIAL4/5` port.
![Zubax BugFace BF1](../../assets/flight_controller/mro/dronecode_probe.jpg)
:::
The pinout is standard serial pinout, designed to connect to a [3.3V FTDI](https://www.digikey.com/en/products/detail/TTL-232R-3V3/768-1015-ND/1836393) cable (5V tolerant).
| 3DR Pixhawk 1 | | FTDI | |
| ------------- | --------- | ---- | ---------------- |
| 1 | +5V (red) | | N/C |
| 2 | S4 Tx | | N/C |
| 3 | S4 Rx | | N/C |
| 4 | S5 Tx | 5 | FTDI RX (yellow) |
| 5 | S5 Rx | 4 | FTDI TX (orange) |
| 6 | GND | 1 | FTDI GND (black) |
The wiring for an FTDI cable to a 6-pos DF13 1:1 connector is shown in the figure below.
![Console Connector](../../assets/flight_controller/mro/console_connector.jpg)
The complete wiring is shown below.
![Console Debug](../../assets/flight_controller/mro/console_debug.jpg)
::: info
For information on how to _use_ the console see: [System Console](../debug/system_console.md).
:::
### SWD Port
The [SWD](../debug/swd_debug.md) (JTAG) ports are hidden under the cover (which must be removed for hardware debugging).
There are separate ports for FMU and IO, as highlighted below.
![Pixhawk SWD](../../assets/flight_controller/mro/pixhawk_swd.jpg)
The ports are ARM 10-pin JTAG connectors, which you will probably have to solder.
The pinout for the ports is shown below (the square markers in the corners above indicates pin 1).
![ARM 10-Pin connector pinout](../../assets/flight_controller/mro/arm_10pin_jtag_connector_pinout.jpg)
::: info
All Pixhawk FMUv2 boards have a similar SWD port.
:::
## Pinouts
See [3DR Pixhawk 1 > Pinouts](../flight_controller/pixhawk.md#pinouts)
#### TELEM1, TELEM2 ports
| Pin | Signal | Volt |
| ------- | --------- | ----- |
| 1 (red) | VCC | +5V |
| 2 (blk) | TX (OUT) | +3.3V |
| 3 (blk) | RX (IN) | +3.3V |
| 4 (blk) | CTS (IN) | +3.3V |
| 5 (blk) | RTS (OUT) | +3.3V |
| 6 (blk) | GND | GND |
#### GPS port
| Pin | Signal | Volt |
| ------- | -------- | ----- |
| 1 (red) | VCC | +5V |
| 2 (blk) | TX (OUT) | +3.3V |
| 3 (blk) | RX (IN) | +3.3V |
| 4 (blk) | CAN2 TX | +3.3V |
| 5 (blk) | CAN2 RX | +3.3V |
| 6 (blk) | GND | GND |
#### SERIAL 4/5 port
Due to space constraints two ports are on one connector.
| Pin | Signal | Volt |
| ------- | ------- | ----- |
| 1 (red) | VCC | +5V |
| 2 (blk) | TX (#4) | +3.3V |
| 3 (blk) | RX (#4) | +3.3V |
| 4 (blk) | TX (#5) | +3.3V |
| 5 (blk) | RX (#5) | +3.3V |
| 6 (blk) | GND | GND |
#### ADC 6.6V
| Pin | Signal | Volt |
| ------- | ------ | ----------- |
| 1 (red) | VCC | +5V |
| 2 (blk) | ADC IN | up to +6.6V |
| 3 (blk) | GND | GND |
#### ADC 3.3V
| Pin | Signal | Volt |
| ------- | ------ | ----------- |
| 1 (red) | VCC | +5V |
| 2 (blk) | ADC IN | up to +3.3V |
| 3 (blk) | GND | GND |
| 4 (blk) | ADC IN | up to +3.3V |
| 5 (blk) | GND | GND |
#### I2C
| Pin | Signal | Volt |
| ------- | ------ | -------------- |
| 1 (red) | VCC | +5V |
| 2 (blk) | SCL | +3.3 (pullups) |
| 3 (blk) | SDA | +3.3 (pullups) |
| 4 (blk) | GND | GND |
#### CAN
| Pin | Signal | Volt |
| ------- | ------ | ---- |
| 1 (red) | VCC | +5V |
| 2 (blk) | CAN_H | +12V |
| 3 (blk) | CAN_L | +12V |
| 4 (blk) | GND | GND |
#### SPI
| Pin | Signal | Volt |
| ------- | ------------ | ---- |
| 1 (red) | VCC | +5V |
| 2 (blk) | SPI_EXT_SCK | +3.3 |
| 3 (blk) | SPI_EXT_MISO | +3.3 |
| 4 (blk) | SPI_EXT_MOSI | +3.3 |
| 5 (blk) | !SPI_EXT_NSS | +3.3 |
| 6 (blk) | !GPIO_EXT | +3.3 |
| 7 (blk) | GND | GND |
#### POWER
| Pin | Signal | Volt |
| ------- | ------- | ----- |
| 1 (red) | VCC | +5V |
| 2 (blk) | VCC | +5V |
| 3 (blk) | CURRENT | +3.3V |
| 4 (blk) | VOLTAGE | +3.3V |
| 5 (blk) | GND | GND |
| 6 (blk) | GND | GND |
#### SWITCH
| Pin | Signal | Volt |
| ------- | -------------- | ----- |
| 1 (red) | VCC | +3.3V |
| 2 (blk) | !IO_LED_SAFETY | GND |
| 3 (blk) | SAFETY | GND |
## Serial Port Mapping
| UART | Device | Port |
| ------ | ---------- | --------------------- |
| UART1 | /dev/ttyS0 | IO debug |
| USART2 | /dev/ttyS1 | TELEM1 (flow control) |
| USART3 | /dev/ttyS2 | TELEM2 (flow control) |
| UART4 | |
| UART7 | CONSOLE |
| UART8 | SERIAL4 |
<!-- Note: Got ports using https://github.com/PX4/PX4-user_guide/pull/672#issuecomment-598198434 -->
## Serial Port Mapping
+3 -3
View File
@@ -93,8 +93,8 @@ Order from [Holybro](https://holybro.com/products/pixhawk-6c-mini).
## Assembly/Setup
The Pixhawk 4 Mini's port is very similar to the Pixhawk 6C Mini's port.
Please refer to the [Pixhawk 4 Mini Wiring Quick Start](../assembly/quick_start_pixhawk4_mini.md) as it provides instructions on how to assemble required/important peripherals including GPS, Power Module etc.
The Pixhawk 6C Mini's ports are very similar to the Pixhawk 4 Mini's ports.
Please refer to the [Pixhawk 4 Mini Wiring Quick Start](https://docs.px4.io/v1.16/en/assembly/quick_start_pixhawk4_mini) (Discontinued) as it provides instructions on how to assemble required/important peripherals including GPS, Power Module etc.
## Pinouts
@@ -199,7 +199,7 @@ The complete set of supported configurations can be seen in the [Airframes Refer
## See Also
- [Holybro Docs](https://docs.holybro.com/) (Holybro)
- [Pixhawk 4 Mini Wiring Quick Start](../assembly/quick_start_pixhawk4_mini.md) (and [Pixhawk 6C Wiring QuickStart](../assembly/quick_start_pixhawk6c.md))
- [Pixhawk 6C Wiring QuickStart](../assembly/quick_start_pixhawk6c.md)
- [PM02 Power Module](../power_module/holybro_pm02.md)
- [PM06 Power Module](../power_module/holybro_pm06_pixhawk4mini_power_module.md)
- [PM07 Power Module](../power_module/holybro_pm07_pixhawk4_power_module.md)
@@ -169,7 +169,7 @@ As we have no ground or positive BEC voltage connections we connect our `PWM` ES
### GPS / External Magnetometer
I took the GPS cable which fits the connector of the used GPS and came with the Pixracer set.
Sadly the pin assignment was completely wrong and I rewired the connector again using tweezers according to the [3DR Pixhawk Mini user manual](../flight_controller/pixhawk_mini.md#connector-pin-assignments-pin-outs) GPS port.
Sadly the pin assignment was completely wrong and I rewired the connector again using tweezers according to the [3DR Pixhawk Mini user manual](https://docs.px4.io/v1.16/en/flight_controller/pixhawk_mini#connector-pin-assignments-pin-outs) GPS port.
#### Pixracer GPS/I2C Port
+188 -188
View File
@@ -95,202 +95,202 @@ They are not build into the module, and hence are neither published or subscribe
::: details See messages
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
- [RcParameterMap](../msg_docs/RcParameterMap.md)
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
- [IrlockReport](../msg_docs/IrlockReport.md)
- [PowerButtonState](../msg_docs/PowerButtonState.md)
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
- [MavlinkLog](../msg_docs/MavlinkLog.md)
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
- [InputRc](../msg_docs/InputRc.md)
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
- [TuneControl](../msg_docs/TuneControl.md)
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md)
- [SatelliteInfo](../msg_docs/SatelliteInfo.md)
- [DebugArray](../msg_docs/DebugArray.md)
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
- [VehicleImu](../msg_docs/VehicleImu.md)
- [EstimatorBias](../msg_docs/EstimatorBias.md)
- [QshellReq](../msg_docs/QshellReq.md)
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
- [GpioRequest](../msg_docs/GpioRequest.md)
- [Airspeed](../msg_docs/Airspeed.md)
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md)
- [Rpm](../msg_docs/Rpm.md)
- [Mission](../msg_docs/Mission.md)
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
- [DatamanRequest](../msg_docs/DatamanRequest.md)
- [Gripper](../msg_docs/Gripper.md)
- [SystemPower](../msg_docs/SystemPower.md)
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
- [ActionRequest](../msg_docs/ActionRequest.md)
- [MissionResult](../msg_docs/MissionResult.md)
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
- [LedControl](../msg_docs/LedControl.md)
- [SensorAirflow](../msg_docs/SensorAirflow.md)
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
- [GpsDump](../msg_docs/GpsDump.md)
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
- [SensorGyro](../msg_docs/SensorGyro.md)
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
- [SensorSelection](../msg_docs/SensorSelection.md)
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
- [RaptorInput](../msg_docs/RaptorInput.md)
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md)
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
- [RadioStatus](../msg_docs/RadioStatus.md)
- [ButtonEvent](../msg_docs/ButtonEvent.md)
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
- [FollowTarget](../msg_docs/FollowTarget.md)
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
- [PowerMonitor](../msg_docs/PowerMonitor.md)
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
- [NeuralControl](../msg_docs/NeuralControl.md)
- [TecsStatus](../msg_docs/TecsStatus.md)
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
- [GeofenceResult](../msg_docs/GeofenceResult.md)
- [AirspeedWind](../msg_docs/AirspeedWind.md)
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
- [Cpuload](../msg_docs/Cpuload.md)
- [SensorCorrection](../msg_docs/SensorCorrection.md)
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
- [SensorAccel](../msg_docs/SensorAccel.md)
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
- [AdcReport](../msg_docs/AdcReport.md)
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
- [DatamanResponse](../msg_docs/DatamanResponse.md)
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
- [GainCompression](../msg_docs/GainCompression.md)
- [HeaterStatus](../msg_docs/HeaterStatus.md)
- [VehicleGlobalPositionV0](../msg_docs/VehicleGlobalPositionV0.md)
- [VehicleRoi](../msg_docs/VehicleRoi.md)
- [RtlStatus](../msg_docs/RtlStatus.md)
- [EstimatorStates](../msg_docs/EstimatorStates.md)
- [Event](../msg_docs/Event.md)
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
- [MagWorkerData](../msg_docs/MagWorkerData.md)
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
- [GpioConfig](../msg_docs/GpioConfig.md)
- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md)
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
- [LandingTargetPose](../msg_docs/LandingTargetPose.md)
- [DebugValue](../msg_docs/DebugValue.md)
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
- [WheelEncoders](../msg_docs/WheelEncoders.md)
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
- [CameraStatus](../msg_docs/CameraStatus.md)
- [LogMessage](../msg_docs/LogMessage.md)
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
- [GpioOut](../msg_docs/GpioOut.md)
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
- [SensorMag](../msg_docs/SensorMag.md)
- [QshellRetval](../msg_docs/QshellRetval.md)
- [SensorTemp](../msg_docs/SensorTemp.md)
- [DebugVect](../msg_docs/DebugVect.md)
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
- [ActuatorTest](../msg_docs/ActuatorTest.md)
- [VelocityLimits](../msg_docs/VelocityLimits.md)
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
- [SensorBaro](../msg_docs/SensorBaro.md)
- [Ping](../msg_docs/Ping.md)
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
- [UlogStream](../msg_docs/UlogStream.md)
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md)
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
- [SensorUwb](../msg_docs/SensorUwb.md)
- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md)
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
- [SensorsStatus](../msg_docs/SensorsStatus.md)
- [BatteryInfo](../msg_docs/BatteryInfo.md)
- [EscReport](../msg_docs/EscReport.md)
- [LoggerStatus](../msg_docs/LoggerStatus.md)
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
- [SensorAirflow](../msg_docs/SensorAirflow.md)
- [UlogStream](../msg_docs/UlogStream.md)
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
- [ParameterUpdate](../msg_docs/ParameterUpdate.md)
- [Vtx](../msg_docs/Vtx.md)
- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md)
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md)
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
- [RaptorStatus](../msg_docs/RaptorStatus.md)
- [GimbalControls](../msg_docs/GimbalControls.md)
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
- [VehicleAirData](../msg_docs/VehicleAirData.md)
- [CameraCapture](../msg_docs/CameraCapture.md)
- [EscStatus](../msg_docs/EscStatus.md)
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
- [EstimatorStates](../msg_docs/EstimatorStates.md)
- [CellularStatus](../msg_docs/CellularStatus.md)
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
- [DatamanResponse](../msg_docs/DatamanResponse.md)
- [AirspeedWind](../msg_docs/AirspeedWind.md)
- [QshellReq](../msg_docs/QshellReq.md)
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
- [TuneControl](../msg_docs/TuneControl.md)
- [VehicleRoi](../msg_docs/VehicleRoi.md)
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
- [EventV0](../msg_docs/EventV0.md)
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
- [VehicleCommandAckV0](../msg_docs/VehicleCommandAckV0.md)
- [FigureEightStatus](../msg_docs/FigureEightStatus.md)
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
- [OrbitStatus](../msg_docs/OrbitStatus.md)
- [PwmInput](../msg_docs/PwmInput.md)
- [PpsCapture](../msg_docs/PpsCapture.md)
- [GeofenceResult](../msg_docs/GeofenceResult.md)
- [HomePositionV0](../msg_docs/HomePositionV0.md)
- [HealthReport](../msg_docs/HealthReport.md)
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md)
- [MagWorkerData](../msg_docs/MagWorkerData.md)
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
- [HeaterStatus](../msg_docs/HeaterStatus.md)
- [EstimatorBias](../msg_docs/EstimatorBias.md)
- [FigureEightStatus](../msg_docs/FigureEightStatus.md)
- [MissionResult](../msg_docs/MissionResult.md)
- [GpioOut](../msg_docs/GpioOut.md)
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
- [SensorMag](../msg_docs/SensorMag.md)
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md)
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
- [Ping](../msg_docs/Ping.md)
- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md)
- [ActuatorTest](../msg_docs/ActuatorTest.md)
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
- [PpsCapture](../msg_docs/PpsCapture.md)
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
- [PowerButtonState](../msg_docs/PowerButtonState.md)
- [GpsInjectData](../msg_docs/GpsInjectData.md)
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
- [VelocityLimits](../msg_docs/VelocityLimits.md)
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
- [SatelliteInfo](../msg_docs/SatelliteInfo.md)
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
- [LedControl](../msg_docs/LedControl.md)
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
- [MountOrientation](../msg_docs/MountOrientation.md)
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
- [VehicleStatusV1](../msg_docs/VehicleStatusV1.md)
- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md)
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
- [RcChannels](../msg_docs/RcChannels.md)
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
- [RtlStatus](../msg_docs/RtlStatus.md)
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
- [OrbTest](../msg_docs/OrbTest.md)
- [MountOrientation](../msg_docs/MountOrientation.md)
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
- [GpsInjectData](../msg_docs/GpsInjectData.md)
- [CameraTrigger](../msg_docs/CameraTrigger.md)
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
- [GpioIn](../msg_docs/GpioIn.md)
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
- [DeviceInformation](../msg_docs/DeviceInformation.md)
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md)
- [SensorGyro](../msg_docs/SensorGyro.md)
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
- [BatteryInfo](../msg_docs/BatteryInfo.md)
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
- [VehicleCommandAckV0](../msg_docs/VehicleCommandAckV0.md)
- [SensorUwb](../msg_docs/SensorUwb.md)
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
- [OrbitStatus](../msg_docs/OrbitStatus.md)
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
- [SensorCorrection](../msg_docs/SensorCorrection.md)
- [Mission](../msg_docs/Mission.md)
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
- [GpioRequest](../msg_docs/GpioRequest.md)
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
- [SensorBaro](../msg_docs/SensorBaro.md)
- [SensorAccel](../msg_docs/SensorAccel.md)
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
- [Gripper](../msg_docs/Gripper.md)
- [IrlockReport](../msg_docs/IrlockReport.md)
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
- [Airspeed](../msg_docs/Airspeed.md)
- [Event](../msg_docs/Event.md)
- [PwmInput](../msg_docs/PwmInput.md)
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
- [Cpuload](../msg_docs/Cpuload.md)
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
- [RcChannels](../msg_docs/RcChannels.md)
- [VehicleAirData](../msg_docs/VehicleAirData.md)
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
- [VehicleImu](../msg_docs/VehicleImu.md)
- [ButtonEvent](../msg_docs/ButtonEvent.md)
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
- [GainCompression](../msg_docs/GainCompression.md)
- [ActionRequest](../msg_docs/ActionRequest.md)
- [VehicleGlobalPositionV0](../msg_docs/VehicleGlobalPositionV0.md)
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
- [GpioConfig](../msg_docs/GpioConfig.md)
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
- [HealthReport](../msg_docs/HealthReport.md)
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
- [DatamanRequest](../msg_docs/DatamanRequest.md)
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
- [MavlinkLog](../msg_docs/MavlinkLog.md)
- [CameraCapture](../msg_docs/CameraCapture.md)
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
- [EscReport](../msg_docs/EscReport.md)
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
- [DebugKeyValue](../msg_docs/DebugKeyValue.md)
- [DebugValue](../msg_docs/DebugValue.md)
- [GpioIn](../msg_docs/GpioIn.md)
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
- [LandingTargetPose](../msg_docs/LandingTargetPose.md)
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md)
- [GpsDump](../msg_docs/GpsDump.md)
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
- [SystemPower](../msg_docs/SystemPower.md)
- [NeuralControl](../msg_docs/NeuralControl.md)
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
- [SensorTemp](../msg_docs/SensorTemp.md)
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
- [TecsStatus](../msg_docs/TecsStatus.md)
- [WheelEncoders](../msg_docs/WheelEncoders.md)
- [RadioStatus](../msg_docs/RadioStatus.md)
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
- [FollowTarget](../msg_docs/FollowTarget.md)
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
- [GimbalControls](../msg_docs/GimbalControls.md)
- [RaptorStatus](../msg_docs/RaptorStatus.md)
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
- [SensorsStatus](../msg_docs/SensorsStatus.md)
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
- [InputRc](../msg_docs/InputRc.md)
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
- [DeviceInformation](../msg_docs/DeviceInformation.md)
- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md)
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
- [QshellRetval](../msg_docs/QshellRetval.md)
- [AdcReport](../msg_docs/AdcReport.md)
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
- [CameraTrigger](../msg_docs/CameraTrigger.md)
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
- [PowerMonitor](../msg_docs/PowerMonitor.md)
- [RcParameterMap](../msg_docs/RcParameterMap.md)
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md)
- [SensorSelection](../msg_docs/SensorSelection.md)
- [Vtx](../msg_docs/Vtx.md)
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
- [DebugArray](../msg_docs/DebugArray.md)
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
- [DebugVect](../msg_docs/DebugVect.md)
- [RaptorInput](../msg_docs/RaptorInput.md)
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
- [EscStatus](../msg_docs/EscStatus.md)
- [LoggerStatus](../msg_docs/LoggerStatus.md)
- [Rpm](../msg_docs/Rpm.md)
- [LogMessage](../msg_docs/LogMessage.md)
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
- [CameraStatus](../msg_docs/CameraStatus.md)
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
:::
+6 -6
View File
@@ -22,11 +22,11 @@ Published by the vehicle's allocation and consumed by the ESC protocol drivers e
## Constants
| Name | Type | Value | Description |
| --------------------------------------------------------------- | -------- | ----- | ----------- |
| Name | Type | Value | Description |
| --------------------------------------------------------------- | -------- | ----- | --------------------------------- |
| <a id="#MESSAGE_VERSION"></a> MESSAGE_VERSION | `uint32` | 0 |
| <a id="#ACTUATOR_FUNCTION_MOTOR1"></a> ACTUATOR_FUNCTION_MOTOR1 | `uint8` | 101 |
| <a id="#NUM_CONTROLS"></a> NUM_CONTROLS | `uint8` | 12 |
| <a id="#ACTUATOR_FUNCTION_MOTOR1"></a> ACTUATOR_FUNCTION_MOTOR1 | `uint8` | 101 | output_functions.yaml Motor.start |
| <a id="#NUM_CONTROLS"></a> NUM_CONTROLS | `uint8` | 12 | output_functions.yaml Motor.count |
## Source Message
@@ -47,9 +47,9 @@ uint64 timestamp_sample # [us] Sampling timestamp of the data this control respo
uint16 reversible_flags # [-] Bitset indicating which motors are configured to be reversible
uint8 ACTUATOR_FUNCTION_MOTOR1 = 101
uint8 ACTUATOR_FUNCTION_MOTOR1 = 101 # output_functions.yaml Motor.start
uint8 NUM_CONTROLS = 12
uint8 NUM_CONTROLS = 12 # output_functions.yaml Motor.count
float32[12] control # [@range -1, 1] Normalized thrust. Where 1 means maximum positive thrust, -1 maximum negative (if not supported by the output, <0 maps to NaN). NaN maps to disarmed (stop the motors)
```
+2 -23
View File
@@ -29,17 +29,7 @@ pageClass: is-wide-page
| Name | Type | Value | Description |
| --------------------------------------------------------------------------- | ------- | ----- | ---------------------------------------------------------------------------- |
| <a id="#ACTUATOR_FUNCTION_MOTOR1"></a> ACTUATOR_FUNCTION_MOTOR1 | `uint8` | 101 |
| <a id="#ACTUATOR_FUNCTION_MOTOR2"></a> ACTUATOR_FUNCTION_MOTOR2 | `uint8` | 102 |
| <a id="#ACTUATOR_FUNCTION_MOTOR3"></a> ACTUATOR_FUNCTION_MOTOR3 | `uint8` | 103 |
| <a id="#ACTUATOR_FUNCTION_MOTOR4"></a> ACTUATOR_FUNCTION_MOTOR4 | `uint8` | 104 |
| <a id="#ACTUATOR_FUNCTION_MOTOR5"></a> ACTUATOR_FUNCTION_MOTOR5 | `uint8` | 105 |
| <a id="#ACTUATOR_FUNCTION_MOTOR6"></a> ACTUATOR_FUNCTION_MOTOR6 | `uint8` | 106 |
| <a id="#ACTUATOR_FUNCTION_MOTOR7"></a> ACTUATOR_FUNCTION_MOTOR7 | `uint8` | 107 |
| <a id="#ACTUATOR_FUNCTION_MOTOR8"></a> ACTUATOR_FUNCTION_MOTOR8 | `uint8` | 108 |
| <a id="#ACTUATOR_FUNCTION_MOTOR9"></a> ACTUATOR_FUNCTION_MOTOR9 | `uint8` | 109 |
| <a id="#ACTUATOR_FUNCTION_MOTOR10"></a> ACTUATOR_FUNCTION_MOTOR10 | `uint8` | 110 |
| <a id="#ACTUATOR_FUNCTION_MOTOR11"></a> ACTUATOR_FUNCTION_MOTOR11 | `uint8` | 111 |
| <a id="#ACTUATOR_FUNCTION_MOTOR12"></a> ACTUATOR_FUNCTION_MOTOR12 | `uint8` | 112 |
| <a id="#ACTUATOR_FUNCTION_MOTOR_MAX"></a> ACTUATOR_FUNCTION_MOTOR_MAX | `uint8` | 112 | output_functions.yaml Motor.start + Motor.count - 1 |
| <a id="#FAILURE_OVER_CURRENT"></a> FAILURE_OVER_CURRENT | `uint8` | 0 | (1 << 0) |
| <a id="#FAILURE_OVER_VOLTAGE"></a> FAILURE_OVER_VOLTAGE | `uint8` | 1 | (1 << 1) |
| <a id="#FAILURE_MOTOR_OVER_TEMPERATURE"></a> FAILURE_MOTOR_OVER_TEMPERATURE | `uint8` | 2 | (1 << 2) |
@@ -72,19 +62,8 @@ uint8 esc_cmdcount # Counter of number of commands
uint8 esc_state # State of ESC - depend on Vendor
uint8 actuator_function # actuator output function (one of Motor1...MotorN)
uint8 ACTUATOR_FUNCTION_MOTOR1 = 101
uint8 ACTUATOR_FUNCTION_MOTOR2 = 102
uint8 ACTUATOR_FUNCTION_MOTOR3 = 103
uint8 ACTUATOR_FUNCTION_MOTOR4 = 104
uint8 ACTUATOR_FUNCTION_MOTOR5 = 105
uint8 ACTUATOR_FUNCTION_MOTOR6 = 106
uint8 ACTUATOR_FUNCTION_MOTOR7 = 107
uint8 ACTUATOR_FUNCTION_MOTOR8 = 108
uint8 ACTUATOR_FUNCTION_MOTOR9 = 109
uint8 ACTUATOR_FUNCTION_MOTOR10 = 110
uint8 ACTUATOR_FUNCTION_MOTOR11 = 111
uint8 ACTUATOR_FUNCTION_MOTOR12 = 112
uint8 ACTUATOR_FUNCTION_MOTOR_MAX = 112 # output_functions.yaml Motor.start + Motor.count - 1
uint16 failures # Bitmask to indicate the internal ESC faults
int8 esc_power # Applied power 0-100 in % (negative values reserved)
@@ -26,6 +26,8 @@ This power module has integrated power distribution board and provides regulated
## Wiring/Connections
Wiring and connection examples can be found in: [Pixhawk 4 Mini > Power](../assembly/quick_start_pixhawk4_mini.md#power).
![pm06_pin_map](../../assets/hardware/power_module/holybro_pm06/pm06_pin_map.jpg)
<img src="../../assets/hardware/power_module/holybro_pm06/pm06_pin_map.jpg" width="450px" title="pm06" />
This image shows the wiring and connections for the [Pixhawk 4 Mini](https://docs.px4.io/v1.16/en/assembly/quick_start_pixhawk4_mini#power) (discontinued).
![Pixhawk 4 - Power Management Board](../../assets/hardware/power_module/holybro_pm06/pixhawk4mini_power_management.png)
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
+1 -12
View File
@@ -11,19 +11,8 @@ uint8 esc_cmdcount # Counter of number of commands
uint8 esc_state # State of ESC - depend on Vendor
uint8 actuator_function # actuator output function (one of Motor1...MotorN)
uint8 ACTUATOR_FUNCTION_MOTOR1 = 101
uint8 ACTUATOR_FUNCTION_MOTOR2 = 102
uint8 ACTUATOR_FUNCTION_MOTOR3 = 103
uint8 ACTUATOR_FUNCTION_MOTOR4 = 104
uint8 ACTUATOR_FUNCTION_MOTOR5 = 105
uint8 ACTUATOR_FUNCTION_MOTOR6 = 106
uint8 ACTUATOR_FUNCTION_MOTOR7 = 107
uint8 ACTUATOR_FUNCTION_MOTOR8 = 108
uint8 ACTUATOR_FUNCTION_MOTOR9 = 109
uint8 ACTUATOR_FUNCTION_MOTOR10 = 110
uint8 ACTUATOR_FUNCTION_MOTOR11 = 111
uint8 ACTUATOR_FUNCTION_MOTOR12 = 112
uint8 ACTUATOR_FUNCTION_MOTOR_MAX = 112 # output_functions.yaml Motor.start + Motor.count - 1
uint16 failures # Bitmask to indicate the internal ESC faults
int8 esc_power # Applied power 0-100 in % (negative values reserved)
+2 -2
View File
@@ -10,7 +10,7 @@ uint64 timestamp_sample # [us] Sampling timestamp of the data this control respo
uint16 reversible_flags # [-] Bitset indicating which motors are configured to be reversible
uint8 ACTUATOR_FUNCTION_MOTOR1 = 101
uint8 ACTUATOR_FUNCTION_MOTOR1 = 101 # output_functions.yaml Motor.start
uint8 NUM_CONTROLS = 12
uint8 NUM_CONTROLS = 12 # output_functions.yaml Motor.count
float32[12] control # [@range -1, 1] Normalized thrust. Where 1 means maximum positive thrust, -1 maximum negative (if not supported by the output, <0 maps to NaN). NaN maps to disarmed (stop the motors)
@@ -232,6 +232,9 @@ class SourceParser(object):
# start waiting for the next part - long comment.
if state == "wait-short-end":
state = "wait-long"
if state == "wait-long-end":
# Long description includes empty lines
long_desc += "\n"
else:
m = self.re_comment_tag.match(comment_content)
if m:
+1 -1
View File
@@ -2016,7 +2016,7 @@ void Commander::run()
_vehicle_status.timestamp = hrt_absolute_time();
_vehicle_status_pub.publish(_vehicle_status);
_failure_detector.publishStatus();
_failure_detector.publishStatus(_health_and_arming_checks.getEscArmStatus(), _health_and_arming_checks.getMotorFailureMask());
}
checkWorkerThread();
@@ -109,6 +109,9 @@ public:
const failsafe_flags_s &failsafeFlags() const { return _failsafe_flags; }
uint16_t getMotorFailureMask() const {return _esc_checks.getMotorFailureMask(); }
bool getEscArmStatus() const { return _esc_checks.getEscArmStatus(); }
#ifndef CONSTRAINED_FLASH
ExternalChecks &externalChecks() { return _external_checks; }
#endif
@@ -37,13 +37,13 @@ void ArmPermissionChecks::checkAndReport(const Context &context, Report &reporte
{
if (_param_com_armable.get() < 1) {
/* EVENT
* @description
* Vehicle is in safety configuration and denies arming.
*
* <profile name="dev">
* This check can be configured via <param>COM_ARMABLE</param> parameter.
* </profile>
*/
* @description
* Vehicle is in safety configuration and denies arming.
*
* <profile name="dev">
* This check can be configured via <param>COM_ARMABLE</param> parameter.
* </profile>
*/
reporter.armingCheckFailure(NavModes::All, health_component_t::system,
events::ID("check_armable_configuration"),
events::Log::Error, "Vehicle is in safety configuration");
@@ -211,13 +211,13 @@ void BatteryChecks::checkAndReport(const Context &context, Report &reporter)
// This is declared critical so QGC displays a yellow box and reads "low battery" out loud making the user aware
/* EVENT
* @description
* The lowest battery state of charge is below the low threshold.
*
* <profile name="dev">
* Can be configured with <param>BAT_LOW_THR</param>.
* </profile>
*/
* @description
* The lowest battery state of charge is below the low threshold.
*
* <profile name="dev">
* Can be configured with <param>BAT_LOW_THR</param>.
* </profile>
*/
reporter.armingCheckFailure(affected_modes, health_component_t::battery, events::ID("check_battery_low"),
events::Log::Critical, "Low battery");
@@ -229,13 +229,13 @@ void BatteryChecks::checkAndReport(const Context &context, Report &reporter)
case battery_status_s::WARNING_CRITICAL:
/* EVENT
* @description
* The lowest battery state of charge is below the critical threshold.
*
* <profile name="dev">
* Can be configured with <param>BAT_CRIT_THR</param> and from when to disalow arming with <param>COM_ARM_BAT_MIN</param>.
* </profile>
*/
* @description
* The lowest battery state of charge is below the critical threshold.
*
* <profile name="dev">
* Can be configured with <param>BAT_CRIT_THR</param> and from when to disalow arming with <param>COM_ARM_BAT_MIN</param>.
* </profile>
*/
reporter.armingCheckFailure(affected_modes, health_component_t::battery, events::ID("check_battery_critical"),
events::Log::Critical, "Critical battery");
@@ -247,13 +247,13 @@ void BatteryChecks::checkAndReport(const Context &context, Report &reporter)
case battery_status_s::WARNING_EMERGENCY:
/* EVENT
* @description
* The lowest battery state of charge is below the emergency threshold.
*
* <profile name="dev">
* Can be configured with <param>BAT_EMERGEN_THR</param>.
* </profile>
*/
* @description
* The lowest battery state of charge is below the emergency threshold.
*
* <profile name="dev">
* Can be configured with <param>BAT_EMERGEN_THR</param>.
* </profile>
*/
reporter.armingCheckFailure(affected_modes, health_component_t::battery, events::ID("check_battery_emergency"),
events::Log::Emergency, "Emergency battery level");
@@ -62,7 +62,6 @@ static constexpr const char *esc_fault_reason_str(esc_fault_reason_t esc_fault_r
case esc_fault_reason_t::esc_warn_temp: return "over temperature";
case esc_fault_reason_t::esc_over_temp: return "critical temperature";
}
return "";
@@ -72,19 +71,31 @@ static constexpr const char *esc_fault_reason_str(esc_fault_reason_t esc_fault_r
void EscChecks::checkAndReport(const Context &context, Report &reporter)
{
const hrt_abstime now = hrt_absolute_time();
const hrt_abstime esc_telemetry_timeout =
700_ms; // Some DShot ESCs are unresponsive for ~550ms during their initialization, so we use a timeout higher than that
esc_status_s esc_status;
if (_esc_status_sub.copy(&esc_status) && (now < esc_status.timestamp + esc_telemetry_timeout)) {
// Run motor status checks even when no new ESC data arrives (to detect timeouts)
if (_esc_status_sub.copy(&esc_status)) {
if (esc_status.esc_count <= 0) {
return;
}
checkEscStatus(context, reporter, esc_status);
uint16_t mask = 0;
if (_param_com_arm_chk_escs.get() > 0) {
mask |= checkEscOnline(context, reporter, esc_status, now);
mask |= checkEscStatus(context, reporter, esc_status);
}
if (_param_fd_act_en.get() > 0) {
updateEscsStatus(context, reporter, esc_status, now);
mask |= checkMotorStatus(context, reporter, esc_status, now);
}
_motor_failure_mask = mask;
reporter.setIsPresent(health_component_t::motors_escs);
reporter.failsafeFlags().fd_motor_failure = (mask != 0);
} else if (_param_com_arm_chk_escs.get()
&& now - _start_time > 5_s) { // Wait a bit after startup to allow esc's to init
} else if ((_param_com_arm_chk_escs.get() > 0) && now > _start_time + 3_s) { // Allow ESCs to init
/* EVENT
* @description
* <profile name="dev">
@@ -100,83 +111,240 @@ void EscChecks::checkAndReport(const Context &context, Report &reporter)
}
}
void EscChecks::checkEscStatus(const Context &context, Report &reporter, const esc_status_s &esc_status)
uint16_t EscChecks::checkEscOnline(const Context &context, Report &reporter, const esc_status_s &esc_status, hrt_abstime now)
{
const NavModes required_modes = _param_com_arm_chk_escs.get() ? NavModes::All : NavModes::None;
// Check if one or more the ESCs are offline
uint16_t mask = 0;
char esc_fail_msg[esc_status_s::CONNECTED_ESC_MAX * 6 + 1] = "";
if (esc_status.esc_count > 0) {
// Check if one or more the ESCs are offline
char esc_fail_msg[50];
esc_fail_msg[0] = '\0';
for (int esc_index = 0; esc_index < esc_status_s::CONNECTED_ESC_MAX; esc_index++) {
if (!math::isInRange(esc_status.esc[esc_index].actuator_function,
esc_report_s::ACTUATOR_FUNCTION_MOTOR1, esc_report_s::ACTUATOR_FUNCTION_MOTOR_MAX)) {
continue; // Skip unmapped ESC status entries
}
for (int i = 0; i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
const bool mapped = math::isInRange(esc_status.esc[i].actuator_function, actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1,
uint8_t(actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1 + actuator_motors_s::NUM_CONTROLS - 1));
const bool offline = (esc_status.esc_online_flags & (1 << i)) == 0;
const bool timeout = now > esc_status.esc[esc_index].timestamp + ESC_TIMEOUT_US;
const bool is_offline = (esc_status.esc_online_flags & (1 << esc_index)) == 0;
if (mapped && offline) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>COM_ARM_CHK_ESCS</param> parameter.
* </profile>
*/
reporter.healthFailure<uint8_t>(required_modes, health_component_t::motors_escs, events::ID("check_escs_offline"),
events::Log::Critical, "ESC {1} offline", i + 1);
snprintf(esc_fail_msg + strlen(esc_fail_msg), sizeof(esc_fail_msg) - strlen(esc_fail_msg), "ESC%d ", i + 1);
esc_fail_msg[sizeof(esc_fail_msg) - 1] = '\0';
// Set failure bits for this motor
if (timeout || is_offline) {
mask |= (1u << esc_index);
uint8_t esc_nr = esc_index + 1;
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>COM_ARM_CHK_ESCS</param> parameter.
* </profile>
*/
reporter.healthFailure<uint8_t>(NavModes::All, health_component_t::motors_escs, events::ID("check_escs_offline"),
events::Log::Critical, "ESC {1} offline", esc_nr);
snprintf(esc_fail_msg + strlen(esc_fail_msg), sizeof(esc_fail_msg) - strlen(esc_fail_msg), "ESC%d ", esc_nr);
esc_fail_msg[sizeof(esc_fail_msg) - 1] = '\0';
}
}
if (reporter.mavlink_log_pub() && esc_fail_msg[0] != '\0') {
mavlink_log_critical(reporter.mavlink_log_pub(), "%soffline. %s\t", esc_fail_msg, context.isArmed() ? "Land now!" : "");
}
return mask;
}
uint16_t EscChecks::checkEscStatus(const Context &context, Report &reporter, const esc_status_s &esc_status)
{
uint16_t mask = 0;
for (int esc_index = 0; esc_index < esc_status_s::CONNECTED_ESC_MAX; esc_index++) {
if (!math::isInRange(esc_status.esc[esc_index].actuator_function,
esc_report_s::ACTUATOR_FUNCTION_MOTOR1, esc_report_s::ACTUATOR_FUNCTION_MOTOR_MAX)) {
continue; // Skip unmapped ESC status entries
}
const uint8_t actuator_function_index = esc_status.esc[esc_index].actuator_function - esc_report_s::ACTUATOR_FUNCTION_MOTOR1;
if (esc_status.esc[esc_index].failures == 0) {
continue;
} else {
mask |= (1u << actuator_function_index); // Set bit in mask
}
for (uint8_t fault_index = 0; fault_index <= static_cast<uint8_t>(esc_fault_reason_t::_max); fault_index++) {
if (!(esc_status.esc[esc_index].failures & (1 << fault_index))) {
continue;
}
}
if ((esc_fail_msg[0] != '\0') && reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "%soffline. %s\t", esc_fail_msg, context.isArmed() ? "Land now!" : "");
}
esc_fault_reason_t fault_reason_index = static_cast<esc_fault_reason_t>(fault_index);
const char *user_action = "";
events::px4::enums::suggested_action_t action = events::px4::enums::suggested_action_t::none;
for (int index = 0; index < esc_status_s::CONNECTED_ESC_MAX; ++index) {
if (context.isArmed()) {
if (fault_reason_index == esc_fault_reason_t::motor_warn_temp
|| fault_reason_index == esc_fault_reason_t::esc_warn_temp
|| fault_reason_index == esc_fault_reason_t::over_rpm) {
user_action = "Reduce throttle";
action = events::px4::enums::suggested_action_t::reduce_throttle;
if (esc_status.esc[index].failures != 0) {
for (uint8_t fault_index = 0; fault_index <= static_cast<uint8_t>(esc_fault_reason_t::_max); fault_index++) {
if (esc_status.esc[index].failures & (1 << fault_index)) {
esc_fault_reason_t fault_reason_index = static_cast<esc_fault_reason_t>(fault_index);
const char *user_action = "";
events::px4::enums::suggested_action_t action = events::px4::enums::suggested_action_t::none;
if (context.isArmed()) {
if (fault_reason_index == esc_fault_reason_t::motor_warn_temp
|| fault_reason_index == esc_fault_reason_t::esc_warn_temp) {
user_action = "Reduce throttle";
action = events::px4::enums::suggested_action_t::reduce_throttle;
} else {
user_action = "Land now!";
action = events::px4::enums::suggested_action_t::land;
}
}
uint8_t motor_index = esc_status.esc[index].actuator_function - actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1 + 1;
/* EVENT
* @description
* {3}
*
* <profile name="dev">
* This check can be configured via <param>COM_ARM_CHK_ESCS</param> parameter.
* </profile>
*/
reporter.healthFailure<uint8_t, events::px4::enums::esc_fault_reason_t, events::px4::enums::suggested_action_t>(
required_modes, health_component_t::motors_escs, events::ID("check_escs_fault"),
events::Log::Critical, "ESC {1}: {2}", motor_index, fault_reason_index, action);
if (reporter.mavlink_log_pub()) {
mavlink_log_emergency(reporter.mavlink_log_pub(), "ESC%d: %s. %s \t", motor_index,
esc_fault_reason_str(fault_reason_index), user_action);
}
}
} else {
user_action = "Land now!";
action = events::px4::enums::suggested_action_t::land;
}
}
/* EVENT
* @description
* {3}
*
* <profile name="dev">
* This check can be configured via <param>COM_ARM_CHK_ESCS</param> parameter.
* </profile>
*/
reporter.healthFailure<uint8_t, events::px4::enums::esc_fault_reason_t, events::px4::enums::suggested_action_t>(
NavModes::All, health_component_t::motors_escs, events::ID("check_failure_detector_arm_esc"),
events::Log::Critical, "ESC {1}: {2}", esc_index + 1, fault_reason_index, action);
if (reporter.mavlink_log_pub()) {
mavlink_log_emergency(reporter.mavlink_log_pub(), "ESC%d: %s. %s \t", esc_index + 1,
esc_fault_reason_str(fault_reason_index), user_action);
}
}
}
return mask;
}
uint16_t EscChecks::checkMotorStatus(const Context &context, Report &reporter, const esc_status_s &esc_status, hrt_abstime now)
{
uint16_t mask = 0;
// Only check while armed
if (context.status().arming_state == vehicle_status_s::ARMING_STATE_ARMED) {
actuator_motors_s actuator_motors{};
_actuator_motors_sub.copy(&actuator_motors);
// Check individual ESC reports
for (uint8_t i = 0; i < esc_status_s::CONNECTED_ESC_MAX; i++) {
if (!math::isInRange(esc_status.esc[i].actuator_function,
esc_report_s::ACTUATOR_FUNCTION_MOTOR1, esc_report_s::ACTUATOR_FUNCTION_MOTOR_MAX)) {
continue; // Skip unmapped ESC status entries
}
const uint8_t actuator_function_index = esc_status.esc[i].actuator_function - esc_report_s::ACTUATOR_FUNCTION_MOTOR1;
const float current = esc_status.esc[i].esc_current;
// First wait for ESC telemetry reporting non-zero current. Before that happens, don't check it.
if (current > FLT_EPSILON) {
_esc_has_reported_current[i] = true;
}
if (!_esc_has_reported_current[i]) {
continue;
}
// Current limits
float thrust = 0.f;
if (PX4_ISFINITE(actuator_motors.control[actuator_function_index])) {
// Normalized motor thrust commands before thrust model factor is applied, NAN means motor is turned off -> 0 thrust
thrust = fabsf(actuator_motors.control[actuator_function_index]);
}
bool current_too_low = current < (thrust * _param_motfail_c2t.get()) - _param_motfail_low_off.get();
bool current_too_high = current > (thrust * _param_motfail_c2t.get()) + _param_motfail_high_off.get();
_esc_undercurrent_hysteresis[i].set_hysteresis_time_from(false, _param_motfail_time.get() * 1_s);
_esc_overcurrent_hysteresis[i].set_hysteresis_time_from(false, _param_motfail_time.get() * 1_s);
if (!_esc_undercurrent_hysteresis[i].get_state()) {
// Only set, never clear mid-air: stopping the motor in response could make it appear healthy again
_esc_undercurrent_hysteresis[i].set_state_and_update(current_too_low, now);
}
if (!_esc_overcurrent_hysteresis[i].get_state()) {
// Only set, never clear mid-air: stopping the motor in response could make it appear healthy again
_esc_overcurrent_hysteresis[i].set_state_and_update(current_too_high, now);
}
mask |= (static_cast<uint16_t>(_esc_undercurrent_hysteresis[i].get_state()) << actuator_function_index);
mask |= (static_cast<uint16_t>(_esc_overcurrent_hysteresis[i].get_state()) << actuator_function_index);
if (_esc_undercurrent_hysteresis[i].get_state()) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>FD_ACT_EN</param> parameter.
* </profile>
*/
reporter.healthFailure<uint8_t>(NavModes::All, health_component_t::motors_escs,
events::ID("check_motor_undercurrent"),
events::Log::Critical, "Motor {1} undercurrent detected", actuator_function_index + 1);
if (reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "Motor failure: Motor %d undercurrent detected",
actuator_function_index + 1);
}
}
if (_esc_overcurrent_hysteresis[i].get_state()) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>FD_ACT_EN</param> parameter.
* </profile>
*/
reporter.healthFailure<uint8_t>(NavModes::All, health_component_t::motors_escs,
events::ID("check_motor_overcurrent"),
events::Log::Critical, "Motor {1} overcurrent detected", actuator_function_index + 1);
if (reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "Motor failure: Motor %d overcurrent detected",
actuator_function_index + 1);
}
}
}
} else { // Disarmed
for (uint8_t i = 0; i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
_esc_undercurrent_hysteresis[i].set_state_and_update(false, now);
_esc_overcurrent_hysteresis[i].set_state_and_update(false, now);
}
}
return mask;
}
void EscChecks::updateEscsStatus(const Context &context, Report &reporter, const esc_status_s &esc_status, hrt_abstime now)
{
if (context.status().arming_state == vehicle_status_s::ARMING_STATE_ARMED) {
const int limited_esc_count = math::min(esc_status.esc_count, esc_status_s::CONNECTED_ESC_MAX);
const int all_escs_armed_mask = (1 << limited_esc_count) - 1;
const bool is_all_escs_armed = (all_escs_armed_mask == esc_status.esc_armed_flags);
_esc_arm_hysteresis.set_hysteresis_time_from(false, ESC_TIMEOUT_US);
_esc_arm_hysteresis.set_state_and_update(!is_all_escs_armed, now);
if (_esc_arm_hysteresis.get_state()) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>COM_ARM_CHK_ESCS</param> parameter.
* </profile>
*/
reporter.healthFailure(NavModes::All, health_component_t::motors_escs,
events::ID("check_escs_not_all_armed"),
events::Log::Critical, "Not all ESCs are armed");
if (reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "ESC failure: Not all ESCs are armed. Land now!");
}
reporter.failsafeFlags().fd_esc_arming_failure = true;
}
} else {
// reset ESC bitfield
_esc_arm_hysteresis.set_state_and_update(false, now);
reporter.failsafeFlags().fd_esc_arming_failure = false;
}
}
@@ -35,8 +35,11 @@
#include "../Common.hpp"
#include <lib/hysteresis/hysteresis.h>
#include <uORB/Subscription.hpp>
#include <uORB/topics/actuator_motors.h>
#include <uORB/topics/esc_status.h>
#include <uORB/topics/failure_detector_status.h>
class EscChecks : public HealthAndArmingCheckBase
{
@@ -46,14 +49,33 @@ public:
void checkAndReport(const Context &context, Report &reporter) override;
uint16_t getMotorFailureMask() const { return _motor_failure_mask; }
bool getEscArmStatus() const { return _esc_arm_hysteresis.get_state(); }
private:
void checkEscStatus(const Context &context, Report &reporter, const esc_status_s &esc_status);
uint16_t checkEscOnline(const Context &context, Report &reporter, const esc_status_s &esc_status, hrt_abstime now);
uint16_t checkEscStatus(const Context &context, Report &reporter, const esc_status_s &esc_status);
uint16_t checkMotorStatus(const Context &context, Report &reporter, const esc_status_s &esc_status, hrt_abstime now);
void updateEscsStatus(const Context &context, Report &reporter, const esc_status_s &esc_status, hrt_abstime now);
static constexpr hrt_abstime ESC_TIMEOUT_US = 300_ms;
uORB::Subscription _esc_status_sub{ORB_ID(esc_status)};
uORB::Subscription _actuator_motors_sub{ORB_ID(actuator_motors)};
const hrt_abstime _start_time{hrt_absolute_time()};
uint16_t _motor_failure_mask = 0;
bool _esc_has_reported_current[esc_status_s::CONNECTED_ESC_MAX] {};
systemlib::Hysteresis _esc_undercurrent_hysteresis[esc_status_s::CONNECTED_ESC_MAX];
systemlib::Hysteresis _esc_overcurrent_hysteresis[esc_status_s::CONNECTED_ESC_MAX];
systemlib::Hysteresis _esc_arm_hysteresis;
DEFINE_PARAMETERS_CUSTOM_PARENT(HealthAndArmingCheckBase,
(ParamBool<px4::params::COM_ARM_CHK_ESCS>) _param_com_arm_chk_escs
)
(ParamBool<px4::params::COM_ARM_CHK_ESCS>) _param_com_arm_chk_escs,
(ParamBool<px4::params::FD_ACT_EN>) _param_fd_act_en,
(ParamFloat<px4::params::MOTFAIL_C2T>) _param_motfail_c2t,
(ParamFloat<px4::params::MOTFAIL_TIME>) _param_motfail_time,
(ParamFloat<px4::params::MOTFAIL_LOW_OFF>) _param_motfail_low_off,
(ParamFloat<px4::params::MOTFAIL_HIGH_OFF>) _param_motfail_high_off);
};
@@ -98,27 +98,6 @@ void FailureDetectorChecks::checkAndReport(const Context &context, Report &repor
(vehicle_status_s::FAILURE_ROLL | vehicle_status_s::FAILURE_PITCH | vehicle_status_s::FAILURE_ALT |
vehicle_status_s::FAILURE_EXT);
reporter.failsafeFlags().fd_esc_arming_failure = context.status().failure_detector_status &
vehicle_status_s::FAILURE_ARM_ESC;
if (reporter.failsafeFlags().fd_esc_arming_failure) {
/* EVENT
* @description
* One or more ESCs failed to arm.
*
* <profile name="dev">
* This check can be configured via <param>FD_ESCS_EN</param> parameter.
* </profile>
*/
reporter.healthFailure(NavModes::All, health_component_t::motors_escs, events::ID("check_failure_detector_arm_esc"),
events::Log::Critical, "ESC failure");
if (reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "Preflight Fail: ESC failure detected");
}
}
reporter.failsafeFlags().fd_imbalanced_prop = context.status().failure_detector_status &
vehicle_status_s::FAILURE_IMBALANCED_PROP;
@@ -138,22 +117,4 @@ void FailureDetectorChecks::checkAndReport(const Context &context, Report &repor
mavlink_log_critical(reporter.mavlink_log_pub(), "Preflight Fail: Imbalanced propeller detected");
}
}
reporter.failsafeFlags().fd_motor_failure = context.status().failure_detector_status & vehicle_status_s::FAILURE_MOTOR;
if (reporter.failsafeFlags().fd_motor_failure) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>FD_ACT_EN</param> parameter.
* </profile>
*/
reporter.healthFailure(NavModes::All, health_component_t::motors_escs, events::ID("check_failure_detector_motor"),
events::Log::Critical, "Motor failure detected");
if (reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "Preflight Fail: Motor failure detected");
}
}
}
@@ -80,9 +80,9 @@ void FlightTimeChecks::checkAndReport(const Context &context, Report &reporter)
}
/* EVENT
* @description
* Maximal flight time warning (less than 1min remaining)
*/
* @description
* Maximal flight time warning (less than 1min remaining)
*/
events::send<int16_t>(events::ID("commander_max_flight_time_warning_seconds"), events::Log::Warning,
"Approaching max flight time (system will RTL in {1} seconds)", floored_remaining_flight_time_sec);
@@ -97,9 +97,9 @@ void FlightTimeChecks::checkAndReport(const Context &context, Report &reporter)
}
/* EVENT
* @description
* Maximal flight time warning (more than 1min remaining)
*/
* @description
* Maximal flight time warning (more than 1min remaining)
*/
events::send<int16_t>(events::ID("commander_max_flight_time_warning_minutes"), events::Log::Warning,
"Approaching max flight time (system will RTL in {1} minutes)", floored_remaining_flight_time_min);
}
@@ -51,11 +51,11 @@ void GeofenceChecks::checkAndReport(const Context &context, Report &reporter)
if (geofence_result.geofence_max_dist_triggered) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>GF_ACTION</param> and <param>GF_MAX_HOR_DIST</param> parameters.
* </profile>
*/
* @description
* <profile name="dev">
* This check can be configured via <param>GF_ACTION</param> and <param>GF_MAX_HOR_DIST</param> parameters.
* </profile>
*/
reporter.armingCheckFailure(NavModes::All, health_component_t::system,
events::ID("check_gf_violation_max_hor_dist"),
events::Log::Error, "Geofence violation: exceeding maximum distance to Home");
@@ -67,11 +67,11 @@ void GeofenceChecks::checkAndReport(const Context &context, Report &reporter)
if (geofence_result.geofence_max_alt_triggered) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>GF_ACTION</param> and <param>GF_MAX_VER_DIST</param> parameters.
* </profile>
*/
* @description
* <profile name="dev">
* This check can be configured via <param>GF_ACTION</param> and <param>GF_MAX_VER_DIST</param> parameters.
* </profile>
*/
reporter.armingCheckFailure(NavModes::All, health_component_t::system,
events::ID("check_gf_violation_max_alt"),
events::Log::Error, "Geofence violation: exceeding maximum altitude above Home");
@@ -83,11 +83,11 @@ void GeofenceChecks::checkAndReport(const Context &context, Report &reporter)
if (geofence_result.geofence_custom_fence_triggered) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>GF_ACTION</param> parameter.
* </profile>
*/
* @description
* <profile name="dev">
* This check can be configured via <param>GF_ACTION</param> parameter.
* </profile>
*/
reporter.armingCheckFailure(NavModes::All, health_component_t::system,
events::ID("check_gf_violation_custom_gf"),
events::Log::Error, "Geofence violation: approaching or outside geofence");
@@ -0,0 +1,104 @@
/****************************************************************************
*
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* Enable Actuator Failure check
*
* If enabled, the HealthAndArmingChecks will verify that for motors, a minimum amount of ESC current per throttle
* level is being consumed.
* Otherwise this indicates an motor failure.
* This check only works for ESCs that report current consumption.
*
* @boolean
*
* @group Motor Failure
*/
PARAM_DEFINE_INT32(FD_ACT_EN, 0);
/**
* Motor Failure Current/Throttle Scale
*
* Determines the slope between expected steady state current and linearized, normalized thrust command.
* E.g. FD_ACT_MOT_C2T A represents the expected steady state current at 100%.
* FD_ACT_LOW_OFF and FD_ACT_HIGH_OFF offset the threshold from that slope.
*
* @group Motor Failure
* @min 0.0
* @max 50.0
* @unit A/%
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(MOTFAIL_C2T, 35.f);
/**
* Undercurrent motor failure limit offset
*
* threshold = FD_ACT_MOT_C2T * thrust - FD_ACT_LOW_OFF
*
* @group Motor Failure
* @min 0
* @max 30
* @unit A
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(MOTFAIL_LOW_OFF, 10.f);
/**
* Overcurrent motor failure limit offset
*
* threshold = FD_ACT_MOT_C2T * thrust + FD_ACT_HIGH_OFF
*
* @group Motor Failure
* @min 0
* @max 30
* @unit A
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(MOTFAIL_HIGH_OFF, 10.f);
/**
* Motor Failure Hysteresis Time
*
* Motor failure only triggers after current thresholds are exceeded for this time.
*
* @group Motor Failure
* @unit s
* @min 0.01
* @max 10
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(MOTFAIL_TIME, 1.f);
@@ -39,6 +39,7 @@
*/
#include "FailureDetector.hpp"
#include "../HealthAndArmingChecks/HealthAndArmingChecks.hpp"
using namespace time_literals;
@@ -67,21 +68,6 @@ bool FailureDetector::update(const vehicle_status_s &vehicle_status, const vehic
_failure_detector_status.flags.ext = false;
}
// esc_status subscriber is shared between subroutines
esc_status_s esc_status;
if (_esc_status_sub.update(&esc_status)) {
_failure_injector.manipulateEscStatus(esc_status);
if (_param_escs_en.get()) {
updateEscsStatus(vehicle_status, esc_status);
}
if (_param_fd_act_en.get()) {
updateMotorStatus(vehicle_status, esc_status);
}
}
if (_param_fd_imb_prop_thr.get() > 0) {
updateImbalancedPropStatus();
}
@@ -89,19 +75,19 @@ bool FailureDetector::update(const vehicle_status_s &vehicle_status, const vehic
return _failure_detector_status.value != status_prev.value;
}
void FailureDetector::publishStatus()
void FailureDetector::publishStatus(bool esc_arm_status, uint16_t motor_failure_mask)
{
failure_detector_status_s failure_detector_status{};
failure_detector_status.fd_roll = _failure_detector_status.flags.roll;
failure_detector_status.fd_pitch = _failure_detector_status.flags.pitch;
failure_detector_status.fd_alt = _failure_detector_status.flags.alt;
failure_detector_status.fd_ext = _failure_detector_status.flags.ext;
failure_detector_status.fd_arm_escs = _failure_detector_status.flags.arm_escs;
failure_detector_status.fd_arm_escs = esc_arm_status || (motor_failure_mask != 0);
failure_detector_status.fd_battery = _failure_detector_status.flags.battery;
failure_detector_status.fd_imbalanced_prop = _failure_detector_status.flags.imbalanced_prop;
failure_detector_status.fd_motor = _failure_detector_status.flags.motor;
failure_detector_status.fd_motor = (motor_failure_mask != 0);
failure_detector_status.imbalanced_prop_metric = _imbalanced_prop_lpf.getState();
failure_detector_status.motor_failure_mask = _motor_failure_mask;
failure_detector_status.motor_failure_mask = motor_failure_mask;
failure_detector_status.motor_stop_mask = _failure_injector.getMotorStopMask();
failure_detector_status.timestamp = hrt_absolute_time();
_failure_detector_status_pub.publish(failure_detector_status);
@@ -172,34 +158,6 @@ void FailureDetector::updateExternalAtsStatus()
}
}
void FailureDetector::updateEscsStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status)
{
hrt_abstime now = hrt_absolute_time();
if (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED) {
const int limited_esc_count = math::min(esc_status.esc_count, esc_status_s::CONNECTED_ESC_MAX);
const int all_escs_armed_mask = (1 << limited_esc_count) - 1;
const bool is_all_escs_armed = (all_escs_armed_mask == esc_status.esc_armed_flags);
bool is_esc_failure = !is_all_escs_armed;
for (int i = 0; i < limited_esc_count; i++) {
is_esc_failure = is_esc_failure || (esc_status.esc[i].failures > 0);
}
_esc_failure_hysteresis.set_hysteresis_time_from(false, 300_ms);
_esc_failure_hysteresis.set_state_and_update(is_esc_failure, now);
if (_esc_failure_hysteresis.get_state()) {
_failure_detector_status.flags.arm_escs = true;
}
} else {
// reset ESC bitfield
_esc_failure_hysteresis.set_state_and_update(false, now);
_failure_detector_status.flags.arm_escs = false;
}
}
void FailureDetector::updateImbalancedPropStatus()
{
@@ -258,82 +216,3 @@ void FailureDetector::updateImbalancedPropStatus()
}
}
}
void FailureDetector::updateMotorStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status)
{
// 1. Telemetry times out -> communication or power lost on that ESC
// 2. Too low current draw compared to commanded thrust
// Overvoltage, overcurrent do not have checks yet esc_report.failures are handled separately
const hrt_abstime now = hrt_absolute_time();
// Only check while armed
if (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED) {
actuator_motors_s actuator_motors{};
_actuator_motors_sub.copy(&actuator_motors);
// Check individual ESC reports
for (uint8_t i = 0; i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
// Map the esc status index to the actuator function index
const uint8_t actuator_function_index =
esc_status.esc[i].actuator_function - actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1;
if (actuator_function_index >= actuator_motors_s::NUM_CONTROLS) {
continue; // Invalid mapping
}
const bool timeout = now > esc_status.esc[i].timestamp + 300_ms;
const float current = esc_status.esc[i].esc_current;
// First wait for ESC telemetry reporting non-zero current. Before that happens, don't check it.
if (current > FLT_EPSILON) {
_esc_has_reported_current[i] = true;
}
if (!_esc_has_reported_current[i]) {
continue;
}
_motor_failure_mask &= ~(1u << actuator_function_index); // Reset bit in mask to accumulate failures again
_motor_failure_mask |= (static_cast<uint16_t>(timeout) << actuator_function_index); // Telemetry timeout
// Current limits
float thrust = 0.f;
if (PX4_ISFINITE(actuator_motors.control[actuator_function_index])) {
// Normalized motor thrust commands before thrust model factor is applied, NAN means motor is turned off -> 0 thrust
thrust = fabsf(actuator_motors.control[actuator_function_index]);
}
bool thrust_above_threshold = thrust > _param_fd_act_mot_thr.get();
bool current_too_low = current < (thrust * _param_fd_act_mot_c2t.get()) - _param_fd_act_low_off.get();
bool current_too_high = current > (thrust * _param_fd_act_mot_c2t.get()) + _param_fd_act_high_off.get();
_esc_undercurrent_hysteresis[i].set_hysteresis_time_from(false, _param_fd_act_mot_tout.get() * 1_ms);
_esc_overcurrent_hysteresis[i].set_hysteresis_time_from(false, _param_fd_act_mot_tout.get() * 1_ms);
if (!_esc_undercurrent_hysteresis[i].get_state()) {
// Do not clear mid operation because a reaction could be to stop the motor and that would be conidered healthy again
_esc_undercurrent_hysteresis[i].set_state_and_update(thrust_above_threshold && current_too_low && !timeout, now);
}
if (!_esc_overcurrent_hysteresis[i].get_state()) {
// Do not clear mid operation because a reaction could be to stop the motor and that would be conidered healthy again
_esc_overcurrent_hysteresis[i].set_state_and_update(current_too_high && !timeout, now);
}
_motor_failure_mask |= (static_cast<uint16_t>(_esc_undercurrent_hysteresis[i].get_state()) << actuator_function_index);
_motor_failure_mask |= (static_cast<uint16_t>(_esc_overcurrent_hysteresis[i].get_state()) << actuator_function_index);
}
_failure_detector_status.flags.motor = (_motor_failure_mask != 0u);
} else { // Disarmed
for (uint8_t i = 0; i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
_esc_undercurrent_hysteresis[i].set_state_and_update(false, now);
_esc_overcurrent_hysteresis[i].set_state_and_update(false, now);
}
_failure_detector_status.flags.motor = false;
}
}
@@ -53,8 +53,6 @@
// subscriptions
#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/topics/actuator_motors.h>
#include <uORB/topics/esc_status.h>
#include <uORB/topics/failure_detector_status.h>
#include <uORB/topics/pwm_input.h>
#include <uORB/topics/sensor_selection.h>
@@ -70,10 +68,8 @@ union failure_detector_status_u {
uint16_t pitch : 1;
uint16_t alt : 1;
uint16_t ext : 1;
uint16_t arm_escs : 1;
uint16_t battery : 1;
uint16_t imbalanced_prop : 1;
uint16_t motor : 1;
} flags;
uint16_t value {0};
};
@@ -89,13 +85,11 @@ public:
bool update(const vehicle_status_s &vehicle_status, const vehicle_control_mode_s &vehicle_control_mode);
const failure_detector_status_u &getStatus() const { return _failure_detector_status; }
void publishStatus();
void publishStatus(bool esc_arm_status, uint16_t motor_failure_mask);
private:
void updateAttitudeStatus(const vehicle_status_s &vehicle_status);
void updateExternalAtsStatus();
void updateEscsStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status);
void updateMotorStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status);
void updateImbalancedPropStatus();
failure_detector_status_u _failure_detector_status{};
@@ -103,25 +97,17 @@ private:
systemlib::Hysteresis _roll_failure_hysteresis{false};
systemlib::Hysteresis _pitch_failure_hysteresis{false};
systemlib::Hysteresis _ext_ats_failure_hysteresis{false};
systemlib::Hysteresis _esc_failure_hysteresis{false};
static constexpr float _imbalanced_prop_lpf_time_constant{5.f};
AlphaFilter<float> _imbalanced_prop_lpf{};
uint32_t _selected_accel_device_id{0};
hrt_abstime _imu_status_timestamp_prev{0};
// Motor failure check
bool _esc_has_reported_current[esc_status_s::CONNECTED_ESC_MAX] {}; // true if ESC reported non-zero current before (some never report any)
systemlib::Hysteresis _esc_undercurrent_hysteresis[esc_status_s::CONNECTED_ESC_MAX];
systemlib::Hysteresis _esc_overcurrent_hysteresis[esc_status_s::CONNECTED_ESC_MAX];
uint16_t _motor_failure_mask = 0; // actuator function indexed
uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)};
uORB::Subscription _esc_status_sub{ORB_ID(esc_status)}; // TODO: multi-instance
uORB::Subscription _pwm_input_sub{ORB_ID(pwm_input)};
uORB::Subscription _sensor_selection_sub{ORB_ID(sensor_selection)};
uORB::Subscription _vehicle_imu_status_sub{ORB_ID(vehicle_imu_status)};
uORB::Subscription _actuator_motors_sub{ORB_ID(actuator_motors)};
uORB::Publication<failure_detector_status_s> _failure_detector_status_pub{ORB_ID(failure_detector_status)};
@@ -134,15 +120,6 @@ private:
(ParamFloat<px4::params::FD_FAIL_P_TTRI>) _param_fd_fail_p_ttri,
(ParamBool<px4::params::FD_EXT_ATS_EN>) _param_fd_ext_ats_en,
(ParamInt<px4::params::FD_EXT_ATS_TRIG>) _param_fd_ext_ats_trig,
(ParamInt<px4::params::FD_ESCS_EN>) _param_escs_en,
(ParamInt<px4::params::FD_IMB_PROP_THR>) _param_fd_imb_prop_thr,
// Actuator failure
(ParamBool<px4::params::FD_ACT_EN>) _param_fd_act_en,
(ParamFloat<px4::params::FD_ACT_MOT_THR>) _param_fd_act_mot_thr,
(ParamFloat<px4::params::FD_ACT_MOT_C2T>) _param_fd_act_mot_c2t,
(ParamInt<px4::params::FD_ACT_MOT_TOUT>) _param_fd_act_mot_tout,
(ParamFloat<px4::params::FD_ACT_LOW_OFF>) _param_fd_act_low_off,
(ParamFloat<px4::params::FD_ACT_HIGH_OFF>) _param_fd_act_high_off
(ParamInt<px4::params::FD_IMB_PROP_THR>) _param_fd_imb_prop_thr
)
};
@@ -39,9 +39,6 @@
* @author Mathieu Bresciani <brescianimathieu@gmail.com>
*/
#include <px4_platform_common/px4_config.h>
#include <parameters/param.h>
/**
* FailureDetector Max Roll
*
@@ -130,18 +127,6 @@ PARAM_DEFINE_INT32(FD_EXT_ATS_EN, 0);
*/
PARAM_DEFINE_INT32(FD_EXT_ATS_TRIG, 1900);
/**
* Enable checks on ESCs that report their arming state.
*
* If enabled, failure detector will verify that all the ESCs have successfully armed when the vehicle has transitioned to the armed state.
* Timeout for receiving an acknowledgement from the ESCs is 0.3s, if no feedback is received the failure detector will auto disarm the vehicle.
*
* @boolean
*
* @group Failure Detector
*/
PARAM_DEFINE_INT32(FD_ESCS_EN, 1);
/**
* Imbalanced propeller check threshold
*
@@ -156,89 +141,3 @@ PARAM_DEFINE_INT32(FD_ESCS_EN, 1);
* @group Failure Detector
*/
PARAM_DEFINE_INT32(FD_IMB_PROP_THR, 30);
/**
* Enable Actuator Failure check
*
* If enabled, failure detector will verify that for motors, a minimum amount of ESC current per throttle
* level is being consumed.
* Otherwise this indicates an motor failure.
*
* @boolean
* @reboot_required true
*
* @group Failure Detector
*/
PARAM_DEFINE_INT32(FD_ACT_EN, 0);
/**
* Motor Failure Thrust Threshold
*
* Failure detection per motor only triggers above this thrust value.
* Set to 1 to disable the detection.
*
* @group Failure Detector
* @unit norm
* @min 0.0
* @max 1.0
* @decimal 2
* @increment 0.01
*/
PARAM_DEFINE_FLOAT(FD_ACT_MOT_THR, 0.2f);
/**
* Motor Failure Current/Throttle Scale
*
* Determines the slope between expected steady state current and linearized, normalized thrust command.
* E.g. FD_ACT_MOT_C2T A represents the expected steady state current at 100%.
* FD_ACT_LOW_OFF and FD_ACT_HIGH_OFF offset the threshold from that slope.
*
* @group Failure Detector
* @min 0.0
* @max 50.0
* @unit A/%
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(FD_ACT_MOT_C2T, 35.f);
/**
* Motor Failure Hysteresis Time
*
* Motor failure only triggers after current thresholds are exceeded for this time.
*
* @group Failure Detector
* @unit ms
* @min 10
* @max 10000
* @increment 100
*/
PARAM_DEFINE_INT32(FD_ACT_MOT_TOUT, 1000);
/**
* Undercurrent motor failure limit offset
*
* threshold = FD_ACT_MOT_C2T * thrust - FD_ACT_LOW_OFF
*
* @group Failure Detector
* @min 0
* @max 30
* @unit A
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(FD_ACT_LOW_OFF, 10.f);
/**
* Overcurrent motor failure limit offset
*
* threshold = FD_ACT_MOT_C2T * thrust + FD_ACT_HIGH_OFF
*
* @group Failure Detector
* @min 0
* @max 30
* @unit A
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(FD_ACT_HIGH_OFF, 10.f);
+26 -24
View File
@@ -522,9 +522,16 @@ bool MavlinkLogHandler::log_entry_from_id(uint16_t log_id, LogEntry *entry)
return found_entry;
}
void MavlinkLogHandler::delete_all_logs(const char *dir)
void MavlinkLogHandler::delete_all_logs(const char *dir, unsigned depth)
{
//-- Open log directory
// Log structure is log/yyyy-mm-dd/file.ulg (2 levels). Cap recursion to prevent stack overflow.
static constexpr unsigned MAX_DEPTH = 3;
if (depth >= MAX_DEPTH) {
PX4_DEBUG("Max depth reached: %s", dir);
return;
}
DIR *dp = opendir(dir);
if (dp == nullptr) {
@@ -534,34 +541,29 @@ void MavlinkLogHandler::delete_all_logs(const char *dir)
struct dirent *result = nullptr;
while ((result = readdir(dp))) {
// no more entries?
if (result == nullptr) {
break;
if (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0) {
continue;
}
if (result->d_type == PX4LOG_DIRECTORY && result->d_name[0] != '.') {
char filepath[PX4_MAX_FILEPATH];
int ret = snprintf(filepath, sizeof(filepath), "%s/%s", dir, result->d_name);
bool path_is_ok = (ret > 0) && (ret < (int)sizeof(filepath));
char filepath[PX4_MAX_FILEPATH];
int ret = snprintf(filepath, sizeof(filepath), "%s/%s", dir, result->d_name);
bool path_is_ok = (ret > 0) && (ret < (int)sizeof(filepath));
if (path_is_ok) {
delete_all_logs(filepath);
if (!path_is_ok) {
continue;
}
if (rmdir(filepath)) {
PX4_DEBUG("Error removing %s", filepath);
}
if (result->d_type == PX4LOG_DIRECTORY) {
delete_all_logs(filepath, depth + 1);
if (rmdir(filepath)) {
PX4_DEBUG("Error removing %s", filepath);
}
}
if (result->d_type == PX4LOG_REGULAR_FILE) {
char filepath[PX4_MAX_FILEPATH];
int ret = snprintf(filepath, sizeof(filepath), "%s/%s", dir, result->d_name);
bool path_is_ok = (ret > 0) && (ret < (int)sizeof(filepath));
if (path_is_ok) {
if (unlink(filepath)) {
PX4_DEBUG("Error unlinking %s", filepath);
}
} else {
if (unlink(filepath)) {
PX4_DEBUG("Error unlinking %s", filepath);
}
}
}
+1 -1
View File
@@ -96,7 +96,7 @@ private:
bool log_entry_from_id(uint16_t log_id, LogEntry *entry);
// Log erase
void delete_all_logs(const char *dir);
void delete_all_logs(const char *dir, unsigned depth = 0);
private:
+2 -2
View File
@@ -102,8 +102,8 @@ private:
_interface[i].esc_online_flags = 0;
for (int j = 0; j < esc_status_s::CONNECTED_ESC_MAX; j++) {
bool is_motor = ((int)esc.esc[j].actuator_function >= esc_report_s::ACTUATOR_FUNCTION_MOTOR1) &&
((int)esc.esc[j].actuator_function <= esc_report_s::ACTUATOR_FUNCTION_MOTOR12);
bool is_motor = math::isInRange(esc.esc[j].actuator_function,
esc_report_s::ACTUATOR_FUNCTION_MOTOR1, esc_report_s::ACTUATOR_FUNCTION_MOTOR_MAX);
if (is_motor) {
// Map OutputFunction number to index
+2 -2
View File
@@ -84,8 +84,8 @@ private:
if (_esc_status_subs[i].update(&esc)) {
for (int j = 0; j < esc_status_s::CONNECTED_ESC_MAX; j++) {
bool is_motor = ((int)esc.esc[j].actuator_function >= esc_report_s::ACTUATOR_FUNCTION_MOTOR1) &&
((int)esc.esc[j].actuator_function <= esc_report_s::ACTUATOR_FUNCTION_MOTOR12);
const bool is_motor = math::isInRange(esc.esc[j].actuator_function,
esc_report_s::ACTUATOR_FUNCTION_MOTOR1, esc_report_s::ACTUATOR_FUNCTION_MOTOR_MAX);
if (is_motor) {
// Map OutputFunction number to index