Compare commits

...

46 Commits

Author SHA1 Message Date
Pedro-Roque bbd6d9794f fix: add whitelist on dds em 2026-03-12 22:50:46 -07:00
Pedro-Roque 695e2c7caa Merge branch 'feat/safe_dds' of github.com:PX4/PX4-Autopilot into feat/safe_dds 2026-03-12 15:25:42 -07:00
Pedro-Roque 627072b811 feat: added module name 2026-03-12 15:25:31 -07:00
Pedro Roque d651d9e8e2 Merge branch 'main' into feat/safe_dds 2026-03-12 15:08:41 -07:00
Pedro-Roque 574295998b Merge branch 'feat/safe_dds' of github.com:PX4/PX4-Autopilot into feat/safe_dds 2026-03-12 15:07:21 -07:00
Pedro-Roque 71807c93d8 fix: schema failure 2026-03-12 15:07:09 -07:00
PX4BuildBot 59ded6affd docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-03-12 20:51:32 +00:00
Ege Kural 4a33fb169f fix(ci): enable clang-tidy bugprone-macro-parentheses (#26722)
Signed-off-by: kuralme <kuralme@protonmail.com>
2026-03-12 12:42:07 -08:00
Ramon Roche 11700382f6 docs(contributing): add coding standards and test policy
Add explicit coding standards section referencing astyle and
clang-tidy enforcement. Add formal test policy requiring tests
where practical and types of tests table.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-03-12 13:15:45 -07:00
Ramon Roche 3f0ddf9793 docs(security): update policy for OpenSSF badge
Update supported versions to 1.16.x, add response process with
7-day acknowledgment timeline, reporter credit policy, and secure
development practices section.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-03-12 13:15:45 -07:00
Ramon Roche 400bb253bd docs(mavlink): security hardening guide for production deployments (#26730)
* docs(mavlink): add security hardening guide for production deployments

Add a dedicated security hardening page covering MAVLink authentication
risks, a hardening checklist (enable signing, secure physical access,
secure network links), and integrator responsibility for deployment
security. Add a warning block to the main MAVLink page linking to the
new guide.

---------

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-03-12 12:53:29 -07:00
PX4BuildBot d6e31f59cf docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-03-12 19:52:00 +00:00
Ramon Roche 3ed2f23d9c fix(build): resolve Dependabot security alerts (#26729)
Fix 4 Dependabot alerts:
- CVE-2021-34141: remove duplicate vulnerable numpy==1.21.5 pin
- markdown-it ReDoS (>= 13.0.0, < 14.1.1): add yarn resolution to 14.1.1
- preact JSON VNode injection: resolved by yarn upgrade to 10.29.0
- esbuild dev server request leak (<= 0.24.2): add yarn resolution to 0.25.0

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-03-12 12:40:35 -07:00
Balduin ab6c9b7909 docs(ekf2): clarify EKF2_HGT_REF param description (#26725)
* docs(ekf2): clarify EKF2_HGT_REF param description

To me it was not obvious that with EKF2_GPS_CTRL=0 this altitude
initialisation based on GPS again does not apply.

* docs(ekf2): separate paragraph
2026-03-12 11:30:22 -08:00
Pedro Roque b0d061b0b7 Merge branch 'main' into feat/safe_dds 2026-03-12 11:15:05 -07:00
Pedro-Roque 23613e7e4a rft(dds): reduce the number of conditional checks 2026-03-12 11:13:59 -07:00
PX4BuildBot eeb251aa52 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-03-12 17:47:04 +00:00
Matthias Grob 7b3fe3478b ESC check cleanup 2026-03-12 18:30:51 +01:00
ttechnick 7aa28de922 ESC check: use constants for ESC timeout 2026-03-12 18:30:51 +01:00
Matthias Grob a9461c4d1a escCheck: Change MOTFAIL_TIME unit to seconds for better UX 2026-03-12 18:30:51 +01:00
Matthias Grob fb9f8d1835 escCheck: remove thrust threshold above which current model applies
The newer upper lower bound offset current model should apply more accurately and not require a lower bount for thrust where there's no detection.
2026-03-12 18:30:51 +01:00
Matthias Grob 6361b4cd7e Unify motor function mapping checks to only depend on the interface 2026-03-12 18:30:51 +01:00
Matthias Grob 8bb82c70ee escCheck: structure suggestions 2026-03-12 18:30:51 +01:00
Matthias Grob 0071699348 HealthChecks: correct indentation for EVENT metadata 2026-03-12 18:30:51 +01:00
Matthias Grob 54df6d64a6 Commander: move FD_ACT_EN to esc check 2026-03-12 18:30:51 +01:00
Matthias Grob 7207c34c5b Commander: avoid leaking health checks into failure detector 2026-03-12 18:30:51 +01:00
Matthias Grob 270ad06e5f Remove traces of FD_ESCS_EN 2026-03-12 18:30:51 +01:00
Matthias Grob 8bafcfbac7 Rename parameters file for ESC checks 2026-03-12 18:30:51 +01:00
Matthias Grob 2ff83e7e7c escCheck: rename MOTFAIL_TOUT -> MOTFAIL_TIME and further cleanup 2026-03-12 18:30:51 +01:00
Matthias Grob 035ccc8395 FailureDetector: disarm again with ESC failures during spoolup 2026-03-12 18:30:51 +01:00
Matthias Grob 7d84911668 FailureDetector: remove obsolete subscriptions 2026-03-12 18:30:51 +01:00
ttechnick 4e279b16c2 uavcan: optimization and edge cases 2026-03-12 18:30:51 +01:00
ttechnick c5652b2084 escChecks: param reorg
Reorganise parameters
fix esc & motor indices
set failsafe flags
2026-03-12 18:30:51 +01:00
ttechnick 03fc051c29 uavcan:fix check 2026-03-12 18:30:51 +01:00
ttechnick 96c5c7ba02 work on: feed back checks to commander 2026-03-12 18:30:51 +01:00
ttechnick e9874b6f05 ensure motor faults are cleared 2026-03-12 18:30:51 +01:00
ttechnick 15f5a18629 uavcan: cleanup 2026-03-12 18:30:51 +01:00
ttechnick b2ea7ffab6 fd: reorganise motor & esc failures 2026-03-12 18:30:51 +01:00
ttechnick 9f978b05f3 uavcan: unify timeout handling 2026-03-12 18:30:51 +01:00
Pedro-Roque 71ac74827a feat: add whitelisting 2026-03-12 10:00:05 -07:00
PX4BuildBot aa998d88b8 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-03-12 03:57:59 +00:00
Hamish Willee 7e776a7b9c fix(docs): src_parser.py keep empty lines in param desciption (#26656) 2026-03-11 20:29:53 -07:00
Hamish Willee 57cf570bb4 fix(docs): Fix internal docs links (#26718) 2026-03-12 14:29:35 +11:00
Jacob Dahl 55b62e5f2b fix(mavlink): use >= for depth check to match MAX_DEPTH semantics 2026-03-11 19:50:36 -07:00
Jacob Dahl 8d99569643 fix(mavlink): bound recursion depth in delete_all_logs
Prevent potential stack overflow from symlink loops or deeply nested
directories by capping recursion to 3 levels. Also fixes dot-entry
skipping to use strcmp instead of prefix check, and deduplicates the
filepath construction.
2026-03-11 19:50:36 -07:00
Pedro-Roque 41e1ee6023 feat: ensure safe DDS interface by default 2026-03-11 15:58:47 -07:00
69 changed files with 2216 additions and 1429 deletions
-1
View File
@@ -150,7 +150,6 @@ Checks: '*,
-readability-convert-member-functions-to-static,
-readability-make-member-function-const,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-macro-parentheses,
-bugprone-multi-level-implicit-pointer-conversion,
-bugprone-signed-char-misuse,
-cppcoreguidelines-avoid-non-const-global-variables,
+21 -1
View File
@@ -16,7 +16,13 @@ git checkout -b mydescriptivebranchname
## Edit and build the code
The [developer guide](https://docs.px4.io/main/en/development/development.html) explains how to set up the development environment on Mac OS, Linux or Windows. Please take note of our [coding style](https://docs.px4.io/main/en/contribute/code.html) when editing files.
The [developer guide](https://docs.px4.io/main/en/development/development.html) explains how to set up the development environment on Mac OS, Linux or Windows.
### Coding standards
All C/C++ code must follow the [PX4 coding style](https://docs.px4.io/main/en/contribute/code.html). Formatting is enforced by [astyle](http://astyle.sourceforge.net/) in CI (`make check_format`). Code quality checks run via [clang-tidy](https://clang.llvm.org/extra/clang-tidy/). Pull requests that fail either check will not be merged.
Python code is checked with [mypy](https://mypy-lang.org/) and [flake8](https://flake8.pycqa.org/).
## Commit message convention
@@ -141,6 +147,20 @@ git push --force-with-lease
## Test your changes
PX4 is safety-critical software. All contributions must include adequate testing where practical:
- **New features** must include unit tests and/or integration tests that exercise the new functionality, where practical. Hardware-dependent changes that cannot be tested in SITL should include bench test or flight test evidence.
- **Bug fixes** must include a regression test where practical. When automated testing is not feasible (hardware-specific issues, race conditions, etc.), provide a link to a flight log demonstrating the fix and the reproduction steps for the original bug.
- **Reviewers** will verify that tests or test evidence exist before approving a pull request.
### Types of tests
| Test type | When to use | How to run |
|-----------|-------------|------------|
| **Unit tests** (gtest) | Module-level logic, math, parsing | `make tests` |
| **SITL integration tests** (MAVSDK) | Flight behavior, failsafes, missions | `test/mavsdk_tests/` |
| **Bench tests / flight logs** | Hardware-dependent changes | Upload logs to [Flight Review](https://logs.px4.io) |
Since we care about safety, we will regularly ask you for test results. Best is to do a test flight (or bench test where it applies) and upload the log file from it (on the microSD card in the logs directory) to Google Drive or Dropbox and share the link.
## Push your changes
@@ -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
+28 -12
View File
@@ -2,24 +2,40 @@
## Supported Versions
The following is a list of versions the development team is currently supporting.
The following versions receive security updates:
| Version | Supported |
| ------- | ------------------ |
| 1.4.x | :white_check_mark: |
| 1.3.3 | :white_check_mark: |
| < 1.3 | :x: |
| 1.16.x | :white_check_mark: |
| < 1.16 | :x: |
## Reporting a Vulnerability
We currently only receive security vulnerability reports through GitHub.
We receive security vulnerability reports through GitHub Security Advisories.
To begin a report, please go to the top-level repository, for example, PX4/PX4-Autopilot,
and click on the Security tab. If you are on mobile, click the ... dropdown menu, and then click Security.
To begin a report, go to the [PX4/PX4-Autopilot](https://github.com/PX4/PX4-Autopilot) repository
and click on the **Security** tab. If you are on mobile, click the **...** dropdown menu, then click **Security**.
Click Report a Vulnerability to open the advisory form. Fill in the advisory details form.
Make sure your title is descriptive, and the development team can find all of the relevant details needed
to verify on the description box. We recommend you add as much data as possible. We welcome logs,
screenshots, photos, and videos, anything that can help us verify and identify the issues being reported.
Click **Report a Vulnerability** to open the advisory form. Fill in the advisory details form.
Make sure your title is descriptive and the description contains all relevant details needed
to verify the issue. We welcome logs, screenshots, photos, and videos.
At the bottom of the form, click Submit report. The maintainer team will be notified and will get back to you ASAP.
At the bottom of the form, click **Submit report**.
## Response Process
1. **Acknowledgment**: The maintainer team will acknowledge your report within **7 days**.
2. **Triage**: We will assess severity and impact and communicate next steps.
3. **Disclosure**: We coordinate disclosure with the reporter. We follow responsible disclosure practices and will credit reporters in the advisory unless they request anonymity.
If you do not receive acknowledgment within 7 days, please follow up by emailing the [release managers](MAINTAINERS.md).
## Secure Development Practices
The PX4 development team applies the following practices to reduce security risk:
- **Code review**: All changes require peer review before merging.
- **Static analysis**: [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) runs on every pull request with warnings treated as errors.
- **Fuzzing**: A daily fuzzing pipeline using [Google fuzztest](https://github.com/google/fuzztest) tests MAVLink message handling and GNSS driver protocol parsing.
- **Input validation**: All external inputs (MAVLink messages, RC signals, sensor data) are validated against expected ranges before use.
- **Compiler hardening**: Builds use `-Wall -Werror`, stack protectors, and other hardening flags where supported by the target platform.
@@ -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

+1
View File
@@ -759,6 +759,7 @@
- [Receiving Messages](mavlink/receiving_messages.md)
- [Custom MAVLink Messages](mavlink/custom_messages.md)
- [Message Signing](mavlink/message_signing.md)
- [Security Hardening](mavlink/security_hardening.md)
- [Protocols/Microservices](mavlink/protocols.md)
- [Standard Modes Protocol](mavlink/standard_modes.md)
- [uXRCE-DDS (PX4-ROS 2/DDS Bridge)](middleware/uxrce_dds.md)
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
+4
View File
@@ -14,6 +14,10 @@ It also links instructions for how you can add PX4 support for:
- [Message Signing](../mavlink/message_signing.md)
- [Protocols/Microservices](../mavlink/protocols.md)
::: warning
MAVLink messages are unauthenticated by default. Without [message signing](../mavlink/message_signing.md) enabled, any device that can send MAVLink messages to the vehicle can execute commands including shell access, file operations, and flight termination. Production deployments must enable signing and follow the [Security Hardening](../mavlink/security_hardening.md) guide.
:::
::: info
We do not yet cover _command_ handling and sending, or how to implement your own microservices.
:::
+84
View File
@@ -0,0 +1,84 @@
# MAVLink Security Hardening for Production Deployments
<Badge type="tip" text="PX4 v1.17" />
MAVLink is an open communication protocol designed for lightweight, low-latency communication between drones and ground stations.
By default, all MAVLink messages are unauthenticated.
This is intentional for development and testing, but **production deployments must enable [message signing](message_signing.md)** to prevent unauthorized access.
::: warning
Without message signing enabled, any device that can send MAVLink messages to the vehicle (via radio, network, or serial) can execute any command, including shell access, file operations, parameter changes, mission uploads, arming, and flight termination.
:::
## What Is at Risk
When MAVLink signing is not enabled, an attacker within communication range can:
| Capability | MAVLink mechanism |
| ---------------------------- | ------------------------------------------------ |
| Execute shell commands | `SERIAL_CONTROL` with `SERIAL_CONTROL_DEV_SHELL` |
| Read, write, or delete files | MAVLink FTP protocol |
| Change any flight parameter | `PARAM_SET` / `PARAM_EXT_SET` |
| Upload or overwrite missions | Mission protocol |
| Arm or disarm motors | `MAV_CMD_COMPONENT_ARM_DISARM` |
| Terminate flight (crash) | `MAV_CMD_DO_FLIGHTTERMINATION` |
| Trigger emergency landing | Spoofed `BATTERY_STATUS` |
| Reboot the vehicle | `MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN` |
All of these are standard MAVLink capabilities used by ground control stations.
Without signing, there is no distinction between a legitimate GCS and an unauthorized sender.
## Hardening Checklist
### 1. Enable Message Signing
Message signing provides cryptographic authentication for all MAVLink communication.
See [Message Signing](message_signing.md) for full details.
Steps:
1. Connect the vehicle via **USB** (key provisioning only works over USB).
2. Provision a 32-byte secret key using the [SETUP_SIGNING](https://mavlink.io/en/messages/common.html#SETUP_SIGNING) message.
3. Set [MAV_SIGN_CFG](../advanced_config/parameter_reference.md#MAV_SIGN_CFG) to **1** (signing enabled on all links except USB) or **2** (signing on all links including USB).
4. Provision the same key on all ground control stations and companion computers that need to communicate with the vehicle.
5. Verify that unsigned messages from unknown sources are rejected.
::: info
`MAV_SIGN_CFG=1` is recommended for most deployments.
This enforces signing on telemetry radios and network links while allowing unsigned access over USB for maintenance.
USB connections require physical access to the vehicle, which provides equivalent security to physical key access.
:::
### 2. Secure Physical Access
- Protect access to the SD card. The signing key is stored at `/mavlink/mavlink-signing-key.bin` and can be read or removed by anyone with physical access.
- USB connections bypass signing when `MAV_SIGN_CFG=1`. Ensure USB ports are not exposed in deployed configurations.
### 3. Secure Network Links
- Do not expose MAVLink UDP/TCP ports to untrusted networks or the internet.
- Place MAVLink communication links behind firewalls or VPNs.
- Segment MAVLink networks from business or public networks.
- When using companion computers, audit which network interfaces MAVLink is bound to.
### 4. Understand the Limitations
- **No encryption**: Message signing provides authentication and integrity, but messages are sent in plaintext. An eavesdropper can read telemetry and commands but cannot forge them.
- **Allowlisted messages**: A small set of [safety-critical messages](message_signing.md#unsigned-message-allowlist) (RADIO_STATUS, ADSB_VEHICLE, COLLISION) are always accepted unsigned.
- **Key management**: There is no automatic key rotation. Keys must be reprovisioned manually via USB if compromised.
## Integrator Responsibility
PX4 is open-source flight controller firmware used by manufacturers and system integrators to build commercial and custom drone platforms.
Securing the communication links for a specific deployment is the responsibility of the system integrator.
This includes:
- Choosing appropriate radio hardware and link security
- Enabling and managing MAVLink message signing
- Restricting network access to MAVLink interfaces
- Applying firmware updates that address security issues
- Evaluating whether the default configuration meets the security requirements of the target application
PX4 provides the tools for securing MAVLink communication.
Integrators must enable and configure them for their deployment context.
+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)
- [DeviceInformation](../msg_docs/DeviceInformation.md)
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
- [Mission](../msg_docs/Mission.md)
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
- [LedControl](../msg_docs/LedControl.md)
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
- [LoggerStatus](../msg_docs/LoggerStatus.md)
- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md)
- [DebugVect](../msg_docs/DebugVect.md)
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
- [EscReport](../msg_docs/EscReport.md)
- [AirspeedWind](../msg_docs/AirspeedWind.md)
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
- [EscStatus](../msg_docs/EscStatus.md)
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
- [MountOrientation](../msg_docs/MountOrientation.md)
- [Cpuload](../msg_docs/Cpuload.md)
- [RaptorStatus](../msg_docs/RaptorStatus.md)
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
- [MavlinkLog](../msg_docs/MavlinkLog.md)
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
- [GainCompression](../msg_docs/GainCompression.md)
- [ActuatorTest](../msg_docs/ActuatorTest.md)
- [ButtonEvent](../msg_docs/ButtonEvent.md)
- [HeaterStatus](../msg_docs/HeaterStatus.md)
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
- [OrbTest](../msg_docs/OrbTest.md)
- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md)
- [FollowTarget](../msg_docs/FollowTarget.md)
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
- [QshellReq](../msg_docs/QshellReq.md)
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
- [TecsStatus](../msg_docs/TecsStatus.md)
- [Vtx](../msg_docs/Vtx.md)
- [SensorGyro](../msg_docs/SensorGyro.md)
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
- [GpioIn](../msg_docs/GpioIn.md)
- [DatamanResponse](../msg_docs/DatamanResponse.md)
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
- [GimbalControls](../msg_docs/GimbalControls.md)
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
- [SensorMag](../msg_docs/SensorMag.md)
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
- [VehicleCommandAckV0](../msg_docs/VehicleCommandAckV0.md)
- [QshellRetval](../msg_docs/QshellRetval.md)
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
- [RcChannels](../msg_docs/RcChannels.md)
- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md)
- [RtlStatus](../msg_docs/RtlStatus.md)
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
- [Rpm](../msg_docs/Rpm.md)
- [PwmInput](../msg_docs/PwmInput.md)
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
- [SensorUwb](../msg_docs/SensorUwb.md)
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
- [GpioRequest](../msg_docs/GpioRequest.md)
- [DebugValue](../msg_docs/DebugValue.md)
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
- [VelocityLimits](../msg_docs/VelocityLimits.md)
- [SensorCorrection](../msg_docs/SensorCorrection.md)
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
- [BatteryInfo](../msg_docs/BatteryInfo.md)
- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md)
- [GpioOut](../msg_docs/GpioOut.md)
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
- [MissionResult](../msg_docs/MissionResult.md)
- [TuneControl](../msg_docs/TuneControl.md)
- [WheelEncoders](../msg_docs/WheelEncoders.md)
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
- [HealthReport](../msg_docs/HealthReport.md)
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
- [CellularStatus](../msg_docs/CellularStatus.md)
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
- [VehicleRoi](../msg_docs/VehicleRoi.md)
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
- [PpsCapture](../msg_docs/PpsCapture.md)
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
- [ParameterUpdate](../msg_docs/ParameterUpdate.md)
- [ActionRequest](../msg_docs/ActionRequest.md)
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
- [DebugArray](../msg_docs/DebugArray.md)
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
- [SatelliteInfo](../msg_docs/SatelliteInfo.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)
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.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)
- [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)
- [CellularStatus](../msg_docs/CellularStatus.md)
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.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)
- [HomePositionV0](../msg_docs/HomePositionV0.md)
- [HealthReport](../msg_docs/HealthReport.md)
- [DifferentialPressure](../msg_docs/DifferentialPressure.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)
- [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)
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
- [GpsDump](../msg_docs/GpsDump.md)
- [GpioConfig](../msg_docs/GpioConfig.md)
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
- [GeofenceResult](../msg_docs/GeofenceResult.md)
- [EstimatorBias](../msg_docs/EstimatorBias.md)
- [SystemPower](../msg_docs/SystemPower.md)
- [EventV0](../msg_docs/EventV0.md)
- [CameraCapture](../msg_docs/CameraCapture.md)
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
- [HomePositionV0](../msg_docs/HomePositionV0.md)
- [VehicleGlobalPositionV0](../msg_docs/VehicleGlobalPositionV0.md)
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
- [EstimatorStates](../msg_docs/EstimatorStates.md)
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
- [FigureEightStatus](../msg_docs/FigureEightStatus.md)
- [InputRc](../msg_docs/InputRc.md)
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md)
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
- [DatamanRequest](../msg_docs/DatamanRequest.md)
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
- [NeuralControl](../msg_docs/NeuralControl.md)
- [DebugKeyValue](../msg_docs/DebugKeyValue.md)
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md)
- [CameraTrigger](../msg_docs/CameraTrigger.md)
- [PowerButtonState](../msg_docs/PowerButtonState.md)
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
- [VehicleStatusV1](../msg_docs/VehicleStatusV1.md)
- [AdcReport](../msg_docs/AdcReport.md)
- [SensorsStatus](../msg_docs/SensorsStatus.md)
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
- [UlogStream](../msg_docs/UlogStream.md)
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
- [SensorAccel](../msg_docs/SensorAccel.md)
- [PowerMonitor](../msg_docs/PowerMonitor.md)
- [OrbitStatus](../msg_docs/OrbitStatus.md)
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
- [Airspeed](../msg_docs/Airspeed.md)
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
- [RadioStatus](../msg_docs/RadioStatus.md)
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
- [VehicleAirData](../msg_docs/VehicleAirData.md)
- [SensorAirflow](../msg_docs/SensorAirflow.md)
- [Ping](../msg_docs/Ping.md)
- [MagWorkerData](../msg_docs/MagWorkerData.md)
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
- [GpsInjectData](../msg_docs/GpsInjectData.md)
- [Event](../msg_docs/Event.md)
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
- [RcParameterMap](../msg_docs/RcParameterMap.md)
- [Gripper](../msg_docs/Gripper.md)
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
- [VehicleImu](../msg_docs/VehicleImu.md)
- [SensorSelection](../msg_docs/SensorSelection.md)
- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md)
- [IrlockReport](../msg_docs/IrlockReport.md)
- [SensorTemp](../msg_docs/SensorTemp.md)
- [RaptorInput](../msg_docs/RaptorInput.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)
+4
View File
@@ -27,5 +27,9 @@
},
"devDependencies": {
"prettier": "^3.2.0"
},
"resolutions": {
"markdown-it": "^14.1.1",
"esbuild": "^0.25.0"
}
}
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
+487 -445
View File
File diff suppressed because it is too large Load Diff
+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)
@@ -645,7 +645,7 @@ int uORBTest::UnitTest::test_wrap_around()
}
#define CHECK_COPY(i_got, i_correct) \
orb_copy(ORB_ID(orb_test_medium_wrap_around), sfd, &u); \
if (i_got != i_correct) { \
if ((i_got) != (i_correct)) { \
return test_fail("got wrong element from the queue (got %i, should be %i)", i_got, i_correct); \
}
@@ -875,7 +875,7 @@ int uORBTest::UnitTest::test_queue()
}
#define CHECK_COPY(i_got, i_correct) \
orb_copy(ORB_ID(orb_test_medium_queue), sfd, &u); \
if (i_got != i_correct) { \
if ((i_got) != (i_correct)) { \
return test_fail("got wrong element from the queue (got %i, should be %i)", i_got, i_correct); \
}
@@ -88,7 +88,7 @@ typedef enum : int32_t {
TRIGGER_MODE_DISTANCE_ON_CMD
} trigger_mode_t;
#define commandParamToInt(n) static_cast<int>(n >= 0 ? n + 0.5f : n - 0.5f)
#define commandParamToInt(n) static_cast<int>((n) >= 0 ? (n) + 0.5f : (n) - 0.5f)
class CameraTrigger final : public px4::ScheduledWorkItem
{
@@ -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:
+2 -2
View File
@@ -51,8 +51,8 @@
# define debug(fmt, args...) do { } while(0)
#endif
#define CODER_CHECK(_c) do { if (_c->dead) { PX4_ERR("coder dead"); return -1; }} while(0)
#define CODER_KILL(_c, _reason) do { PX4_ERR("killed: %s", _reason); _c->dead = true; return -1; } while(0)
#define CODER_CHECK(_c) do { if ((_c)->dead) { PX4_ERR("coder dead"); return -1; }} while(0)
#define CODER_KILL(_c, _reason) do { PX4_ERR("killed: %s", _reason); (_c)->dead = true; return -1; } while(0)
static int
read_x(bson_decoder_t decoder, void *p, size_t s)
+1 -1
View File
@@ -46,7 +46,7 @@
#include <errno.h>
#define BEAT_TIME_CONVERSION_MS (60 * 1000 * 4)
#define BEAT_TIME_CONVERSION_US BEAT_TIME_CONVERSION_MS * 1000
#define BEAT_TIME_CONVERSION_US (BEAT_TIME_CONVERSION_MS * 1000)
#define BEAT_TIME_CONVERSION BEAT_TIME_CONVERSION_US
// semitone offsets from C for the characters 'A'-'G'
+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);
@@ -1,6 +1,5 @@
matplotlib==3.5.1
numpy==1.22.2
numpy==1.21.5
numpy_quaternion==2022.4.3
pyulog==0.9.0
scipy==1.8.0
+4 -2
View File
@@ -92,8 +92,10 @@ parameters:
by this parameter. The range sensor and vision options should only be used
when for operation over a flat surface as the local NED origin will move
up and down with ground level.
If GPS is set as reference but altitude fusion is disabled in EKF2_GPS_CTRL,
the GPS altitude is still used to initiaize the bias of the other height sensors.
If GPS is set as reference and EKF2_GPS_CTRL is not 0, the GPS altitude is
still used to initiaize the bias of the other height sensors, regardless of
the altitude fusion bit in EKF2_GPS_CTRL.
type: enum
values:
0: Barometric pressure
+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
@@ -118,6 +118,7 @@ else()
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generate_dds_topics.py
--client-outdir ${CMAKE_CURRENT_BINARY_DIR}
--dds-topics-file ${CMAKE_CURRENT_SOURCE_DIR}/dds_topics.yaml
--whitelist-file ${CMAKE_CURRENT_SOURCE_DIR}/safety_whitelist.yaml
--template_file ${CMAKE_CURRENT_SOURCE_DIR}/dds_topics.h.em
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/generate_dds_topics.py
+46 -4
View File
@@ -180,8 +180,10 @@ struct RcvTopicsPubs {
@[ end for]@
uint32_t num_payload_received{};
bool _allow_publishing{false};
bool init(uxrSession *session, uxrStreamId reliable_out_stream_id, uxrStreamId reliable_in_stream_id, uxrStreamId best_effort_in_stream_id, uxrObjectId participant_id, const char *client_namespace);
void allow_publishing(bool enabled) { _allow_publishing = enabled; }
};
static void on_topic_update(uxrSession *session, uxrObjectId object_id, uint16_t request_id, uxrStreamId stream_id,
@@ -196,10 +198,17 @@ static void on_topic_update(uxrSession *session, uxrObjectId object_id, uint16_t
case @(idx)+ (65535U / 32U) + 1: {
@(sub['simple_base_type'])_s data;
@[ if sub['topic_simple'] in whitelist_topics]@
if (ucdr_deserialize_@(sub['simple_base_type'])(*ub, data, time_offset_us)) {
//print_message(ORB_ID(@(sub['simple_base_type'])), data);
pubs->@(sub['topic_simple'])_pub.publish(data);
}
@[ else]@
if (pubs->_allow_publishing && ucdr_deserialize_@(sub['simple_base_type'])(*ub, data, time_offset_us)) {
//print_message(ORB_ID(@(sub['simple_base_type'])), data);
pubs->@(sub['topic_simple'])_pub.publish(data);
}
@[ end if]@
}
break;
@@ -208,9 +217,10 @@ static void on_topic_update(uxrSession *session, uxrObjectId object_id, uint16_t
case @(idx + len(subscriptions))+ (65535U / 32U) + 1: {
@(sub['simple_base_type'])_s data;
@[ if sub.get('route_field')]@
@[ if sub['topic_simple'] in whitelist_topics]@
if (ucdr_deserialize_@(sub['simple_base_type'])(*ub, data, time_offset_us)) {
//print_message(ORB_ID(@(sub['simple_base_type'])), data);
@[ if sub.get('route_field')]@
int instance = -1;
for (uint8_t i = 0; i < pubs->@(sub['topic_simple'])_demux.num_assigned; i++) {
@@ -228,10 +238,42 @@ static void on_topic_update(uxrSession *session, uxrObjectId object_id, uint16_t
if (instance >= 0) {
pubs->@(sub['topic_simple'])_pubs[instance].publish(data);
}
@[ else]@
pubs->@(sub['topic_simple'])_pub.publish(data);
@[ end if]@
}
@[ else]@
if (pubs->_allow_publishing && ucdr_deserialize_@(sub['simple_base_type'])(*ub, data, time_offset_us)) {
//print_message(ORB_ID(@(sub['simple_base_type'])), data);
int instance = -1;
for (uint8_t i = 0; i < pubs->@(sub['topic_simple'])_demux.num_assigned; i++) {
if (pubs->@(sub['topic_simple'])_demux.assigned_ids[i] == data.@(sub['route_field'])) {
instance = i;
break;
}
}
if (instance < 0 && pubs->@(sub['topic_simple'])_demux.num_assigned < @(sub['max_instances'])) {
instance = pubs->@(sub['topic_simple'])_demux.num_assigned++;
pubs->@(sub['topic_simple'])_demux.assigned_ids[instance] = data.@(sub['route_field']);
}
if (instance >= 0) {
pubs->@(sub['topic_simple'])_pubs[instance].publish(data);
}
}
@[ end if]@
@[ else]@
@[ if sub['topic_simple'] in whitelist_topics]@
if (ucdr_deserialize_@(sub['simple_base_type'])(*ub, data, time_offset_us)) {
//print_message(ORB_ID(@(sub['simple_base_type'])), data);
pubs->@(sub['topic_simple'])_pub.publish(data);
}
@[ else]@
if (pubs->_allow_publishing && ucdr_deserialize_@(sub['simple_base_type'])(*ub, data, time_offset_us)) {
//print_message(ORB_ID(@(sub['simple_base_type'])), data);
pubs->@(sub['topic_simple'])_pub.publish(data);
}
@[ end if]@
@[ end if]@
}
break;
@@ -51,6 +51,9 @@ parser.add_argument("-t", "--template_file", dest='template_file', type=str,
parser.add_argument("-u", "--client-outdir", dest='clientdir', type=str,
help="Client output dir, by default using relative path 'src/modules/uxrce_dds_client'", default=None)
parser.add_argument("-w", "--whitelist-file", dest='whitelist_file', type=str,
help="Whitelist topics file path for topics that publish regardless of _allow_publishing flag",
default=None)
if len(sys.argv) <= 1:
parser.print_usage()
@@ -138,6 +141,15 @@ merged_em_globals['subscriptions_multi'] = subs_multi
merged_em_globals['type_includes'] = sorted(set(all_type_includes))
# Load whitelist topics that should not be fail-safed
whitelist_topics = set()
if args.whitelist_file and os.path.exists(args.whitelist_file):
with open(args.whitelist_file, 'r') as f:
whitelist_data = yaml.safe_load(f)
if whitelist_data and '__whitelist' in whitelist_data:
whitelist_topics = set(whitelist_data['__whitelist'])
merged_em_globals['whitelist_topics'] = whitelist_topics
# run interpreter
ofile = open(output_file, 'w')
+11
View File
@@ -153,3 +153,14 @@ parameters:
category: System
reboot_required: true
default: 0
UXRCE_DDS_SAFE:
description:
short: Enables offboard safety protection
long: |
If disable, allows offboard passthrough
even in non-offboard modes.
type: boolean
category: System
reboot_required: true
default: 1
@@ -0,0 +1,4 @@
module_name: uxrce_dds_client
__whitelist:
- vehicle_command
@@ -374,6 +374,8 @@ bool UxrceddsClient::setupSession(uxrSession *session)
}
_connected = true;
_safe_dds_mode = _param_uxrce_dds_safe.get();
return true;
}
@@ -651,6 +653,16 @@ void UxrceddsClient::run()
int bytes_available = 0;
// Update vehicle status to check for offboard mode
vehicle_status_s vehicle_status{};
_vehicle_status_sub.copy(&vehicle_status);
_offboard_mode_enabled = (vehicle_status.nav_state == vehicle_status_s::NAVIGATION_STATE_OFFBOARD);
// Allow publish from DDS to uORB if:
// - _param_uxrce_dds_safe is false , regardless of offboard mode
// - _param_uxrce_dds_safe is true AND offboard mode is enabled
_pubs->allow_publishing(!_safe_dds_mode || (_safe_dds_mode && _offboard_mode_enabled));
if (ioctl(_fd, FIONREAD, (unsigned long)&bytes_available) == OK) {
if (bytes_available > 10) {
orb_poll_timeout_ms = 0;
@@ -41,6 +41,7 @@
#include <uORB/topics/message_format_request.h>
#include <uORB/topics/message_format_response.h>
#include <uORB/Subscription.hpp>
#include <uORB/topics/vehicle_status.h>
#include <lib/timesync/Timesync.hpp>
@@ -138,6 +139,7 @@ private:
uORB::Publication<message_format_response_s> _message_format_response_pub{ORB_ID(message_format_response)};
uORB::Subscription _message_format_request_sub{ORB_ID(message_format_request)};
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
/** Synchronizes the system clock if the time is off by more than 5 seconds */
void syncSystemClock(uxrSession *session);
@@ -202,6 +204,8 @@ private:
bool _connected{false};
bool _session_created{false};
bool _timesync_converged{false};
bool _offboard_mode_enabled{false};
bool _safe_dds_mode{true};
Timesync _timesync{timesync_status_s::SOURCE_PROTOCOL_DDS};
@@ -216,6 +220,7 @@ private:
(ParamInt<px4::params::UXRCE_DDS_SYNCT>) _param_uxrce_dds_synct,
(ParamInt<px4::params::UXRCE_DDS_TX_TO>) _param_uxrce_dds_tx_to,
(ParamInt<px4::params::UXRCE_DDS_RX_TO>) _param_uxrce_dds_rx_to,
(ParamInt<px4::params::UXRCE_DDS_FLCTRL>) _param_uxrce_dds_flctrl
(ParamInt<px4::params::UXRCE_DDS_FLCTRL>) _param_uxrce_dds_flctrl,
(ParamInt<px4::params::UXRCE_DDS_SAFE>) _param_uxrce_dds_safe
)
};