From 585a615e64cc9e6a98d026f236524adaef13c825 Mon Sep 17 00:00:00 2001 From: Edvard Sire Date: Mon, 24 Nov 2025 16:17:13 +0000 Subject: [PATCH 01/23] Fix typo in OS version field name --- docs/en/dev_log/ulog_file_format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/dev_log/ulog_file_format.md b/docs/en/dev_log/ulog_file_format.md index a1caea44e9..18a065797f 100644 --- a/docs/en/dev_log/ulog_file_format.md +++ b/docs/en/dev_log/ulog_file_format.md @@ -215,7 +215,7 @@ Predefined information messages are: | `char[value_len] ver_sw_branch` | git branch | "master" | | `uint32_t ver_sw_release` | Software version (see below) | 0x010401ff | | `char[value_len] sys_os_name` | Operating System Name | "Linux" | -| `char[value_len] sys_os_ve`r | OS version (git tag) | "9f82919" | +| `char[value_len] sys_os_ver` | OS version (git tag) | "9f82919" | | `uint32_t ver_os_release` | OS version (see below) | 0x010401ff | | `char[value_len] sys_toolchain` | Toolchain Name | "GNU GCC" | | `char[value_len] sys_toolchain_ver` | Toolchain Version | "6.2.1" | From 921e91863a8ddbd6d94569030ac2c5a2185c0aae Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Sun, 23 Nov 2025 18:51:07 +0100 Subject: [PATCH 02/23] dshot: IMXRT BDSHOT baud training AM32 bdshot doesn't do clock compensation like BLHeli32 did. Instead we traing BDSHOT timing on known zero value to lock on best bdshot baudrate to receive. Reduces CRC and frame errors on AM32 a lot --- .../nuttx/src/px4/nxp/imxrt/dshot/dshot.c | 101 ++++++++++++++++-- 1 file changed, 91 insertions(+), 10 deletions(-) diff --git a/platforms/nuttx/src/px4/nxp/imxrt/dshot/dshot.c b/platforms/nuttx/src/px4/nxp/imxrt/dshot/dshot.c index d0558592a5..7bd2508ddf 100644 --- a/platforms/nuttx/src/px4/nxp/imxrt/dshot/dshot.c +++ b/platforms/nuttx/src/px4/nxp/imxrt/dshot/dshot.c @@ -74,26 +74,40 @@ typedef enum { BDSHOT_RECEIVE_COMPLETE, } dshot_state; -typedef struct dshot_handler_t { +typedef struct dshot_channel_t { bool init; uint32_t data_seg1; uint32_t irq_data; dshot_state state; - bool bdshot; uint32_t raw_response; uint16_t erpm; uint32_t crc_error_cnt; uint32_t frame_error_cnt; uint32_t no_response_cnt; uint32_t last_no_response_cnt; -} dshot_handler_t; + bool bdshot; + uint32_t bdshot_tcmp; + uint32_t bdshot_training_mask; + uint8_t bdshot_training_count; + uint8_t bdshot_training_success; + bool bdshot_training_done; + int8_t bdshot_tcmp_offset; +} dshot_channel_t; #define BDSHOT_OFFLINE_COUNT 400 // If there are no responses for 400 setpoints ESC is offline -static dshot_handler_t dshot_inst[DSHOT_TIMERS] = {}; +#define BDSHOT_TCMP_MIN_OFFSET -16 +#define BDSHOT_TCMP_MAX_OFFSET 15 +#define BDSHOT_TCMP_TO_MASK(x) ((x) - BDSHOT_TCMP_MIN_OFFSET) +#define BDSHOT_TRAINING_TRIES 200 +#define BDSHOT_TRAINING_SUCCESS 198 + +#define BDSHOT_ZERO_RESPONSE 0x52951 + +static dshot_channel_t dshot_inst[DSHOT_TIMERS] = {}; static uint32_t dshot_tcmp; -static uint32_t bdshot_tcmp; +static unsigned dshot_speed; static uint32_t dshot_mask; static uint32_t bdshot_recv_mask; static uint32_t bdshot_parsed_recv_mask; @@ -155,6 +169,12 @@ static inline void clear_timer_status_flags(uint32_t mask) flexio_putreg32(mask, IMXRT_FLEXIO_TIMSTAT_OFFSET); } +static inline void flexio_dshot_set_tcmp(uint32_t channel) +{ + dshot_inst[channel].bdshot_tcmp = 0x2900 | (((BOARD_FLEXIO_PREQ / (dshot_speed * 5 / 4) / 2) + + dshot_inst[channel].bdshot_tcmp_offset) & 0xFF); +} + static void flexio_dshot_output(uint32_t channel, uint32_t pin, uint32_t timcmp, bool inverted) { /* Disable Shifter */ @@ -278,7 +298,7 @@ static int flexio_irq_handler(int irq, void *context, void *arg) IMXRT_FLEXIO_TIMCFG0_OFFSET + channel * 0x4); /* Enable on pin transition, resychronize through reset on rising edge */ - flexio_putreg32(bdshot_tcmp, IMXRT_FLEXIO_TIMCMP0_OFFSET + channel * 0x4); + flexio_putreg32(dshot_inst[channel].bdshot_tcmp, IMXRT_FLEXIO_TIMCMP0_OFFSET + channel * 0x4); /* Trigger on FXIO pin transition, Baud mode */ flexio_putreg32(FLEXIO_TIMCTL_TRGSEL(2 * timer_io_channels[channel].dshot.flexio_pin) | @@ -305,7 +325,7 @@ int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq, bool enable_bi { /* Calculate dshot timings based on dshot_pwm_freq */ dshot_tcmp = 0x2F00 | (((BOARD_FLEXIO_PREQ / (dshot_pwm_freq * 3) / 2) - 1) & 0xFF); - bdshot_tcmp = 0x2900 | (((BOARD_FLEXIO_PREQ / (dshot_pwm_freq * 5 / 4) / 2) - 3) & 0xFF); + dshot_speed = dshot_pwm_freq; /* Clock FlexIO peripheral */ imxrt_clockall_flexio1(); @@ -340,7 +360,16 @@ int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq, bool enable_bi imxrt_config_gpio(timer_io_channels[channel].dshot.pinmux | IOMUX_PULL_UP); - dshot_inst[channel].bdshot = enable_bidirectional_dshot; + if (enable_bidirectional_dshot) { + dshot_inst[channel].bdshot = true; + dshot_inst[channel].bdshot_training_mask = 0; + dshot_inst[channel].bdshot_tcmp_offset = BDSHOT_TCMP_MIN_OFFSET; + dshot_inst[channel].bdshot_training_done = false; + flexio_dshot_set_tcmp(channel); + + } else { + dshot_inst[channel].bdshot = false; + } flexio_dshot_output(channel, timer_io_channels[channel].dshot.flexio_pin, dshot_tcmp, dshot_inst[channel].bdshot); @@ -357,6 +386,52 @@ int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq, bool enable_bi return channel_mask; } +void up_bdshot_training(uint32_t channel, uint32_t value) +{ + dshot_channel_t *ch = &dshot_inst[channel]; + + if (value == BDSHOT_ZERO_RESPONSE) { + // Count successful responses + ch->bdshot_training_success++; + + } else if ((value & 0x1) == 0) { + // Invalidate frame error immediately + ch->bdshot_training_count = BDSHOT_TRAINING_TRIES - 1; + } + + // Keep count and check if a training round finished + ch->bdshot_training_count++; + + if (ch->bdshot_training_count == BDSHOT_TRAINING_TRIES) { + if (ch->bdshot_training_success >= BDSHOT_TRAINING_SUCCESS) { + ch->bdshot_training_mask |= + (1 << BDSHOT_TCMP_TO_MASK(ch->bdshot_tcmp_offset)); + } + + ch->bdshot_training_count = 0; + ch->bdshot_training_success = 0; + ch->bdshot_tcmp_offset++; + + if (ch->bdshot_tcmp_offset == BDSHOT_TCMP_MAX_OFFSET) { + + if (ch->bdshot_training_mask == 0) { + // No candidates retry + ch->bdshot_tcmp_offset = BDSHOT_TCMP_MIN_OFFSET; + + } else { + // Training done, use mask to find best offset + int low = __builtin_ctz(ch->bdshot_training_mask); + int high = 31 - __builtin_clz(ch->bdshot_training_mask); + ch->bdshot_tcmp_offset = ((low + high) / 2) + BDSHOT_TCMP_MIN_OFFSET; + ch->bdshot_training_done = true; + } + } + + // Update TCMP + flexio_dshot_set_tcmp(channel); + } +} + void up_bdshot_erpm(void) { uint32_t value; @@ -373,8 +448,12 @@ void up_bdshot_erpm(void) if (bdshot_recv_mask & (1 << channel)) { value = ~dshot_inst[channel].raw_response & 0xFFFFF; - /* if lowest significant isn't 1 we've got a framing error */ - if (value & 0x1) { + // BDSHOT ESC hardware varies and timings differ between units. + // Run training to estimate the correct baudrate to lock onto. + if (!dshot_inst[channel].bdshot_training_done) { + up_bdshot_training(channel, value); + + } else if (value & 0x1) { /* if lowest significant isn't 1 we've got a framing error */ /* Decode RLL */ value = (value ^ (value >> 1)); @@ -461,6 +540,8 @@ void up_bdshot_status(void) if (dshot_inst[channel].init) { PX4_INFO("Channel %i %s Last erpm %i value", channel, up_bdshot_channel_status(channel) ? "online" : "offline", dshot_inst[channel].erpm); + PX4_INFO("BDSHOT Training done: %s TCMP offset: %d", dshot_inst[channel].bdshot_training_done ? "YES" : "NO", + dshot_inst[channel].bdshot_tcmp_offset); PX4_INFO("CRC errors Frame error No response"); PX4_INFO("%10lu %11lu %11lu", dshot_inst[channel].crc_error_cnt, dshot_inst[channel].frame_error_cnt, dshot_inst[channel].no_response_cnt); From 5f7e395609afa89936e43837f306e59b0dcea494 Mon Sep 17 00:00:00 2001 From: Alexis Guijarro Date: Sat, 22 Nov 2025 15:34:49 -0600 Subject: [PATCH 03/23] NuttX: Add support for FM25V02A-DGQ --- platforms/nuttx/NuttX/nuttx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/nuttx/NuttX/nuttx b/platforms/nuttx/NuttX/nuttx index fb2fadf6f5..201d8b01f1 160000 --- a/platforms/nuttx/NuttX/nuttx +++ b/platforms/nuttx/NuttX/nuttx @@ -1 +1 @@ -Subproject commit fb2fadf6f599c1406f052db013efd00a2518e72c +Subproject commit 201d8b01f14269a9647ef6da499214ffd39ff8f0 From a6d9e114beabe425b2221b63ab61da40944ca16e Mon Sep 17 00:00:00 2001 From: Alexis Guijarro Date: Sat, 22 Nov 2025 15:35:54 -0600 Subject: [PATCH 04/23] Revert "3DR Control Zero H7 OEM RevG: MTD driver fix (#25015)" This reverts commit 26499b3c8bcf9896071d0d057a207c9162f8558c. --- .../nuttx-config/scripts/script.ld | 1 - .../ctrl-zero-h7-oem-revg/src/CMakeLists.txt | 1 - boards/3dr/ctrl-zero-h7-oem-revg/src/mtd.cpp | 76 ------------------- 3 files changed, 78 deletions(-) delete mode 100644 boards/3dr/ctrl-zero-h7-oem-revg/src/mtd.cpp diff --git a/boards/3dr/ctrl-zero-h7-oem-revg/nuttx-config/scripts/script.ld b/boards/3dr/ctrl-zero-h7-oem-revg/nuttx-config/scripts/script.ld index 45b12075e5..02e763a790 100755 --- a/boards/3dr/ctrl-zero-h7-oem-revg/nuttx-config/scripts/script.ld +++ b/boards/3dr/ctrl-zero-h7-oem-revg/nuttx-config/scripts/script.ld @@ -132,7 +132,6 @@ ENTRY(_stext) */ EXTERN(abort) EXTERN(_bootdelay_signature) -EXTERN(board_get_manifest) SECTIONS { diff --git a/boards/3dr/ctrl-zero-h7-oem-revg/src/CMakeLists.txt b/boards/3dr/ctrl-zero-h7-oem-revg/src/CMakeLists.txt index 1a47c940b7..6a7d2ce306 100755 --- a/boards/3dr/ctrl-zero-h7-oem-revg/src/CMakeLists.txt +++ b/boards/3dr/ctrl-zero-h7-oem-revg/src/CMakeLists.txt @@ -48,7 +48,6 @@ else() i2c.cpp init.c led.c - mtd.cpp spi.cpp timer_config.cpp usb.c diff --git a/boards/3dr/ctrl-zero-h7-oem-revg/src/mtd.cpp b/boards/3dr/ctrl-zero-h7-oem-revg/src/mtd.cpp deleted file mode 100644 index c1b0f1bac3..0000000000 --- a/boards/3dr/ctrl-zero-h7-oem-revg/src/mtd.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2025 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. - * - ****************************************************************************/ - -#include -#include -// KiB BS nB -static const px4_mft_device_t spi2 = { // FM25V01A on FMUM native: 32K X 8, emulated as (1024 Blocks of 32) - .bus_type = px4_mft_device_t::SPI, - .devid = SPIDEV_FLASH(0) -}; - -static const px4_mtd_entry_t fmum_fram = { - .device = &spi2, - .npart = 1, - .partd = { - { - .type = MTD_PARAMETERS, - .path = "/fs/mtd_params", - .nblocks = (32768 / (1 << CONFIG_RAMTRON_EMULATE_PAGE_SHIFT)) - }, - }, -}; - -static const px4_mtd_manifest_t board_mtd_config = { - .nconfigs = 1, - .entries = { - &fmum_fram - } -}; - -static const px4_mft_entry_s mtd_mft = { - .type = MTD, - .pmft = (void *) &board_mtd_config, -}; - -static const px4_mft_s mft = { - .nmft = 1, - .mfts = { - &mtd_mft - } -}; - -const px4_mft_s *board_get_manifest(void) -{ - return &mft; -} From 6901bc6a016a5cdcac2dfb90cd721aa29d5897d2 Mon Sep 17 00:00:00 2001 From: Jacopo Panerati Date: Tue, 25 Nov 2025 03:46:48 -0500 Subject: [PATCH 05/23] VTOL Takeoff: Use VehicleCommand specified heading for VTOL transition (#24040) * Use VehicleCommand heading for VTOL transition * options for param2 of vehicle_cmd_nav_vtol_takeoff --- msg/versioned/VehicleCommand.msg | 2 +- src/modules/navigator/navigator_main.cpp | 4 ++++ src/modules/navigator/vtol_takeoff.cpp | 11 +++++++++-- src/modules/navigator/vtol_takeoff.h | 2 ++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/msg/versioned/VehicleCommand.msg b/msg/versioned/VehicleCommand.msg index 8f20ec2d85..b5d642b140 100644 --- a/msg/versioned/VehicleCommand.msg +++ b/msg/versioned/VehicleCommand.msg @@ -20,7 +20,7 @@ uint16 VEHICLE_CMD_DO_ORBIT = 34 # Start orbiting on the circumference of a circ uint16 VEHICLE_CMD_DO_FIGUREEIGHT = 35 # Start flying on the outline of a figure eight defined by the parameters. |[m] Major radius|[m] Minor radius|[m/s] Velocity|Orientation|Latitude/X|Longitude/Y|Altitude/Z| uint16 VEHICLE_CMD_NAV_ROI = 80 # Sets the region of interest (ROI) for a sensor set or the vehicle itself. This can then be used by the vehicles control system to control the vehicle attitude and the attitude of various sensors such as cameras. |[@enum VEHICLE_ROI] Region of interest mode.|MISSION index/ target ID.|ROI index (allows a vehicle to manage multiple ROI's)|Unused|x the location of the fixed ROI (see MAV_FRAME)|y|z| uint16 VEHICLE_CMD_NAV_PATHPLANNING = 81 # Control autonomous path planning on the MAV. |0: Disable local obstacle avoidance / local path planning (without resetting map), 1: Enable local path planning, 2: Enable and reset local path planning|0: Disable full path planning (without resetting map), 1: Enable, 2: Enable and reset map/occupancy grid, 3: Enable and reset planned route, but not occupancy grid|Unused|[deg] [@range 0, 360] Yaw angle at goal, in compass degrees|Latitude/X of goal|Longitude/Y of goal|Altitude/Z of goal| -uint16 VEHICLE_CMD_NAV_VTOL_TAKEOFF = 84 # Takeoff from ground / hand and transition to fixed wing. |Minimum pitch (if airspeed sensor present), desired pitch without sensor|Unused|Unused|Yaw angle (if magnetometer present), ignored without magnetometer|Latitude|Longitude|Altitude| +uint16 VEHICLE_CMD_NAV_VTOL_TAKEOFF = 84 # Takeoff from ground / hand and transition to fixed wing. |Minimum pitch (if airspeed sensor present), desired pitch without sensor|Transition heading, 0: Default, 3: Use specified transition heading|Unused|Yaw angle (if magnetometer present), ignored without magnetometer|Latitude|Longitude|Altitude| uint16 VEHICLE_CMD_NAV_VTOL_LAND = 85 # Transition to MC and land at location. |Unused|Unused|Unused|Desired yaw angle.|Latitude|Longitude|Altitude| uint16 VEHICLE_CMD_NAV_GUIDED_LIMITS = 90 # Set limits for external control. |[s] Timeout - maximum time that external controller will be allowed to control vehicle. 0 means no timeout|[m] Absolute altitude min AMSL - if vehicle moves below this alt, the command will be aborted and the mission will continue. 0 means no lower altitude limit|[m] Absolute altitude max - if vehicle moves above this alt, the command will be aborted and the mission will continue. 0 means no upper altitude limit|[m] Horizontal move limit (AMSL) - if vehicle moves more than this distance from it's location at the moment the command was executed, the command will be aborted and the mission will continue. 0 means no horizontal altitude limit|Unused|Unused|Unused| uint16 VEHICLE_CMD_NAV_GUIDED_MASTER = 91 # Set id of master controller. |System ID|Component ID|Unused|Unused|Unused|Unused|Unused| diff --git a/src/modules/navigator/navigator_main.cpp b/src/modules/navigator/navigator_main.cpp index 3430bc0162..c7bdd337b5 100644 --- a/src/modules/navigator/navigator_main.cpp +++ b/src/modules/navigator/navigator_main.cpp @@ -652,6 +652,10 @@ void Navigator::run() _vtol_takeoff.setTransitionAltitudeAbsolute(cmd.param7); + if (std::fabs(cmd.param2 - 3.0f) < FLT_EPSILON) { // Specified transition direction + _vtol_takeoff.setTransitionDirection(cmd.param4); + } + // after the transition the vehicle will establish on a loiter at this position _vtol_takeoff.setLoiterLocation(matrix::Vector2d(cmd.param5, cmd.param6)); diff --git a/src/modules/navigator/vtol_takeoff.cpp b/src/modules/navigator/vtol_takeoff.cpp index 686886a911..b78f5f6e21 100644 --- a/src/modules/navigator/vtol_takeoff.cpp +++ b/src/modules/navigator/vtol_takeoff.cpp @@ -71,8 +71,15 @@ VtolTakeoff::on_active() position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet(); _mission_item.nav_cmd = NAV_CMD_WAYPOINT; - _mission_item.yaw = wrap_pi(get_bearing_to_next_waypoint(_mission_item.lat, - _mission_item.lon, _loiter_location(0), _loiter_location(1))); + + if (!PX4_ISFINITE(_transition_direction_deg)) { + _mission_item.yaw = wrap_pi(get_bearing_to_next_waypoint(_navigator->get_home_position()->lat, + _navigator->get_home_position()->lon, _loiter_location(0), _loiter_location(1))); + + } else { + _mission_item.yaw = wrap_pi(math::radians(_transition_direction_deg)); + } + _mission_item.force_heading = true; mission_item_to_position_setpoint(_mission_item, &pos_sp_triplet->current); pos_sp_triplet->current.cruising_speed = -1.f; diff --git a/src/modules/navigator/vtol_takeoff.h b/src/modules/navigator/vtol_takeoff.h index 3ba32ce7df..162209893d 100644 --- a/src/modules/navigator/vtol_takeoff.h +++ b/src/modules/navigator/vtol_takeoff.h @@ -55,6 +55,7 @@ public: void on_active() override; void setTransitionAltitudeAbsolute(const float alt_amsl) {_transition_alt_amsl = alt_amsl; } + void setTransitionDirection(const float tran_bear) {_transition_direction_deg = tran_bear; } void setLoiterLocation(matrix::Vector2d loiter_location) { _loiter_location = loiter_location; } void setLoiterHeight(const float height_m) { _loiter_height = height_m; } @@ -73,6 +74,7 @@ private: float _takeoff_alt_msl{0.f}; matrix::Vector2d _loiter_location; float _loiter_height{0}; + float _transition_direction_deg{NAN}; DEFINE_PARAMETERS( (ParamFloat) _param_loiter_alt From a5145601699dfd7d3160c7a4ac41d8c75aa1144d Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Wed, 17 Sep 2025 00:27:18 +0800 Subject: [PATCH 06/23] [crsf_rc] Add support for link statistic messages --- docs/en/releases/main.md | 4 ++ msg/InputRc.msg | 2 + src/drivers/rc/crsf_rc/CrsfParser.cpp | 68 ++++++++++++++++++++++----- src/drivers/rc/crsf_rc/CrsfParser.hpp | 20 ++++++++ src/drivers/rc/crsf_rc/CrsfRc.cpp | 31 +++++++++++- src/drivers/rc/crsf_rc/CrsfRc.hpp | 1 + 6 files changed, 111 insertions(+), 15 deletions(-) diff --git a/docs/en/releases/main.md b/docs/en/releases/main.md index 3931d565b4..a8c1805fbb 100644 --- a/docs/en/releases/main.md +++ b/docs/en/releases/main.md @@ -76,6 +76,10 @@ Please continue reading for [upgrade instructions](#upgrade-guide). - TBD +### RC + +- Parse ELRS Status and Link Statistics TX messages in the CRSF parser. + ### Multi-Rotor - Removed parameters `MPC_{XY/Z/YAW}_MAN_EXPO` and use default value instead, as they were not deemed necessary anymore. ([PX4-Autopilot#25435: Add new flight mode: Altitude Cruise](https://github.com/PX4/PX4-Autopilot/pull/25435)). diff --git a/msg/InputRc.msg b/msg/InputRc.msg index 782477407e..2f72125ab8 100644 --- a/msg/InputRc.msg +++ b/msg/InputRc.msg @@ -32,9 +32,11 @@ bool rc_lost # RC receiver connection status: True,if no frame has arrived in uint16 rc_lost_frame_count # Number of lost RC frames. Note: intended purpose: observe the radio link quality if RSSI is not available. This value must not be used to trigger any failsafe-alike functionality. uint16 rc_total_frame_count # Number of total RC frames. Note: intended purpose: observe the radio link quality if RSSI is not available. This value must not be used to trigger any failsafe-alike functionality. uint16 rc_ppm_frame_length # Length of a single PPM frame. Zero for non-PPM systems +uint16 rc_frame_rate # RC frame rate in msg/second. 0 = invalid uint8 input_source # Input source uint16[18] values # measured pulse widths for each of the supported channels int8 link_quality # link quality. Percentage 0-100%. -1 = invalid float32 rssi_dbm # Actual rssi in units of dBm. NaN = invalid +int8 link_snr # link signal to noise ratio in units of dB. -1 = invalid diff --git a/src/drivers/rc/crsf_rc/CrsfParser.cpp b/src/drivers/rc/crsf_rc/CrsfParser.cpp index a81fe930f5..61d2029b0d 100644 --- a/src/drivers/rc/crsf_rc/CrsfParser.cpp +++ b/src/drivers/rc/crsf_rc/CrsfParser.cpp @@ -57,8 +57,10 @@ enum CRSF_PAYLOAD_SIZE { CRSF_PAYLOAD_SIZE_GPS = 15, CRSF_PAYLOAD_SIZE_BATTERY = 8, CRSF_PAYLOAD_SIZE_LINK_STATISTICS = 10, + CRSF_PAYLOAD_SIZE_LINK_STATISTICS_TX = -1, CRSF_PAYLOAD_SIZE_RC_CHANNELS = 22, CRSF_PAYLOAD_SIZE_ATTITUDE = 6, + CRSF_PAYLOAD_SIZE_ELRS_STATUS = -1, // unclear how large this message is }; enum CRSF_PACKET_TYPE { @@ -68,6 +70,8 @@ enum CRSF_PACKET_TYPE { CRSF_PACKET_TYPE_OPENTX_SYNC = 0x10, CRSF_PACKET_TYPE_RADIO_ID = 0x3A, CRSF_PACKET_TYPE_RC_CHANNELS_PACKED = 0x16, + CRSF_PACKET_TYPE_LINK_STATISTICS_RX = 0x1C, + CRSF_PACKET_TYPE_LINK_STATISTICS_TX = 0x1D, CRSF_PACKET_TYPE_ATTITUDE = 0x1E, CRSF_PACKET_TYPE_FLIGHT_MODE = 0x21, // Extended Header Frames, range: 0x28 to 0x96 @@ -76,6 +80,7 @@ enum CRSF_PACKET_TYPE { CRSF_PACKET_TYPE_PARAMETER_SETTINGS_ENTRY = 0x2B, CRSF_PACKET_TYPE_PARAMETER_READ = 0x2C, CRSF_PACKET_TYPE_PARAMETER_WRITE = 0x2D, + CRSF_PACKET_TYPE_ELRS_STATUS = 0x2E, CRSF_PACKET_TYPE_COMMAND = 0x32, // MSP commands CRSF_PACKET_TYPE_MSP_REQ = 0x7A, // response request using msp sequence as command @@ -114,18 +119,22 @@ enum PARSER_STATE { typedef struct { uint8_t packet_type; - uint32_t packet_size; + int32_t packet_size; bool (*processor)(const uint8_t *data, const uint32_t size, CrsfPacket_t *const new_packet); } CrsfPacketDescriptor_t; static bool ProcessChannelData(const uint8_t *data, const uint32_t size, CrsfPacket_t *const new_packet); static bool ProcessLinkStatistics(const uint8_t *data, const uint32_t size, CrsfPacket_t *const new_packet); +static bool ProcessLinkStatisticsTx(const uint8_t *data, const uint32_t size, CrsfPacket_t *const new_packet); +static bool ProcessElrsStatus(const uint8_t *data, const uint32_t size, CrsfPacket_t *const new_packet); -#define CRSF_PACKET_DESCRIPTOR_COUNT 2 -static const CrsfPacketDescriptor_t crsf_packet_descriptors[CRSF_PACKET_DESCRIPTOR_COUNT] = { +static const CrsfPacketDescriptor_t crsf_packet_descriptors[] = { {CRSF_PACKET_TYPE_RC_CHANNELS_PACKED, CRSF_PAYLOAD_SIZE_RC_CHANNELS, ProcessChannelData}, {CRSF_PACKET_TYPE_LINK_STATISTICS, CRSF_PAYLOAD_SIZE_LINK_STATISTICS, ProcessLinkStatistics}, + {CRSF_PACKET_TYPE_LINK_STATISTICS_TX, CRSF_PAYLOAD_SIZE_LINK_STATISTICS_TX, ProcessLinkStatisticsTx}, + {CRSF_PACKET_TYPE_ELRS_STATUS, CRSF_PAYLOAD_SIZE_ELRS_STATUS, ProcessElrsStatus}, }; +#define CRSF_PACKET_DESCRIPTOR_COUNT (sizeof(crsf_packet_descriptors) / sizeof(CrsfPacketDescriptor_t)) static enum PARSER_STATE parser_state = PARSER_STATE_HEADER; static uint32_t working_index = 0; @@ -201,7 +210,7 @@ static bool ProcessLinkStatistics(const uint8_t *data, const uint32_t size, Crsf new_packet->message_type = CRSF_MESSAGE_TYPE_LINK_STATISTICS; new_packet->link_statistics.uplink_rssi_1 = data[0]; - new_packet->link_statistics.uplink_rssi_2 = data[1]; + new_packet->link_statistics.uplink_rssi_2 = data[1]; new_packet->link_statistics.uplink_link_quality = data[2]; new_packet->link_statistics.uplink_snr = data[3]; new_packet->link_statistics.active_antenna = data[4]; @@ -214,6 +223,34 @@ static bool ProcessLinkStatistics(const uint8_t *data, const uint32_t size, Crsf return true; } +static bool ProcessLinkStatisticsTx(const uint8_t *data, const uint32_t size, CrsfPacket_t *const new_packet) +{ + new_packet->message_type = CRSF_MESSAGE_TYPE_LINK_STATISTICS_TX; + + new_packet->link_statistics_tx.uplink_rssi = data[0]; + new_packet->link_statistics_tx.uplink_rssi_pct = data[1]; + new_packet->link_statistics_tx.uplink_link_quality = data[2]; + new_packet->link_statistics_tx.uplink_snr = data[3]; + new_packet->link_statistics_tx.downlink_power = data[4]; + new_packet->link_statistics_tx.uplink_fps = data[5]; + + return true; +} + +static bool ProcessElrsStatus(const uint8_t *data, const uint32_t size, CrsfPacket_t *const new_packet) +{ + new_packet->message_type = CRSF_MESSAGE_TYPE_ELRS_STATUS; + + // Try: crsf_rc inject 0x2E 0x13 0x50 0xFB 0x53 0x31 0x63 0x63 0x63 0x63 + + new_packet->elrs_status.packets_bad = data[2]; + new_packet->elrs_status.packets_good = (data[3] << 8) | data[4]; + new_packet->elrs_status.flags = data[5]; + strlcpy(new_packet->elrs_status.message, (const char *)&data[6], sizeof(new_packet->elrs_status.message)); + + return true; +} + static CrsfPacketDescriptor_t *FindCrsfDescriptor(const enum CRSF_PACKET_TYPE packet_type) { uint32_t i; @@ -280,16 +317,21 @@ bool CrsfParser_TryParseCrsfPacket(CrsfPacket_t *const new_packet, CrsfParserSta // If we know what this packet is... if (working_descriptor != NULL) { // Validate length - if (packet_size != working_descriptor->packet_size + PACKET_SIZE_TYPE_SIZE) { - parser_statistics->invalid_known_packet_sizes++; - parser_state = PARSER_STATE_HEADER; - working_segment_size = HEADER_SIZE; - working_index = 0; - buffer_count = QueueBuffer_Count(&rx_queue); - continue; - } + if (working_descriptor->packet_size == -1) { + working_segment_size = packet_size - PACKET_SIZE_TYPE_SIZE; - working_segment_size = working_descriptor->packet_size; + } else { + if (packet_size != working_descriptor->packet_size + PACKET_SIZE_TYPE_SIZE) { + parser_statistics->invalid_known_packet_sizes++; + parser_state = PARSER_STATE_HEADER; + working_segment_size = HEADER_SIZE; + working_index = 0; + buffer_count = QueueBuffer_Count(&rx_queue); + continue; + } + + working_segment_size = working_descriptor->packet_size; + } } else { // We don't know what this packet is, so we'll let the parser continue diff --git a/src/drivers/rc/crsf_rc/CrsfParser.hpp b/src/drivers/rc/crsf_rc/CrsfParser.hpp index c0bf0e8494..167cd6466e 100644 --- a/src/drivers/rc/crsf_rc/CrsfParser.hpp +++ b/src/drivers/rc/crsf_rc/CrsfParser.hpp @@ -63,6 +63,22 @@ struct CrsfLinkStatistics_t { int8_t downlink_snr; }; +struct CrsfLinkStatisticsTx_t { + uint8_t uplink_rssi; + uint8_t uplink_rssi_pct; + uint8_t uplink_link_quality; + int8_t uplink_snr; + uint8_t downlink_power; + uint8_t uplink_fps; +}; + +struct CrsfElrsStatus_t { + uint8_t packets_bad; + uint16_t packets_good; + uint8_t flags; + char message[48]; +}; + struct CrsfParserStatistics_t { uint32_t disposed_bytes; uint32_t crcs_valid_known_packets; @@ -75,6 +91,8 @@ struct CrsfParserStatistics_t { enum CRSF_MESSAGE_TYPE { CRSF_MESSAGE_TYPE_RC_CHANNELS, CRSF_MESSAGE_TYPE_LINK_STATISTICS, + CRSF_MESSAGE_TYPE_LINK_STATISTICS_TX, + CRSF_MESSAGE_TYPE_ELRS_STATUS, }; typedef struct { @@ -83,6 +101,8 @@ typedef struct { union { CrsfChannelData_t channel_data; CrsfLinkStatistics_t link_statistics; + CrsfLinkStatisticsTx_t link_statistics_tx; + CrsfElrsStatus_t elrs_status; }; } CrsfPacket_t; diff --git a/src/drivers/rc/crsf_rc/CrsfRc.cpp b/src/drivers/rc/crsf_rc/CrsfRc.cpp index 9e311da18e..f099fff909 100644 --- a/src/drivers/rc/crsf_rc/CrsfRc.cpp +++ b/src/drivers/rc/crsf_rc/CrsfRc.cpp @@ -178,8 +178,11 @@ void CrsfRc::Run() Crc8Init(0xd5); + _input_rc.rssi = -1; _input_rc.rssi_dbm = NAN; _input_rc.link_quality = -1; + _input_rc.rc_frame_rate = 0; + _input_rc.link_snr = -1; CrsfParser_Init(); } @@ -213,8 +216,30 @@ void CrsfRc::Run() case CRSF_MESSAGE_TYPE_LINK_STATISTICS: _last_packet_seen = time_now_us; - _input_rc.rssi_dbm = -(float)new_crsf_packet.link_statistics.uplink_rssi_1; + _input_rc.rssi_dbm = -(float)(new_crsf_packet.link_statistics.active_antenna ? + new_crsf_packet.link_statistics.uplink_rssi_2 : + new_crsf_packet.link_statistics.uplink_rssi_1); + + if (time_now_us - _last_stats_tx_seen > 500_ms) { + // We haven't received link statistics tx in a while, use an approximation + _input_rc.rssi = (1.f - _input_rc.rssi_dbm / -130.f) * _input_rc.RSSI_MAX; + } + _input_rc.link_quality = new_crsf_packet.link_statistics.uplink_link_quality; + _input_rc.rc_frame_rate = new_crsf_packet.link_statistics.rf_mode; + _input_rc.link_snr = new_crsf_packet.link_statistics.uplink_snr; + break; + + case CRSF_MESSAGE_TYPE_LINK_STATISTICS_TX: + _last_packet_seen = time_now_us; + _last_stats_tx_seen = time_now_us; + _input_rc.rssi = new_crsf_packet.link_statistics_tx.uplink_rssi_pct; + break; + + case CRSF_MESSAGE_TYPE_ELRS_STATUS: + _last_packet_seen = time_now_us; + _input_rc.rc_lost_frame_count = new_crsf_packet.elrs_status.packets_bad; + _input_rc.rc_total_frame_count = new_crsf_packet.elrs_status.packets_good; break; default: @@ -344,8 +369,11 @@ void CrsfRc::Run() // If no communication if (time_now_us - _last_packet_seen > 100_ms) { // Invalidate link statistics + _input_rc.rssi = -1; _input_rc.rssi_dbm = NAN; _input_rc.link_quality = -1; + _input_rc.rc_frame_rate = 0; + _input_rc.link_snr = -1; } // If we have not gotten RC updates specifically @@ -359,7 +387,6 @@ void CrsfRc::Run() } _input_rc.channel_count = CRSF_CHANNEL_COUNT; - _input_rc.rssi = -1; _input_rc.rc_ppm_frame_length = 0; _input_rc.input_source = input_rc_s::RC_INPUT_SOURCE_PX4FMU_CRSF; _input_rc.timestamp = hrt_absolute_time(); diff --git a/src/drivers/rc/crsf_rc/CrsfRc.hpp b/src/drivers/rc/crsf_rc/CrsfRc.hpp index c3b0a4ec54..a47b361903 100644 --- a/src/drivers/rc/crsf_rc/CrsfRc.hpp +++ b/src/drivers/rc/crsf_rc/CrsfRc.hpp @@ -100,6 +100,7 @@ private: uint32_t _bytes_rx{0}; hrt_abstime _last_packet_seen{0}; + hrt_abstime _last_stats_tx_seen{0}; CrsfParserStatistics_t _packet_parser_statistics{0}; From 7a9b04c67c25e4b9eb2feef8a89a53a6c3e25b9c Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Wed, 17 Sep 2025 00:31:01 +0800 Subject: [PATCH 07/23] [crsf_rc] Allow setting the baudrate via parameter --- src/drivers/rc/crsf_rc/CrsfRc.cpp | 26 +++++++++++++++----------- src/drivers/rc/crsf_rc/CrsfRc.hpp | 3 ++- src/drivers/rc/crsf_rc/module.yaml | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/drivers/rc/crsf_rc/CrsfRc.cpp b/src/drivers/rc/crsf_rc/CrsfRc.cpp index f099fff909..069be2586c 100644 --- a/src/drivers/rc/crsf_rc/CrsfRc.cpp +++ b/src/drivers/rc/crsf_rc/CrsfRc.cpp @@ -36,6 +36,7 @@ #include "Crc8.hpp" #include +#include #include #include @@ -44,11 +45,10 @@ using namespace time_literals; -#define CRSF_BAUDRATE 420000 - -CrsfRc::CrsfRc(const char *device) : +CrsfRc::CrsfRc(const char *device, uint32_t baudrate) : ModuleParams(nullptr), - ScheduledWorkItem(MODULE_NAME, px4::serial_port_to_wq(device)) + ScheduledWorkItem(MODULE_NAME, px4::serial_port_to_wq(device)), + _baudrate(baudrate) { if (device) { strncpy(_device, device, sizeof(_device) - 1); @@ -70,13 +70,18 @@ int CrsfRc::task_spawn(int argc, char *argv[]) int ch; const char *myoptarg = nullptr; const char *device_name = nullptr; + uint32_t baudrate = 420'000; - while ((ch = px4_getopt(argc, argv, "d:", &myoptind, &myoptarg)) != EOF) { + while ((ch = px4_getopt(argc, argv, "d:b:", &myoptind, &myoptarg)) != EOF) { switch (ch) { case 'd': device_name = myoptarg; break; + case 'b': + baudrate = strtoul(myoptarg, nullptr, 10); + break; + case '?': error_flag = true; break; @@ -102,7 +107,7 @@ int CrsfRc::task_spawn(int argc, char *argv[]) return PX4_ERROR; } - CrsfRc *instance = new CrsfRc(device_name); + CrsfRc *instance = new CrsfRc(device_name, baudrate); if (instance == nullptr) { PX4_ERR("alloc failed"); @@ -144,10 +149,9 @@ void CrsfRc::Run() } if (! _uart->isOpen()) { - // Configure the desired baudrate if one was specified by the user. - // Otherwise the default baudrate will be used. - if (! _uart->setBaudrate(CRSF_BAUDRATE)) { - PX4_ERR("Error setting baudrate to %u on %s", CRSF_BAUDRATE, _device); + // Configure the UART. + if (_baudrate && ! _uart->setBaudrate(_baudrate)) { + PX4_ERR("Error setting baudrate to %" PRIu32 " on %s", _baudrate, _device); px4_sleep(1); return; } @@ -565,7 +569,7 @@ This module parses the CRSF RC uplink protocol and generates CRSF downlink telem PRINT_MODULE_USAGE_SUBCATEGORY("radio_control"); PRINT_MODULE_USAGE_COMMAND("start"); PRINT_MODULE_USAGE_PARAM_STRING('d', "/dev/ttyS3", "", "RC device", true); - + PRINT_MODULE_USAGE_PARAM_INT('b', 420000, 4800, 3000000, "RC baudrate", true); PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); return 0; diff --git a/src/drivers/rc/crsf_rc/CrsfRc.hpp b/src/drivers/rc/crsf_rc/CrsfRc.hpp index a47b361903..84d78348af 100644 --- a/src/drivers/rc/crsf_rc/CrsfRc.hpp +++ b/src/drivers/rc/crsf_rc/CrsfRc.hpp @@ -59,7 +59,7 @@ using namespace device; class CrsfRc : public ModuleBase, public ModuleParams, public px4::ScheduledWorkItem { public: - CrsfRc(const char *device); + CrsfRc(const char *device, uint32_t baudrate); ~CrsfRc() override; /** @see ModuleBase */ @@ -94,6 +94,7 @@ private: char _device[20] {}; ///< device / serial port path bool _is_singlewire{false}; + uint32_t _baudrate{0}; static constexpr size_t RC_MAX_BUFFER_SIZE{64}; uint8_t _rcs_buf[RC_MAX_BUFFER_SIZE] {}; diff --git a/src/drivers/rc/crsf_rc/module.yaml b/src/drivers/rc/crsf_rc/module.yaml index fc4ce23a27..4e76ea5976 100644 --- a/src/drivers/rc/crsf_rc/module.yaml +++ b/src/drivers/rc/crsf_rc/module.yaml @@ -1,6 +1,6 @@ module_name: CRSF RC Input Driver serial_config: - - command: "crsf_rc start -d ${SERIAL_DEV}" + - command: "crsf_rc start -d ${SERIAL_DEV} -b ${BAUD_PARAM}" port_config_param: name: RC_CRSF_PRT_CFG group: Serial From 19048380431f62d4161e218fbec57abc34f47f9f Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Wed, 17 Sep 2025 00:32:33 +0800 Subject: [PATCH 08/23] [crsf_rc] Extend the RC packet reception timeouts to 0.5s --- src/drivers/rc/crsf_rc/CrsfRc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/rc/crsf_rc/CrsfRc.cpp b/src/drivers/rc/crsf_rc/CrsfRc.cpp index 069be2586c..09122a3b33 100644 --- a/src/drivers/rc/crsf_rc/CrsfRc.cpp +++ b/src/drivers/rc/crsf_rc/CrsfRc.cpp @@ -371,7 +371,7 @@ void CrsfRc::Run() } // If no communication - if (time_now_us - _last_packet_seen > 100_ms) { + if (time_now_us - _last_packet_seen > 500_ms) { // Invalidate link statistics _input_rc.rssi = -1; _input_rc.rssi_dbm = NAN; @@ -381,7 +381,7 @@ void CrsfRc::Run() } // If we have not gotten RC updates specifically - if (time_now_us - _input_rc.timestamp_last_signal > 50_ms) { + if (time_now_us - _input_rc.timestamp_last_signal > 500_ms) { _input_rc.rc_lost = 1; _input_rc.rc_failsafe = 1; From bb72088ff6cdc3b592ca642006d34dc1c7ad20e5 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Wed, 17 Sep 2025 00:38:06 +0800 Subject: [PATCH 09/23] [crsf_rc] Add ability to inject buffers for development --- src/drivers/rc/crsf_rc/CrsfParser.cpp | 45 +++++++++++++++++++++++++++ src/drivers/rc/crsf_rc/CrsfParser.hpp | 4 +++ src/drivers/rc/crsf_rc/CrsfRc.cpp | 40 ++++++++++++++++++++++++ src/drivers/rc/crsf_rc/Kconfig | 6 ++++ 4 files changed, 95 insertions(+) diff --git a/src/drivers/rc/crsf_rc/CrsfParser.cpp b/src/drivers/rc/crsf_rc/CrsfParser.cpp index 61d2029b0d..b8a1f6bf77 100644 --- a/src/drivers/rc/crsf_rc/CrsfParser.cpp +++ b/src/drivers/rc/crsf_rc/CrsfParser.cpp @@ -143,6 +143,11 @@ static uint32_t working_segment_size = HEADER_SIZE; #define RX_QUEUE_BUFFER_SIZE 200 static QueueBuffer_t rx_queue; static uint8_t rx_queue_buffer[RX_QUEUE_BUFFER_SIZE]; +#ifdef CONFIG_DRIVERS_RC_CRSF_RC_INJECT +static QueueBuffer_t inject_queue; +static uint8_t inject_queue_buffer[RX_QUEUE_BUFFER_SIZE]; +static uint8_t temp_queue_buffer[RX_QUEUE_BUFFER_SIZE]; +#endif static uint8_t process_buffer[CRSF_MAX_PACKET_LEN]; static CrsfPacketDescriptor_t *working_descriptor = NULL; @@ -151,6 +156,9 @@ static CrsfPacketDescriptor_t *FindCrsfDescriptor(const enum CRSF_PACKET_TYPE pa void CrsfParser_Init(void) { QueueBuffer_Init(&rx_queue, rx_queue_buffer, RX_QUEUE_BUFFER_SIZE); +#ifdef CONFIG_DRIVERS_RC_CRSF_RC_INJECT + QueueBuffer_Init(&inject_queue, inject_queue_buffer, RX_QUEUE_BUFFER_SIZE); +#endif } static float ConstrainF(const float x, const float min, const float max) @@ -269,6 +277,13 @@ bool CrsfParser_LoadBuffer(const uint8_t *buffer, const uint32_t size) return QueueBuffer_AppendBuffer(&rx_queue, buffer, size); } +#ifdef CONFIG_DRIVERS_RC_CRSF_RC_INJECT +bool CrsfParser_InjectBuffer(const uint8_t *buffer, const uint32_t size) +{ + return QueueBuffer_AppendBuffer(&inject_queue, buffer, size); +} +#endif + uint32_t CrsfParser_FreeQueueSize(void) { return RX_QUEUE_BUFFER_SIZE - QueueBuffer_Count(&rx_queue); @@ -391,7 +406,37 @@ bool CrsfParser_TryParseCrsfPacket(CrsfPacket_t *const new_packet, CrsfParserSta parser_state = PARSER_STATE_HEADER; if (valid_packet) { +#ifdef CONFIG_DRIVERS_RC_CRSF_RC_INJECT + + if (!QueueBuffer_IsEmpty(&inject_queue)) { + // copy the remaining bytes from the rx queue to the temp buffer + const uint32_t temp_size = QueueBuffer_Count(&rx_queue); + + if (temp_size) { + QueueBuffer_PeekBuffer(&rx_queue, 0, temp_queue_buffer, temp_size); + // clear the rx queue + QueueBuffer_Dequeue(&rx_queue, QueueBuffer_Count(&rx_queue)); + } + + // append the inject queue to the rx queue + uint8_t inject_byte; + + while (QueueBuffer_Get(&inject_queue, &inject_byte)) { + QueueBuffer_Append(&rx_queue, inject_byte); + } + + if (temp_size) { + // append the temp buffer back to the rx queue + QueueBuffer_AppendBuffer(&rx_queue, temp_queue_buffer, temp_size); + } + + } else { + return true; + } + +#else return true; +#endif } break; diff --git a/src/drivers/rc/crsf_rc/CrsfParser.hpp b/src/drivers/rc/crsf_rc/CrsfParser.hpp index 167cd6466e..d0f5bab46d 100644 --- a/src/drivers/rc/crsf_rc/CrsfParser.hpp +++ b/src/drivers/rc/crsf_rc/CrsfParser.hpp @@ -43,6 +43,7 @@ #include #include +#include #define CRSF_CHANNEL_COUNT 16 @@ -108,5 +109,8 @@ typedef struct { void CrsfParser_Init(void); bool CrsfParser_LoadBuffer(const uint8_t *buffer, const uint32_t size); +#ifdef DRIVERS_RC_CRSF_RC_INJECT +bool CrsfParser_InjectBuffer(const uint8_t *buffer, const uint32_t size); +#endif uint32_t CrsfParser_FreeQueueSize(void); bool CrsfParser_TryParseCrsfPacket(CrsfPacket_t *const new_packet, CrsfParserStatistics_t *const parser_statistics); diff --git a/src/drivers/rc/crsf_rc/CrsfRc.cpp b/src/drivers/rc/crsf_rc/CrsfRc.cpp index 09122a3b33..6535fceb1d 100644 --- a/src/drivers/rc/crsf_rc/CrsfRc.cpp +++ b/src/drivers/rc/crsf_rc/CrsfRc.cpp @@ -549,6 +549,43 @@ int CrsfRc::print_status() int CrsfRc::custom_command(int argc, char *argv[]) { +#ifdef CONFIG_DRIVERS_RC_CRSF_RC_INJECT + + if (!strcmp(argv[0], "start")) { + if (is_running()) { + return print_usage("already running"); + } + + int ret = CrsfRc::task_spawn(argc, argv); + + if (ret) { + return ret; + } + } + + if (!is_running()) { + return print_usage("not running"); + } + + // crsf_rc inject 0x7C 0xC8 0xEA 0x30 0x02 0x59 0x31 0x00 0x6A + if (!strcmp(argv[0], "inject")) { + const uint8_t length = argc; + uint8_t buf[100]; + buf[0] = 0xC8; // sync byte + buf[1] = length; + uint8_t i = 0; + + for (; i < length - 1; i++) { + buf[i + 2] = (uint8_t) strtol(argv[i + 1], nullptr, 16); + } + + buf[i + 2] = Crc8Calc(buf + 2, length - 1); // CRC + CrsfParser_InjectBuffer(buf, length + 2); + return PX4_OK; + } + +#endif + return print_usage("unknown command"); } @@ -570,6 +607,9 @@ This module parses the CRSF RC uplink protocol and generates CRSF downlink telem PRINT_MODULE_USAGE_COMMAND("start"); PRINT_MODULE_USAGE_PARAM_STRING('d', "/dev/ttyS3", "", "RC device", true); PRINT_MODULE_USAGE_PARAM_INT('b', 420000, 4800, 3000000, "RC baudrate", true); +#ifdef CONFIG_DRIVERS_RC_CRSF_RC_INJECT + PRINT_MODULE_USAGE_COMMAND_DESCR("inject", "Inject frame data bytes (for testing)"); +#endif PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); return 0; diff --git a/src/drivers/rc/crsf_rc/Kconfig b/src/drivers/rc/crsf_rc/Kconfig index 21096275af..2e74abf782 100644 --- a/src/drivers/rc/crsf_rc/Kconfig +++ b/src/drivers/rc/crsf_rc/Kconfig @@ -3,3 +3,9 @@ menuconfig DRIVERS_RC_CRSF_RC default n ---help--- Enable support for crsf rc + +config DRIVERS_RC_CRSF_RC_INJECT + bool "Inject CRSF RC" + default n + ---help--- + Enable this to inject CRSF RC commands. From 14b38f2ebaffb222e4abc698977bb1b94d5d5d58 Mon Sep 17 00:00:00 2001 From: Alexander Lerach Date: Tue, 25 Nov 2025 14:48:11 +0100 Subject: [PATCH 10/23] boards: free up FLASH in auterion v6s by disabling modules --- boards/auterion/fmu-v6s/default.px4board | 3 --- boards/auterion/fmu-v6s/init/rc.board_defaults | 2 +- boards/auterion/fmu-v6x/init/rc.board_defaults | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/boards/auterion/fmu-v6s/default.px4board b/boards/auterion/fmu-v6s/default.px4board index 97dfd2f6df..bc7883a1b8 100644 --- a/boards/auterion/fmu-v6s/default.px4board +++ b/boards/auterion/fmu-v6s/default.px4board @@ -77,9 +77,7 @@ CONFIG_MODULES_VTOL_ATT_CONTROL=y CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y CONFIG_SYSTEMCMDS_BSONDUMP=y CONFIG_SYSTEMCMDS_DMESG=y -CONFIG_SYSTEMCMDS_GPIO=y CONFIG_SYSTEMCMDS_HARDFAULT_LOG=y -CONFIG_SYSTEMCMDS_I2C_LAUNCHER=y CONFIG_SYSTEMCMDS_I2CDETECT=y CONFIG_SYSTEMCMDS_LED_CONTROL=y CONFIG_SYSTEMCMDS_MFT=y @@ -91,7 +89,6 @@ CONFIG_SYSTEMCMDS_PARAM=y CONFIG_SYSTEMCMDS_PERF=y CONFIG_SYSTEMCMDS_REBOOT=y CONFIG_SYSTEMCMDS_SD_BENCH=y -CONFIG_SYSTEMCMDS_SD_STRESS=y CONFIG_SYSTEMCMDS_SERIAL_TEST=y CONFIG_SYSTEMCMDS_SYSTEM_TIME=y CONFIG_SYSTEMCMDS_TOP=y diff --git a/boards/auterion/fmu-v6s/init/rc.board_defaults b/boards/auterion/fmu-v6s/init/rc.board_defaults index a5e81c9825..4904ffe0c2 100644 --- a/boards/auterion/fmu-v6s/init/rc.board_defaults +++ b/boards/auterion/fmu-v6s/init/rc.board_defaults @@ -4,7 +4,7 @@ #------------------------------------------------------------------------------ # By disabling INA modules, we use the -# i2c_launcher instead. +# auterion launcher instead. param set-default SENS_EN_INA226 0 param set-default SENS_EN_INA228 0 param set-default SENS_EN_INA238 0 diff --git a/boards/auterion/fmu-v6x/init/rc.board_defaults b/boards/auterion/fmu-v6x/init/rc.board_defaults index 1a6fc9673c..05f56d4f9f 100644 --- a/boards/auterion/fmu-v6x/init/rc.board_defaults +++ b/boards/auterion/fmu-v6x/init/rc.board_defaults @@ -4,7 +4,7 @@ #------------------------------------------------------------------------------ # By disabling all 3 INA modules, we use the -# i2c_launcher instead. +# auterion launcher instead. param set-default SENS_EN_INA238 0 param set-default SENS_EN_INA228 0 param set-default SENS_EN_INA226 0 From bd3b3d647fcc7e7d7cf374b07a35708c23293f61 Mon Sep 17 00:00:00 2001 From: Alexander Lerach Date: Tue, 25 Nov 2025 15:39:03 +0100 Subject: [PATCH 11/23] drivers: PCA9685 robustness & logging improvements Co-authored-by: Phil-Engljaehringer --- src/drivers/pca9685_pwm_out/PCA9685.cpp | 127 +++++++++------- src/drivers/pca9685_pwm_out/PCA9685.h | 22 ++- src/drivers/pca9685_pwm_out/main.cpp | 189 ++++++++++++++++-------- 3 files changed, 210 insertions(+), 128 deletions(-) diff --git a/src/drivers/pca9685_pwm_out/PCA9685.cpp b/src/drivers/pca9685_pwm_out/PCA9685.cpp index 7eccd6c04b..f2a151ef44 100644 --- a/src/drivers/pca9685_pwm_out/PCA9685.cpp +++ b/src/drivers/pca9685_pwm_out/PCA9685.cpp @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright (c) 2019-2022 PX4 Development Team. All rights reserved. + * Copyright (c) 2019-2025 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 @@ -57,61 +57,61 @@ PCA9685::PCA9685(int bus, int addr): int PCA9685::init() { - int ret = I2C::init(); - - if (ret != PX4_OK) { return ret; } + return I2C::init(); +} +int PCA9685::configure() +{ uint8_t buf[2] = {}; buf[0] = PCA9685_REG_MODE1; buf[1] = PCA9685_DEFAULT_MODE1_CFG | PCA9685_MODE1_SLEEP_MASK; // put into sleep mode - ret = transfer(buf, 2, nullptr, 0); - - if (OK != ret) { - PX4_ERR("init: i2c::transfer returned %d", ret); - return ret; - } + int ret = transfer(buf, 2, nullptr, 0); #ifdef CONFIG_PCA9685_USE_EXTERNAL_CRYSTAL + /* EXTCLK is sticky, so writing it once is enough. Its not a problem when its written to 0 later. */ buf[1] = PCA9685_DEFAULT_MODE1_CFG | PCA9685_MODE1_SLEEP_MASK | PCA9685_MODE1_EXTCLK_MASK; - ret = transfer(buf, 2, nullptr, 0); // enable EXTCLK if possible - - if (OK != ret) { - PX4_ERR("init: i2c::transfer returned %d", ret); - return ret; - } - + ret |= transfer(buf, 2, nullptr, 0); #endif buf[0] = PCA9685_REG_MODE2; buf[1] = PCA9685_DEFAULT_MODE2_CFG; - ret = transfer(buf, 2, nullptr, 0); + ret |= transfer(buf, 2, nullptr, 0); + return ret; +} - if (OK != ret) { - PX4_ERR("init: i2c::transfer returned %d", ret); - return ret; +int PCA9685::registers_check() +{ + /* Check MODE1 register */ + uint8_t send_buf = PCA9685_REG_MODE1; + uint8_t recv_buf; + + int ret = transfer(&send_buf, 1, &recv_buf, 1); + uint8_t ignore_extclk_mask = ~PCA9685_MODE1_EXTCLK_MASK; + + if (ret != PX4_OK) { + return -EIO; + } + + if ((recv_buf & ignore_extclk_mask) != (PCA9685_DEFAULT_MODE1_CFG & ignore_extclk_mask)) { + return -EFAULT; + } + + /* Check MODE2 register */ + send_buf = PCA9685_REG_MODE2; + ret = transfer(&send_buf, 1, &recv_buf, 1); + + if (ret != PX4_OK) { + return -EIO; + } + + if (recv_buf != PCA9685_DEFAULT_MODE2_CFG) { + return -EFAULT; } return PX4_OK; } -int PCA9685::updatePWM(const uint16_t *outputs, unsigned num_outputs) -{ - if (num_outputs > PCA9685_PWM_CHANNEL_COUNT) { - num_outputs = PCA9685_PWM_CHANNEL_COUNT; - PX4_DEBUG("PCA9685 can only drive up to 16 channels"); - } - - uint16_t out[PCA9685_PWM_CHANNEL_COUNT]; - memcpy(out, outputs, sizeof(uint16_t) * num_outputs); - - for (unsigned i = 0; i < num_outputs; ++i) { - out[i] = calcRawFromPulse(out[i]); - } - - return writePWM(0, out, num_outputs); -} - int PCA9685::updateFreq(float freq) { uint16_t divider = (uint16_t)round((float)PCA9685_CLOCK_REFERENCE / freq / PCA9685_PWM_RES) - 1; @@ -160,30 +160,47 @@ int PCA9685::sleep() int PCA9685::wake() { - uint8_t buf[2] = { - PCA9685_REG_MODE1, - PCA9685_DEFAULT_MODE1_CFG - }; - return transfer(buf, 2, nullptr, 0); -} + uint8_t send_buf[2]; + uint8_t recv_buf; -int PCA9685::doRestart() -{ - uint8_t buf[2] = { - PCA9685_REG_MODE1, - PCA9685_DEFAULT_MODE1_CFG | PCA9685_MODE1_RESTART_MASK - }; - return transfer(buf, 2, nullptr, 0); + send_buf[0] = PCA9685_REG_MODE1; + int ret = transfer(&send_buf[0], 1, &recv_buf, 1); + + if (ret != PX4_OK) { + return PX4_ERROR; + } + + send_buf[1] = recv_buf & ~PCA9685_MODE1_SLEEP_MASK; // Clear sleep bit + ret |= transfer(&send_buf[0], 2, nullptr, 0); + px4_usleep(500); // wait for oscillator to stabilize + + if (recv_buf & PCA9685_MODE1_RESTART_MASK) { // Check if reset bit is set + send_buf[1] |= PCA9685_MODE1_RESTART_MASK; // Set restart bit + ret |= transfer(&send_buf[0], 2, nullptr, 0); + } + + ret |= transfer(&send_buf[0], 1, &recv_buf, 1); + + if (ret != PX4_OK || recv_buf & (PCA9685_MODE1_RESTART_MASK | PCA9685_MODE1_SLEEP_MASK)) { + return PX4_ERROR; + } + + return ret; } int PCA9685::probe() { - int ret = I2C::probe(); + for (int i = 0; i < 10; i++) { + uint8_t send_buf = PCA9685_REG_MODE1; - if (ret != PX4_OK) { return ret; } + if (transfer(&send_buf, 1, nullptr, 0) == PX4_OK) { + return PX4_OK; + } - uint8_t buf[2] = {0x00}; - return transfer(buf, 2, buf, 1); + px4_usleep(10'000); + } + + return PX4_ERROR; } int PCA9685::writePWM(uint8_t idx, const uint16_t *value, uint8_t num) diff --git a/src/drivers/pca9685_pwm_out/PCA9685.h b/src/drivers/pca9685_pwm_out/PCA9685.h index e8bd5eb4d8..d22b4cec22 100644 --- a/src/drivers/pca9685_pwm_out/PCA9685.h +++ b/src/drivers/pca9685_pwm_out/PCA9685.h @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright (c) 2019 PX4 Development Team. All rights reserved. + * Copyright (c) 2025 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 @@ -95,13 +95,6 @@ public: int init() override; - /* - * Write new PWM value to device - * - * *output: pulse width, us - */ - int updatePWM(const uint16_t *outputs, unsigned num_outputs); - /* * Set PWM frequency to new value. * @@ -150,11 +143,14 @@ public: int wake(); /* - * If PCA9685 is put into sleep without clearing all the outputs, - * then the restart command will be available, and it can bring back PWM output without the - * need of updatePWM() call. - */ - int doRestart(); + * Configure the PCA9685 device with necessary settings. e.g. MODE1 or MODE2 + */ + int configure(); + + /* + * Verfy whether the registers of PCA9685 are in a consistent state + */ + int registers_check(); protected: int probe() override; diff --git a/src/drivers/pca9685_pwm_out/main.cpp b/src/drivers/pca9685_pwm_out/main.cpp index 60d0cc6340..2d22c36a77 100644 --- a/src/drivers/pca9685_pwm_out/main.cpp +++ b/src/drivers/pca9685_pwm_out/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright (c) 2012-2022 PX4 Development Team. All rights reserved. + * Copyright (c) 2012-2025 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 @@ -80,12 +80,15 @@ protected: private: perf_counter_t _cycle_perf; + perf_counter_t _comms_errors; + perf_counter_t _registers_invalid_reset; + perf_counter_t _registers_transfer_reset; enum class STATE : uint8_t { + CONFIGURE, INIT, - WAIT_FOR_OSC, RUNNING - } state{STATE::INIT}; + } _state{STATE::CONFIGURE}; PCA9685 *pca9685 = nullptr; uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; @@ -99,14 +102,22 @@ private: float param_pwm_freq, previous_pwm_freq; float param_schd_rate, previous_schd_rate; + bool param_update_failed = false; uint32_t param_duty_mode; + static constexpr uint8_t _transfer_fails_threshold = 10; + uint8_t _register_transfer_fails = 0; + void Run() override; + int registers_check(); }; PCA9685Wrapper::PCA9685Wrapper() : OutputModuleInterface(MODULE_NAME, px4::wq_configurations::hp_default), - _cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")) + _cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")), + _comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": comms errors")), + _registers_invalid_reset(perf_alloc(PC_COUNT, MODULE_NAME": registers invalid reset")), + _registers_transfer_reset(perf_alloc(PC_COUNT, MODULE_NAME": registers transfer reset")) { } @@ -119,6 +130,9 @@ PCA9685Wrapper::~PCA9685Wrapper() } perf_free(_cycle_perf); + perf_free(_comms_errors); + perf_free(_registers_invalid_reset); + perf_free(_registers_transfer_reset); } int PCA9685Wrapper::init() @@ -139,7 +153,7 @@ int PCA9685Wrapper::init() bool PCA9685Wrapper::updateOutputs(uint16_t *outputs, unsigned num_outputs, unsigned num_control_groups_updated) { - if (state != STATE::RUNNING) { return false; } + if (_state != STATE::RUNNING) { return false; } uint16_t low_level_outputs[PCA9685_PWM_CHANNEL_COUNT] = {}; num_outputs = num_outputs > PCA9685_PWM_CHANNEL_COUNT ? PCA9685_PWM_CHANNEL_COUNT : num_outputs; @@ -154,7 +168,7 @@ bool PCA9685Wrapper::updateOutputs(uint16_t *outputs, unsigned num_outputs, } if (pca9685->updateRAW(low_level_outputs, num_outputs) != PX4_OK) { - PX4_ERR("Failed to write PWM to PCA9685"); + perf_count(_comms_errors); return false; } @@ -176,69 +190,124 @@ void PCA9685Wrapper::Run() return; } - switch (state) { - case STATE::INIT: - updateParams(); - pca9685->updateFreq(param_pwm_freq); - previous_pwm_freq = param_pwm_freq; - previous_schd_rate = param_schd_rate; + switch (_state) { + case STATE::CONFIGURE: { + int ret = pca9685->configure(); - pca9685->wake(); - state = STATE::WAIT_FOR_OSC; - ScheduleDelayed(500); - break; + if (ret == PX4_OK) { + _state = STATE::INIT; + ScheduleNow(); - case STATE::WAIT_FOR_OSC: { - state = STATE::RUNNING; - ScheduleOnInterval(1000000 / param_schd_rate, 0); - } - break; - - case STATE::RUNNING: - perf_begin(_cycle_perf); - - _mixing_output.update(); - - // check for parameter updates - if (_parameter_update_sub.updated()) { - // clear update - parameter_update_s pupdate; - _parameter_update_sub.copy(&pupdate); - - // update parameters from storage - updateParams(); - - // apply param updates - if ((float)fabs(previous_pwm_freq - param_pwm_freq) > 0.01f) { - previous_pwm_freq = param_pwm_freq; - - ScheduleClear(); - - pca9685->sleep(); - pca9685->updateFreq(param_pwm_freq); - pca9685->wake(); - - // update of PWM freq will always trigger scheduling change - previous_schd_rate = param_schd_rate; - - state = STATE::WAIT_FOR_OSC; - ScheduleDelayed(500); - - } else if ((float)fabs(previous_schd_rate - param_schd_rate) > 0.01f) { - // case when PWM freq not changed but scheduling rate does - previous_schd_rate = param_schd_rate; - ScheduleClear(); - ScheduleOnInterval(1000000 / param_schd_rate, 1000000 / param_schd_rate); + } else { + perf_count(_comms_errors); + ScheduleDelayed(20_ms); } + + break; } - _mixing_output.updateSubscriptions(false); + case STATE::INIT: { + updateParams(); + int ret = pca9685->updateFreq(param_pwm_freq); + ret |= pca9685->wake(); - perf_end(_cycle_perf); - break; + if (ret == PX4_OK) { + previous_pwm_freq = param_pwm_freq; + previous_schd_rate = param_schd_rate; + _state = STATE::RUNNING; + ScheduleOnInterval(1000000 / param_schd_rate, 0); + + } else { + perf_count(_comms_errors); + _state = STATE::CONFIGURE; + ScheduleDelayed(20_ms); + } + + break; + } + + case STATE::RUNNING: { + perf_begin(_cycle_perf); + _mixing_output.update(); + + // check for parameter updates + if (_parameter_update_sub.updated() || param_update_failed) { + // clear update + parameter_update_s pupdate; + _parameter_update_sub.copy(&pupdate); + + // update parameters from storage + updateParams(); + + // apply param updates + if ((float)fabs(previous_pwm_freq - param_pwm_freq) > 0.01f) { + ScheduleClear(); + + int ret = pca9685->sleep(); + ret |= pca9685->updateFreq(param_pwm_freq); + ret |= pca9685->wake(); + + if (ret == PX4_OK) { + // update of PWM freq will always trigger scheduling change + param_update_failed = false; + previous_schd_rate = param_schd_rate; + previous_pwm_freq = param_pwm_freq; + ScheduleOnInterval(1000000 / param_schd_rate, 0); + + } else { + param_update_failed = true; + perf_count(_comms_errors); + ScheduleDelayed(20_ms); + break; + } + + } else if ((float)fabs(previous_schd_rate - param_schd_rate) > 0.01f) { + // case when PWM freq not changed but scheduling rate does + previous_schd_rate = param_schd_rate; + ScheduleClear(); + ScheduleOnInterval(1000000 / param_schd_rate, 1000000 / param_schd_rate); + } + } + + if (registers_check() != PX4_OK) { + _state = STATE::CONFIGURE; + ScheduleClear(); + ScheduleDelayed(20_ms); + } + + _mixing_output.updateSubscriptions(false); + + perf_end(_cycle_perf); + break; + } } } +int PCA9685Wrapper::registers_check() +{ + int reg_ret = pca9685->registers_check(); + + if (reg_ret == -EIO) { + _register_transfer_fails++; + + } else { + _register_transfer_fails = 0; + } + + if (reg_ret == -EFAULT) { + perf_count(_registers_invalid_reset); + return PX4_ERROR; + } + + if (_register_transfer_fails > _transfer_fails_threshold) { + perf_count(_registers_transfer_reset); + _register_transfer_fails = 0; + return PX4_ERROR; + } + + return PX4_OK; +} + int PCA9685Wrapper::print_usage(const char *reason) { if (reason) { From 932abfd55890cee050a0b25d98bb022c3776dc16 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Mon, 24 Nov 2025 10:24:56 +0100 Subject: [PATCH 12/23] [auav] Robustify I2C transfers and enforce minimum sample time --- .../differential_pressure/auav/AUAV.cpp | 19 +++++++++++++------ .../auav/AUAV_Absolute.hpp | 2 ++ .../auav/AUAV_Differential.hpp | 2 ++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/drivers/differential_pressure/auav/AUAV.cpp b/src/drivers/differential_pressure/auav/AUAV.cpp index 2533399a35..66f8a3b46b 100644 --- a/src/drivers/differential_pressure/auav/AUAV.cpp +++ b/src/drivers/differential_pressure/auav/AUAV.cpp @@ -65,6 +65,7 @@ AUAV::AUAV(const I2CSPIDriverConfig &config) : _sample_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": read")), _comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": comms errors")) { + I2C::_retries = 5; } AUAV::~AUAV() @@ -130,15 +131,21 @@ int AUAV::init() int AUAV::probe() { - uint8_t res_data = 0; - int status = transfer(nullptr, 0, &res_data, sizeof(res_data)); + uint8_t res_data; - /* Check that the sensor is active. Reported in bit 6 of the status byte */ - if ((res_data & 0x40) == 0) { - status = PX4_ERROR; + for (unsigned i = 0; i < 10; i++) { + res_data = 0; + int status = transfer(nullptr, 0, &res_data, 1); + + /* Check that the sensor is active. Reported in bit 6 of the status byte */ + if (status == PX4_OK && (res_data & 0x40)) { + return PX4_OK; + } + + px4_usleep(10'000); } - return status; + return PX4_ERROR; } void AUAV::handle_state_read_calibdata() diff --git a/src/drivers/differential_pressure/auav/AUAV_Absolute.hpp b/src/drivers/differential_pressure/auav/AUAV_Absolute.hpp index 624ef27079..603649a783 100644 --- a/src/drivers/differential_pressure/auav/AUAV_Absolute.hpp +++ b/src/drivers/differential_pressure/auav/AUAV_Absolute.hpp @@ -51,6 +51,8 @@ static constexpr uint8_t EEPROM_ABS_ES = 0x38; /* Measurement rate is 50Hz */ static constexpr unsigned ABS_MEAS_RATE = 50; static constexpr int64_t ABS_CONVERSION_INTERVAL = (1000000 / ABS_MEAS_RATE); /* microseconds */ +/* reading too fast can yield all zero data -> incorrect sensor reading */ +static_assert(ABS_CONVERSION_INTERVAL >= 7000, "Conversion interval is too fast"); /* Conversions */ static constexpr float MBAR_TO_PA = 100.0f; diff --git a/src/drivers/differential_pressure/auav/AUAV_Differential.hpp b/src/drivers/differential_pressure/auav/AUAV_Differential.hpp index 412066a6ac..168fb322b6 100644 --- a/src/drivers/differential_pressure/auav/AUAV_Differential.hpp +++ b/src/drivers/differential_pressure/auav/AUAV_Differential.hpp @@ -51,6 +51,8 @@ static constexpr uint8_t EEPROM_DIFF_ES = 0x34; /* Measurement rate is 100Hz */ static constexpr unsigned DIFF_MEAS_RATE = 100; static constexpr int64_t DIFF_CONVERSION_INTERVAL = (1000000 / DIFF_MEAS_RATE); /* microseconds */ +/* reading too fast can yield all zero data -> incorrect sensor reading */ +static_assert(DIFF_CONVERSION_INTERVAL >= 7000, "Conversion interval is too fast"); /* Conversions */ static constexpr float INH_TO_PA = 249.08f; From c4a459838e008896fade24b61005ebafd3b245eb Mon Sep 17 00:00:00 2001 From: Alexander Lerach Date: Mon, 24 Nov 2025 13:31:40 +0100 Subject: [PATCH 13/23] gps: wipe FLASH config only once --- src/drivers/gps/gps.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/drivers/gps/gps.cpp b/src/drivers/gps/gps.cpp index 1b61662335..8497027eb2 100644 --- a/src/drivers/gps/gps.cpp +++ b/src/drivers/gps/gps.cpp @@ -178,6 +178,7 @@ private: char _port[20] {}; ///< device / serial port path bool _healthy{false}; ///< flag to signal if the GPS is ok + bool _cfg_wiped{false}; ///< flag to signal if the config was already wiped bool _mode_auto; ///< if true, auto-detect which GPS is attached gps_driver_mode_t _mode; ///< current mode @@ -939,7 +940,7 @@ GPS::run() param_get(handle, &gps_cfg_wipe); } - gpsConfig.cfg_wipe = static_cast(gps_cfg_wipe); + gpsConfig.cfg_wipe = static_cast(gps_cfg_wipe) && !_cfg_wiped; if (_helper && _helper->configure(_baudrate, gpsConfig) == 0) { @@ -1068,6 +1069,11 @@ GPS::run() // PX4_WARN("module found: %s", mode_str); _healthy = true; } + + /* Do not wipe the FLASH config multiple times. */ + if (!_cfg_wiped) { + _cfg_wiped = true; + } } if (_healthy) { From 8dd88e036de8cad17b45d0abdd1c96de0d281cd2 Mon Sep 17 00:00:00 2001 From: Alexander Lerach Date: Mon, 24 Nov 2025 14:23:44 +0100 Subject: [PATCH 14/23] gps: add init timeout to handle larger diff after configuration --- src/drivers/gps/gps.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/drivers/gps/gps.cpp b/src/drivers/gps/gps.cpp index 8497027eb2..e7dbab947a 100644 --- a/src/drivers/gps/gps.cpp +++ b/src/drivers/gps/gps.cpp @@ -84,9 +84,11 @@ using namespace device; using namespace time_literals; -#define TIMEOUT_1HZ 1300 //!< Timeout time in mS, 1000 mS (1Hz) + 300 mS delta for error -#define TIMEOUT_5HZ 500 //!< Timeout time in mS, 200 mS (5Hz) + 300 mS delta for error -#define TIMEOUT_DUMP_ADD 450 //!< Additional time in mS to account for RTCM3 parsing and dumping +#define TIMEOUT_1HZ 1300 //!< Timeout time in mS, 1000 mS (1Hz) + 300 mS delta for error +#define TIMEOUT_5HZ 500 //!< Timeout time in mS, 200 mS (5Hz) + 300 mS delta for error +#define TIMEOUT_INIT_1HZ (3 * TIMEOUT_1HZ) //!< Timeout time in mS, used until GPS is healthy +#define TIMEOUT_INIT_5HZ (3 * TIMEOUT_5HZ) //!< Timeout time in mS, used until GPS is healthy +#define TIMEOUT_DUMP_ADD 450 //!< Additional time in mS to account for RTCM3 parsing and dumping enum class gps_driver_mode_t { None = 0, @@ -996,19 +998,26 @@ GPS::run() } int helper_ret; - unsigned receive_timeout = TIMEOUT_5HZ; + + /* After being configured (especially in combination with FLASH wipes) the GPS may require + * additional time before outputting the first navigation data. To account for this, there is + * an init timeout. As soon as the GPS is healthy, the timeout is decreased. This allows for + * a quick reaction to a connection loss. */ + unsigned receive_timeout = TIMEOUT_INIT_5HZ; + unsigned healthy_timeout = TIMEOUT_5HZ; if ((ubx_mode == GPSDriverUBX::UBXMode::RoverWithMovingBase) || (ubx_mode == GPSDriverUBX::UBXMode::RoverWithMovingBaseUART1)) { /* The MB rover will wait as long as possible to compute a navigation solution, * possibly lowering the navigation rate all the way to 1 Hz while doing so. */ - receive_timeout = TIMEOUT_1HZ; + receive_timeout = TIMEOUT_INIT_1HZ; + healthy_timeout = TIMEOUT_1HZ; } if (_dump_communication_mode != gps_dump_comm_mode_t::Disabled) { /* Dumping the RTCM3/UBX data requires additional parsing and storing of data via uORB. * Without additional time this can lead to timeouts. */ - receive_timeout += TIMEOUT_DUMP_ADD; + healthy_timeout += TIMEOUT_DUMP_ADD; } while ((helper_ret = _helper->receive(receive_timeout)) > 0 && !should_exit()) { @@ -1068,6 +1077,7 @@ GPS::run() // // PX4_WARN("module found: %s", mode_str); _healthy = true; + receive_timeout = healthy_timeout; } /* Do not wipe the FLASH config multiple times. */ From a8c5df90ce9245d2224147c3521169642e421a83 Mon Sep 17 00:00:00 2001 From: Mahima Yoga Date: Tue, 25 Nov 2025 21:25:43 +0100 Subject: [PATCH 15/23] fw-ctrl: advertise attitude_sp_pub in attitude and FwLateralLongitudinal controller (#25983) --- src/modules/fw_att_control/FixedwingAttitudeControl.cpp | 1 + .../FwLateralLongitudinalControl.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/modules/fw_att_control/FixedwingAttitudeControl.cpp b/src/modules/fw_att_control/FixedwingAttitudeControl.cpp index f658eb56c2..ec856e942d 100644 --- a/src/modules/fw_att_control/FixedwingAttitudeControl.cpp +++ b/src/modules/fw_att_control/FixedwingAttitudeControl.cpp @@ -48,6 +48,7 @@ FixedwingAttitudeControl::FixedwingAttitudeControl(bool vtol) : /* fetch initial parameter values */ parameters_update(); _landing_gear_wheel_pub.advertise(); + _attitude_sp_pub.advertise(); } FixedwingAttitudeControl::~FixedwingAttitudeControl() diff --git a/src/modules/fw_lateral_longitudinal_control/FwLateralLongitudinalControl.cpp b/src/modules/fw_lateral_longitudinal_control/FwLateralLongitudinalControl.cpp index 9c5647f1a5..53005d8ba5 100644 --- a/src/modules/fw_lateral_longitudinal_control/FwLateralLongitudinalControl.cpp +++ b/src/modules/fw_lateral_longitudinal_control/FwLateralLongitudinalControl.cpp @@ -70,6 +70,7 @@ FwLateralLongitudinalControl::FwLateralLongitudinalControl(bool is_vtol) : _attitude_sp_pub(is_vtol ? ORB_ID(fw_virtual_attitude_setpoint) : ORB_ID(vehicle_attitude_setpoint)), _loop_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")) { + _attitude_sp_pub.advertise(); _tecs_status_pub.advertise(); _flight_phase_estimation_pub.advertise(); _fixed_wing_lateral_status_pub.advertise(); From d9a66b11ac06643e15310f468bb86c28fa56258e Mon Sep 17 00:00:00 2001 From: Marco Hauswirth <58551738+haumarco@users.noreply.github.com> Date: Wed, 26 Nov 2025 01:52:40 +0100 Subject: [PATCH 16/23] Docs: baro-auto-calibration and gnss-fault-detection (#25796) --- docs/en/advanced_config/tuning_the_ecl_ekf.md | 54 +++++++++++++++++++ docs/en/sensor/barometer.md | 50 ++++++++++++++--- src/modules/ekf2/params_gnss.yaml | 4 +- 3 files changed, 98 insertions(+), 10 deletions(-) diff --git a/docs/en/advanced_config/tuning_the_ecl_ekf.md b/docs/en/advanced_config/tuning_the_ecl_ekf.md index 8a68bc05dc..d2c0ada7fb 100644 --- a/docs/en/advanced_config/tuning_the_ecl_ekf.md +++ b/docs/en/advanced_config/tuning_the_ecl_ekf.md @@ -348,6 +348,60 @@ The `hpos_drift_rate`, `vpos_drift_rate` and `hspd` are calculated over a period Note that `ekf2_gps_drift` is not logged! ::: +#### GNSS Fault Detection + +PX4's GNSS fault detection protects against malicious or erroneous GNSS signals using selective fusion control based on measurement validation. + +The fault detection logic depends on the GPS mode, and also operates differently for horizontal position and altitude measurements. +The mode is set using the [EKF2_GPS_MODE](../advanced_config/parameter_reference.md#EKF2_GPS_MODE) parameter: + +- **Automatic (`0`)** (Default): Assumes that GNSS is generally reliable and is likely to be recovered. + EKF2 resets on fusion timeouts if no other source of position is available. +- **Dead-reckoning (`1`)**: Assumes that GNSS might be lost indefinitely, so resets should be avoided while we have other estimates of position data. + EKF2 may reset if no other sources of position or velocity are available. + If GNSS altitude OR horizontal position data drifts, the system disables fusion of both measurements simultaneously (even if one would still pass validation) and avoids performing resets. + +##### Detection Logic + +Horizontal Position: + +- **Automatic mode**: Horizontal position resets to GNSS data if no other horizontal position source is currently being fused (e.g., Auxiliary Global Position - AGP). +- **Dead-reckoning mode**: Horizontal position resets to GNSS data only if no other horizontal position OR velocity source is currently being fused (e.g., AGP, airspeed, optical flow). + +Altitude: + +- The altitude logic is more complex due to the height reference sensor ([EKF2_HGT_REF](../advanced_config/parameter_reference.md#EKF2_HGT_REF)) parameter, which is typically set to GNSS or baro in GNSS-denied scenarios. +- If height reference is set to baro, GNSS-based height resets are prevented (except when baro fusion fails completely and height reference automatically switches to GNSS). +- When height reference is set to GNSS: +- **Automatic mode**: Resets occur on drifting GNSS altitude measurements. +- **Dead-reckoning mode**: When validation starts failing, the system prevents GNSS altitude resets and labels the GNSS data as faulty. + +##### Faulty GNSS Data During Boot + +The system cannot automatically detect faulty GNSS data during vehicle boot as no baseline comparison exists. + +If GNSS fusion is enabled ([EKF2_GPS_CTRL](../advanced_config/parameter_reference.md#EKF2_GPS_CTRL)), operators will observe incorrect positions on maps and should disable GNSS fusion, then manually set the correct position via ground control station. +The global position gets corrected, and if [SENS_BAR_AUTOCAL](../advanced_config/parameter_reference.md#SENS_BAR_AUTOCAL) was enabled, baro offsets are automatically adjusted (through bias correction, not parameter changes). + +##### Enabling GNSS Fusion Mid-Flight + +With Faulty GNSS Data: + +- **Automatic mode**: Vehicle will reset to faulty position - potentially dangerous. +- **Dead-reckoning mode**: Large measurement differences cause GNSS rejection and fault detection activation. + +With Valid GNSS Data: + +- **Automatic mode**: Vehicle will reset to GNSS measurements. +- **Dead-reckoning mode**: If estimated position/altitude is close enough to measurements, fusion resumes; if too far apart, data gets labeled as faulty. + +##### Notes + +- **Dual Detection**: Horizontal and altitude checks run completely separately but both lead to the same result when triggered - all GNSS fusion gets disabled. +- **Recovery**: Only the specific check that labeled data as invalid can re-enable fusion. +- **Alternative Sources**: Dead-reckoning mode provides enhanced protection by requiring absence of alternative navigation sources before allowing resets. +- **Boot Vulnerability**: Initial faulty GNSS data cannot be detected automatically; requires operator intervention and manual position correction. + ### Range Finder [Range finder](../sensor/rangefinders.md) distance to ground is used by a single state filter to estimate the vertical position of the terrain relative to the height datum. diff --git a/docs/en/sensor/barometer.md b/docs/en/sensor/barometer.md index 46f77a8d8b..598bdc3d11 100644 --- a/docs/en/sensor/barometer.md +++ b/docs/en/sensor/barometer.md @@ -30,17 +30,51 @@ If needed, you can: - Change the selection order of barometers using the [CAL_BAROx_PRIO](../advanced_config/parameter_reference.md#CAL_BARO0_PRIO) parameters for each barometer. - Disable a barometer by setting its [CAL_BAROx_PRIO](../advanced_config/parameter_reference.md#CAL_BARO0_PRIO) value to `0`. -## Calibration +## Baro Auto-Calibration (Developers) -Barometers don't require calibration. +::: tip +This section documents the automated calibration mechanisms that ensure accurate altitude measurements throughout flight operations. +It is intended primarily for a developer audience who want to understand the underlying mechanisms. +::: - +The system implements two complementary calibration approaches that work together to maintain altitude measurement precision. +Both calibrations are initiated at the beginning after a system boot. +Relative calibration is performed first, followed by GNSS-barometric calibration. -## Developer Information +### Relative Calibration + +Relative baro calibration is **always enabled** and operates automatically during system initialization. +This calibration establishes offset corrections for all secondary baro sensors relative to the primary (selected) sensor. + +This calibration: + +- Eliminates altitude jumps when switching between baro sensors during flight. +- Ensures consistent altitude readings across all available baro sensors. +- Maintains seamless sensor redundancy and failover capability. + +### GNSS-Baro Calibration + +::: info +GNSS-baro calibration requires an operational GNSS receiver with vertical accuracy (EPV) ≤ 8 meters. +Relative calibration must already have completed. +::: + +GNSS-baro calibration adjusts baro sensor offsets to align with absolute altitude measurements from the GNSS receiver. +This calibration is controlled by the [SENS_BAR_AUTOCAL](../advanced_config/parameter_reference.md#SENS_BAR_AUTOCAL) parameter (enabled by default). + +The algorithm monitors GNSS quality, collects altitude differences over a 2-second filtered window, and verifies stability within 4m tolerance. +Once stable, it uses binary search to calculate pressure offsets that align baro altitude with GNSS altitude (0.1m precision), then applies the offset to all sensors and saves the parameters. + +Notes: + +- **EKF Independence**: GNSS-baro calibration operates independently of EKF2 altitude fusion settings. +- **Execution Timing**: Calibration runs even when [EKF2_GPS_CTRL](../advanced_config/parameter_reference.md#EKF2_GPS_CTRL) altitude fusion is disabled. +- **One-Time Process**: Each calibration session completes once per system startup. +- **Persistence**: Calibration offsets are saved to parameters and persist across reboots. +- **Faulty GNSS Vulnerability**: If GNSS data is faulty during boot, the calibration will use incorrect altitude reference. + See [Faulty GNSS Data During Boot](../advanced_config/tuning_the_ecl_ekf.md#faulty-gnss-data-during-boot) for mitigation strategies. + +## See Also - [Baro driver source code](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/barometer) - [Modules Reference: Baro (Driver)](../modules/modules_driver_baro.md) documentation. diff --git a/src/modules/ekf2/params_gnss.yaml b/src/modules/ekf2/params_gnss.yaml index b8168e494a..319846316d 100644 --- a/src/modules/ekf2/params_gnss.yaml +++ b/src/modules/ekf2/params_gnss.yaml @@ -20,8 +20,8 @@ parameters: EKF2_GPS_MODE: description: short: Fusion reset mode - long: 'Automatic: reset on fusion timeout if no other source of position is available - Dead-reckoning: reset on fusion timeout if no source of velocity is available' + long: 'Automatic: reset on fusion timeout if no other source of position is available. + Dead-reckoning: reset on fusion timeout if no source of velocity is available.' type: enum values: 0: Automatic From 6eb2251ee5a7e4c623d2f00c81ee0dc71e212414 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Wed, 26 Nov 2025 15:05:05 +1100 Subject: [PATCH 17/23] docs: Update metadata (#25993) --- docs/en/SUMMARY.md | 3 +- .../en/advanced_config/parameter_reference.md | 88 +++- docs/en/config_rover/basic_setup.md | 2 +- docs/en/config_rover/position_tuning.md | 5 +- docs/en/config_rover/velocity_tuning.md | 4 +- docs/en/middleware/dds_topics.md | 486 +++++++++--------- docs/en/modules/modules_driver.md | 85 +-- docs/en/modules/modules_driver_adc.md | 107 ++++ .../modules/modules_driver_radio_control.md | 20 +- docs/en/msg_docs/AdcReport.md | 18 +- docs/en/msg_docs/EscReport.md | 15 +- docs/en/msg_docs/InputRc.md | 4 +- docs/en/msg_docs/RoverVelocitySetpoint.md | 15 - docs/en/msg_docs/RoverVelocityStatus.md | 18 - docs/en/msg_docs/SensorTemp.md | 11 + docs/en/msg_docs/VehicleCommand.md | 2 +- docs/en/msg_docs/index.md | 3 +- 17 files changed, 508 insertions(+), 378 deletions(-) create mode 100644 docs/en/modules/modules_driver_adc.md delete mode 100644 docs/en/msg_docs/RoverVelocitySetpoint.md delete mode 100644 docs/en/msg_docs/RoverVelocityStatus.md create mode 100644 docs/en/msg_docs/SensorTemp.md diff --git a/docs/en/SUMMARY.md b/docs/en/SUMMARY.md index 58317715a3..8cbcaa427d 100644 --- a/docs/en/SUMMARY.md +++ b/docs/en/SUMMARY.md @@ -672,8 +672,6 @@ - [RoverSpeedStatus](msg_docs/RoverSpeedStatus.md) - [RoverSteeringSetpoint](msg_docs/RoverSteeringSetpoint.md) - [RoverThrottleSetpoint](msg_docs/RoverThrottleSetpoint.md) - - [RoverVelocitySetpoint](msg_docs/RoverVelocitySetpoint.md) - - [RoverVelocityStatus](msg_docs/RoverVelocityStatus.md) - [Rpm](msg_docs/Rpm.md) - [RtlStatus](msg_docs/RtlStatus.md) - [RtlTimeEstimate](msg_docs/RtlTimeEstimate.md) @@ -695,6 +693,7 @@ - [SensorOpticalFlow](msg_docs/SensorOpticalFlow.md) - [SensorPreflightMag](msg_docs/SensorPreflightMag.md) - [SensorSelection](msg_docs/SensorSelection.md) + - [SensorTemp](msg_docs/SensorTemp.md) - [SensorUwb](msg_docs/SensorUwb.md) - [SensorsStatus](msg_docs/SensorsStatus.md) - [SensorsStatusImu](msg_docs/SensorsStatusImu.md) diff --git a/docs/en/advanced_config/parameter_reference.md b/docs/en/advanced_config/parameter_reference.md index 7eca46d3f3..0c1a843a55 100644 --- a/docs/en/advanced_config/parameter_reference.md +++ b/docs/en/advanced_config/parameter_reference.md @@ -10,6 +10,48 @@ If a listed parameter is missing from the Firmware see: [Finding/Updating Parame +## ADC + +### ADC_ADS7953_EN (`INT32`) {#ADC_ADS7953_EN} + +Enable ADS7953. + +Enable the driver for the ADS7953 board + +| Reboot | minValue | maxValue | increment | default | unit | +| ------- | -------- | -------- | --------- | ------------ | ---- | +| ✓ | | | | Disabled (0) | + +### ADC_ADS7953_REFV (`FLOAT`) {#ADC_ADS7953_REFV} + +Applied reference Voltage. + +The voltage applied to the ADS7953 board as reference + +| Reboot | minValue | maxValue | increment | default | unit | +| ------- | -------- | -------- | --------- | ------- | ---- | +| ✓ | 2.0 | 3.0 | 0.01 | 2.5 | V | + +### ADC_TLA2528_EN (`INT32`) {#ADC_TLA2528_EN} + +Enable TLA2528. + +Enable the driver for the TLA2528 + +| Reboot | minValue | maxValue | increment | default | unit | +| ------- | -------- | -------- | --------- | ------------ | ---- | +| ✓ | | | | Disabled (0) | + +### ADC_TLA2528_REFV (`FLOAT`) {#ADC_TLA2528_REFV} + +Applied reference Voltage. + +The voltage applied to the TLA2528 board as reference + +| Reboot | minValue | maxValue | increment | default | unit | +| ------- | -------- | -------- | --------- | ------- | ---- | +| ✓ | 2.0 | 3.0 | 0.01 | 2.5 | V | + ## ADSB ### ADSB_CALLSIGN_1 (`INT32`) {#ADSB_CALLSIGN_1} @@ -13955,9 +13997,9 @@ Scale of airspeed sensor 1. This is the scale IAS --> CAS of the first airspeed sensor instance -| Reboot | minValue | maxValue | increment | default | unit | -| ------- | -------- | -------- | --------- | ------- | ---- | -| ✓ | 0.5 | 2.0 | | 1.0 | +| Reboot | minValue | maxValue | increment | default | unit | +| ------ | -------- | -------- | --------- | ------- | ---- | +|   | 0.5 | 2.0 | | 1.0 | ### ASPD_SCALE_2 (`FLOAT`) {#ASPD_SCALE_2} @@ -13965,9 +14007,9 @@ Scale of airspeed sensor 2. This is the scale IAS --> CAS of the second airspeed sensor instance -| Reboot | minValue | maxValue | increment | default | unit | -| ------- | -------- | -------- | --------- | ------- | ---- | -| ✓ | 0.5 | 2.0 | | 1.0 | +| Reboot | minValue | maxValue | increment | default | unit | +| ------ | -------- | -------- | --------- | ------- | ---- | +|   | 0.5 | 2.0 | | 1.0 | ### ASPD_SCALE_3 (`FLOAT`) {#ASPD_SCALE_3} @@ -13975,9 +14017,9 @@ Scale of airspeed sensor 3. This is the scale IAS --> CAS of the third airspeed sensor instance -| Reboot | minValue | maxValue | increment | default | unit | -| ------- | -------- | -------- | --------- | ------- | ---- | -| ✓ | 0.5 | 2.0 | | 1.0 | +| Reboot | minValue | maxValue | increment | default | unit | +| ------ | -------- | -------- | --------- | ------- | ---- | +|   | 0.5 | 2.0 | | 1.0 | ### ASPD_SCALE_APPLY (`INT32`) {#ASPD_SCALE_APPLY} @@ -17165,7 +17207,9 @@ Set bits in the following positions to enable: 0 : Longitude and latitude fusion ### EKF2_GPS_DELAY (`FLOAT`) {#EKF2_GPS_DELAY} -GPS measurement delay relative to IMU measurements. +GPS measurement delay relative to IMU measurement. + +GPS measurement delay relative to IMU measurement if PPS time correction is not available/enabled (PPS_CAP_ENABLE). | Reboot | minValue | maxValue | increment | default | unit | | ------- | -------- | -------- | --------- | ------- | ---- | @@ -17175,7 +17219,7 @@ GPS measurement delay relative to IMU measurements. Fusion reset mode. -Automatic: reset on fusion timeout if no other source of position is available Dead-reckoning: reset on fusion timeout if no source of velocity is available +Automatic: reset on fusion timeout if no other source of position is available. Dead-reckoning: reset on fusion timeout if no source of velocity is available. **Values:** @@ -33105,6 +33149,14 @@ Maxbotix Sonar (mb12xx). | ------- | -------- | -------- | --------- | ------------ | ---- | | ✓ | | | | Disabled (0) | +### SENS_EN_MCP9808 (`INT32`) {#SENS_EN_MCP9808} + +Enable MCP9808 temperature sensor (external I2C). + +| Reboot | minValue | maxValue | increment | default | unit | +| ------- | -------- | -------- | --------- | ------------ | ---- | +| ✓ | | | | Disabled (0) | + ### SENS_EN_MPDT (`INT32`) {#SENS_EN_MPDT} Enable Mappydot rangefinder (i2c). @@ -39432,6 +39484,14 @@ Maximum time (in seconds) before resetting setpoint. | ------ | -------- | -------- | --------- | ------- | ---- | |   | | | | 2.0 | +### UUV_STICK_MODE (`INT32`) {#UUV_STICK_MODE} + +Stick mode selector (0=Heave/sway control, roll/pitch leveled; 1=Pitch/roll control). + +| Reboot | minValue | maxValue | increment | default | unit | +| ------ | -------- | -------- | --------- | ------- | ---- | +|   | 0 | 1 | | 0 | + ### UUV_THRUST_SAT (`FLOAT`) {#UUV_THRUST_SAT} UUV Thrust setpoint Saturation. @@ -40135,7 +40195,7 @@ Time in seconds it takes to tilt form VT_TILT_FW to VT_TILT_MC. ### VT_B_DEC_I (`FLOAT`) {#VT_B_DEC_I} -Backtransition deceleration setpoint to pitch I gain. +Backtransition deceleration setpoint to tilt I gain. | Reboot | minValue | maxValue | increment | default | unit | | ------ | -------- | -------- | --------- | ------- | ------- | @@ -40353,7 +40413,7 @@ During landing it can be beneficial to reduce the pitch angle to reduce the gene | Reboot | minValue | maxValue | increment | default | unit | | ------ | -------- | -------- | --------- | ------- | ---- | -|   | -10.0 | 45.0 | 0.1 | -5.0 | deg | +|   | -10.0 | 45.0 | 0.1 | 0.0 | deg | ### VT_PITCH_MIN (`FLOAT`) {#VT_PITCH_MIN} @@ -40364,7 +40424,7 @@ VT_FWD_TRHUST_EN is set. | Reboot | minValue | maxValue | increment | default | unit | | ------ | -------- | -------- | --------- | ------- | ---- | -|   | -10.0 | 45.0 | 0.1 | -5.0 | deg | +|   | -10.0 | 45.0 | 0.1 | 0.0 | deg | ### VT_PSHER_SLEW (`FLOAT`) {#VT_PSHER_SLEW} diff --git a/docs/en/config_rover/basic_setup.md b/docs/en/config_rover/basic_setup.md index 328e04950c..e729fc6328 100644 --- a/docs/en/config_rover/basic_setup.md +++ b/docs/en/config_rover/basic_setup.md @@ -88,7 +88,7 @@ Navigate to [Parameters](../advanced_config/parameters.md) in QGroundControl and One approach to determine an appropriate value is: 1. From a standstill, give the rover full throttle until it reaches the maximum speed. - 2. Disarm the rover and plot the `measured_speed_body_x` from [RoverVelocityStatus](../msg_docs/RoverVelocityStatus.md). + 2. Disarm the rover and plot the `measured_speed_body_x` from [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md). 3. Divide the maximum speed by the time it took to reach it and set this as the value for [RO_ACCEL_LIM](#RO_ACCEL_LIM). Some RC rovers have enough torque to lift up if the maximum acceleration is not limited. diff --git a/docs/en/config_rover/position_tuning.md b/docs/en/config_rover/position_tuning.md index 933e528cbe..f5e7f6ae2e 100644 --- a/docs/en/config_rover/position_tuning.md +++ b/docs/en/config_rover/position_tuning.md @@ -19,7 +19,6 @@ To tune the position controller configure the [parameters](../advanced_config/pa $v*{max} = v*{full throttle} \cdot (1 - \theta\_{normalized} \cdot k) $ with - - $v_{max}:$ Maximum speed - $v_{full throttle}:$ Speed at maximum throttle [RO_MAX_THR_SPEED](../advanced_config/parameter_reference.md#RO_MAX_THR_SPEED). - $\theta_{normalized}:$ Course error (Course - bearing setpoint) normalized from $[0\degree, 180\degree]$ to $[0, 1]$ @@ -34,14 +33,13 @@ To tune the position controller configure the [parameters](../advanced_config/pa ::: tip Plan a mission for the rover to drive a square and observe how it slows down when approaching a waypoint: - - If the rover decelerates too quickly decrease the [RO_DECEL_LIM](../advanced_config/parameter_reference.md#RO_DECEL_LIM) parameter, if it starts slowing down too early increase the parameter. - If you observe a jerking motion as the rover slows down, decrease the [RO_JERK_LIM](../advanced_config/parameter_reference.md#RO_JERK_LIM) parameter otherwise increase it as much as possible as it can interfere with the tuning of [RO_DECEL_LIM](../advanced_config/parameter_reference.md#RO_DECEL_LIM). These two parameters have to be tuned as a pair, repeat until you are satisfied with the behaviour. ::: -3. Plot the `adjusted_speed_body_x_setpoint` and `measured_speed_body_x` from the [RoverVelocityStatus](../msg_docs/RoverVelocityStatus.md) message over each other. +3. Plot the `adjusted_speed_body_x_setpoint` and `measured_speed_body_x` from the [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md) message over each other. If the tracking of these setpoints is not satisfactory adjust the values for [RO_SPEED_P](../advanced_config/parameter_reference.md#RO_SPEED_P) and [RO_SPEED_I](../advanced_config/parameter_reference.md#RO_SPEED_I). ## Path Following @@ -57,7 +55,6 @@ The following parameters are used to tune the algorithm: Decreasing the parameter makes it more aggressive but can lead to oscillations. To tune this: - 1. Start with a value of 1 for [PP_LOOKAHD_GAIN](#PP_LOOKAHD_GAIN) 2. Put the rover in [Position mode](../flight_modes_rover/manual.md#position-mode) and while driving a straight line at approximately half the maximum speed observe its behaviour. 3. If the rover does not drive in a straight line, reduce the value of the parameter, if it oscillates around the path increase the value. diff --git a/docs/en/config_rover/velocity_tuning.md b/docs/en/config_rover/velocity_tuning.md index 04323e7413..bf0429d43f 100644 --- a/docs/en/config_rover/velocity_tuning.md +++ b/docs/en/config_rover/velocity_tuning.md @@ -23,11 +23,10 @@ To tune the velocity controller configure the following [parameters](../advanced ::: tip To further tune this parameter: - 1. Set [RO_SPEED_P](#RO_SPEED_P) and [RO_SPEED_I](#RO_SPEED_I) to zero. This way the speed is only controlled by the feed-forward term, which makes it easier to tune. 2. Put the rover in [Position mode](../flight_modes_rover/manual.md#position-mode) and then move the left stick of your controller up and/or down and hold it at a few different levels for a couple of seconds each. - 3. Disarm the rover and from the flight log plot the `adjusted_speed_body_x_setpoint` and the `measured_speed_body_x` from the [RoverVelocityStatus](../msg_docs/RoverVelocityStatus.md) message over each other. + 3. Disarm the rover and from the flight log plot the `adjusted_speed_body_x_setpoint` and the `measured_speed_body_x` from the [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md) message over each other. 4. If the actual speed of the rover is higher than the speed setpoint, increase [RO_MAX_THR_SPEED](#RO_MAX_THR_SPEED). If it is the other way around decrease the parameter and repeat until you are satisfied with the setpoint tracking. @@ -64,7 +63,6 @@ These steps are only necessary if you are tuning/want to unlock the manual [Posi Decreasing the parameter makes it more aggressive but can lead to oscillations. To tune this: - 1. Start with a value of 1 for [PP_LOOKAHD_GAIN](#PP_LOOKAHD_GAIN) 2. Put the rover in [Position mode](../flight_modes_rover/manual.md#position-mode) and while driving a straight line at approximately half the maximum speed observe its behaviour. 3. If the rover does not drive in a straight line, reduce the value of the parameter, if it oscillates around the path increase the value. diff --git a/docs/en/middleware/dds_topics.md b/docs/en/middleware/dds_topics.md index 82ec12edcd..07ec63404c 100644 --- a/docs/en/middleware/dds_topics.md +++ b/docs/en/middleware/dds_topics.md @@ -4,75 +4,84 @@ This document is [auto-generated](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/msg/generate_msg_docs.py) from the source code. ::: - -The [dds_topics.yaml](https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/uxrce_dds_client/dds_topics.yaml) file specifies which uORB message definitions are compiled into the [uxrce_dds_client](../modules/modules_system.md#uxrce-dds-client) and/or [zenoh](../modules/modules_driver.md#zenoh) module when [PX4 is built](../middleware/uxrce_dds.md#code-generation), and hence which topics are available for ROS 2 applications to subscribe or publish (by default). +The [dds_topics.yaml](https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/uxrce_dds_client/dds_topics.yaml) file specifies which uORB message definitions are compiled into the [uxrce_dds_client](../modules/modules_system.md#uxrce-dds-client) module when [PX4 is built](../middleware/uxrce_dds.md#code-generation), and hence which topics are available for ROS 2 applications to subscribe or publish (by default). This document shows a markdown-rendered version of [dds_topics.yaml](https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/uxrce_dds_client/dds_topics.yaml), listing the publications, subscriptions, and so on. ## Publications -Topic | Type| Rate Limit ---- | --- | --- -`/fmu/out/register_ext_component_reply` | [px4_msgs::msg::RegisterExtComponentReply](../msg_docs/RegisterExtComponentReply.md) | -`/fmu/out/arming_check_request` | [px4_msgs::msg::ArmingCheckRequest](../msg_docs/ArmingCheckRequest.md) | 5.0 -`/fmu/out/mode_completed` | [px4_msgs::msg::ModeCompleted](../msg_docs/ModeCompleted.md) | 50.0 -`/fmu/out/battery_status` | [px4_msgs::msg::BatteryStatus](../msg_docs/BatteryStatus.md) | 1.0 -`/fmu/out/collision_constraints` | [px4_msgs::msg::CollisionConstraints](../msg_docs/CollisionConstraints.md) | 50.0 -`/fmu/out/estimator_status_flags` | [px4_msgs::msg::EstimatorStatusFlags](../msg_docs/EstimatorStatusFlags.md) | 5.0 -`/fmu/out/failsafe_flags` | [px4_msgs::msg::FailsafeFlags](../msg_docs/FailsafeFlags.md) | 5.0 -`/fmu/out/manual_control_setpoint` | [px4_msgs::msg::ManualControlSetpoint](../msg_docs/ManualControlSetpoint.md) | 25.0 -`/fmu/out/message_format_response` | [px4_msgs::msg::MessageFormatResponse](../msg_docs/MessageFormatResponse.md) | -`/fmu/out/position_setpoint_triplet` | [px4_msgs::msg::PositionSetpointTriplet](../msg_docs/PositionSetpointTriplet.md) | 5.0 -`/fmu/out/sensor_combined` | [px4_msgs::msg::SensorCombined](../msg_docs/SensorCombined.md) | -`/fmu/out/timesync_status` | [px4_msgs::msg::TimesyncStatus](../msg_docs/TimesyncStatus.md) | 10.0 -`/fmu/out/vehicle_land_detected` | [px4_msgs::msg::VehicleLandDetected](../msg_docs/VehicleLandDetected.md) | 5.0 -`/fmu/out/vehicle_attitude` | [px4_msgs::msg::VehicleAttitude](../msg_docs/VehicleAttitude.md) | -`/fmu/out/vehicle_control_mode` | [px4_msgs::msg::VehicleControlMode](../msg_docs/VehicleControlMode.md) | 50.0 -`/fmu/out/vehicle_command_ack` | [px4_msgs::msg::VehicleCommandAck](../msg_docs/VehicleCommandAck.md) | -`/fmu/out/vehicle_global_position` | [px4_msgs::msg::VehicleGlobalPosition](../msg_docs/VehicleGlobalPosition.md) | 50.0 -`/fmu/out/vehicle_gps_position` | [px4_msgs::msg::SensorGps](../msg_docs/SensorGps.md) | 50.0 -`/fmu/out/vehicle_local_position` | [px4_msgs::msg::VehicleLocalPosition](../msg_docs/VehicleLocalPosition.md) | 50.0 -`/fmu/out/vehicle_odometry` | [px4_msgs::msg::VehicleOdometry](../msg_docs/VehicleOdometry.md) | -`/fmu/out/vehicle_status` | [px4_msgs::msg::VehicleStatus](../msg_docs/VehicleStatus.md) | 5.0 -`/fmu/out/airspeed_validated` | [px4_msgs::msg::AirspeedValidated](../msg_docs/AirspeedValidated.md) | 50.0 -`/fmu/out/vtol_vehicle_status` | [px4_msgs::msg::VtolVehicleStatus](../msg_docs/VtolVehicleStatus.md) | -`/fmu/out/home_position` | [px4_msgs::msg::HomePosition](../msg_docs/HomePosition.md) | 5.0 +| Topic | Type | Rate Limit | +| ---------------------------------------- | -------------------------------------------------------------------------------------- | ---------- | +| `/fmu/out/register_ext_component_reply` | [px4_msgs::msg::RegisterExtComponentReply](../msg_docs/RegisterExtComponentReply.md) | +| `/fmu/out/arming_check_request` | [px4_msgs::msg::ArmingCheckRequest](../msg_docs/ArmingCheckRequest.md) | 5.0 | +| `/fmu/out/mode_completed` | [px4_msgs::msg::ModeCompleted](../msg_docs/ModeCompleted.md) | 50.0 | +| `/fmu/out/battery_status` | [px4_msgs::msg::BatteryStatus](../msg_docs/BatteryStatus.md) | 1.0 | +| `/fmu/out/collision_constraints` | [px4_msgs::msg::CollisionConstraints](../msg_docs/CollisionConstraints.md) | 50.0 | +| `/fmu/out/estimator_status_flags` | [px4_msgs::msg::EstimatorStatusFlags](../msg_docs/EstimatorStatusFlags.md) | 5.0 | +| `/fmu/out/failsafe_flags` | [px4_msgs::msg::FailsafeFlags](../msg_docs/FailsafeFlags.md) | 5.0 | +| `/fmu/out/manual_control_setpoint` | [px4_msgs::msg::ManualControlSetpoint](../msg_docs/ManualControlSetpoint.md) | 25.0 | +| `/fmu/out/message_format_response` | [px4_msgs::msg::MessageFormatResponse](../msg_docs/MessageFormatResponse.md) | +| `/fmu/out/position_setpoint_triplet` | [px4_msgs::msg::PositionSetpointTriplet](../msg_docs/PositionSetpointTriplet.md) | 5.0 | +| `/fmu/out/sensor_combined` | [px4_msgs::msg::SensorCombined](../msg_docs/SensorCombined.md) | +| `/fmu/out/timesync_status` | [px4_msgs::msg::TimesyncStatus](../msg_docs/TimesyncStatus.md) | 10.0 | +| `/fmu/out/transponder_report` | [px4_msgs::msg::TransponderReport](../msg_docs/TransponderReport.md) | +| `/fmu/out/vehicle_land_detected` | [px4_msgs::msg::VehicleLandDetected](../msg_docs/VehicleLandDetected.md) | 5.0 | +| `/fmu/out/vehicle_attitude` | [px4_msgs::msg::VehicleAttitude](../msg_docs/VehicleAttitude.md) | 50.0 | +| `/fmu/out/vehicle_control_mode` | [px4_msgs::msg::VehicleControlMode](../msg_docs/VehicleControlMode.md) | 50.0 | +| `/fmu/out/vehicle_command_ack` | [px4_msgs::msg::VehicleCommandAck](../msg_docs/VehicleCommandAck.md) | +| `/fmu/out/vehicle_global_position` | [px4_msgs::msg::VehicleGlobalPosition](../msg_docs/VehicleGlobalPosition.md) | 50.0 | +| `/fmu/out/vehicle_gps_position` | [px4_msgs::msg::SensorGps](../msg_docs/SensorGps.md) | 50.0 | +| `/fmu/out/vehicle_local_position` | [px4_msgs::msg::VehicleLocalPosition](../msg_docs/VehicleLocalPosition.md) | 50.0 | +| `/fmu/out/vehicle_odometry` | [px4_msgs::msg::VehicleOdometry](../msg_docs/VehicleOdometry.md) | 100.0 | +| `/fmu/out/vehicle_status` | [px4_msgs::msg::VehicleStatus](../msg_docs/VehicleStatus.md) | 5.0 | +| `/fmu/out/airspeed_validated` | [px4_msgs::msg::AirspeedValidated](../msg_docs/AirspeedValidated.md) | 50.0 | +| `/fmu/out/vtol_vehicle_status` | [px4_msgs::msg::VtolVehicleStatus](../msg_docs/VtolVehicleStatus.md) | +| `/fmu/out/home_position` | [px4_msgs::msg::HomePosition](../msg_docs/HomePosition.md) | 5.0 | +| `/fmu/out/wind` | [px4_msgs::msg::Wind](../msg_docs/Wind.md) | 1.0 | +| `/fmu/out/gimbal_device_attitude_status` | [px4_msgs::msg::GimbalDeviceAttitudeStatus](../msg_docs/GimbalDeviceAttitudeStatus.md) | 20.0 | ## Subscriptions -Topic | Type ---- | --- -/fmu/in/register_ext_component_request | [px4_msgs::msg::RegisterExtComponentRequest](../msg_docs/RegisterExtComponentRequest.md) -/fmu/in/unregister_ext_component | [px4_msgs::msg::UnregisterExtComponent](../msg_docs/UnregisterExtComponent.md) -/fmu/in/config_overrides_request | [px4_msgs::msg::ConfigOverrides](../msg_docs/ConfigOverrides.md) -/fmu/in/arming_check_reply | [px4_msgs::msg::ArmingCheckReply](../msg_docs/ArmingCheckReply.md) -/fmu/in/message_format_request | [px4_msgs::msg::MessageFormatRequest](../msg_docs/MessageFormatRequest.md) -/fmu/in/mode_completed | [px4_msgs::msg::ModeCompleted](../msg_docs/ModeCompleted.md) -/fmu/in/config_control_setpoints | [px4_msgs::msg::VehicleControlMode](../msg_docs/VehicleControlMode.md) -/fmu/in/distance_sensor | [px4_msgs::msg::DistanceSensor](../msg_docs/DistanceSensor.md) -/fmu/in/manual_control_input | [px4_msgs::msg::ManualControlSetpoint](../msg_docs/ManualControlSetpoint.md) -/fmu/in/offboard_control_mode | [px4_msgs::msg::OffboardControlMode](../msg_docs/OffboardControlMode.md) -/fmu/in/onboard_computer_status | [px4_msgs::msg::OnboardComputerStatus](../msg_docs/OnboardComputerStatus.md) -/fmu/in/obstacle_distance | [px4_msgs::msg::ObstacleDistance](../msg_docs/ObstacleDistance.md) -/fmu/in/sensor_optical_flow | [px4_msgs::msg::SensorOpticalFlow](../msg_docs/SensorOpticalFlow.md) -/fmu/in/goto_setpoint | [px4_msgs::msg::GotoSetpoint](../msg_docs/GotoSetpoint.md) -/fmu/in/telemetry_status | [px4_msgs::msg::TelemetryStatus](../msg_docs/TelemetryStatus.md) -/fmu/in/trajectory_setpoint | [px4_msgs::msg::TrajectorySetpoint](../msg_docs/TrajectorySetpoint.md) -/fmu/in/vehicle_attitude_setpoint | [px4_msgs::msg::VehicleAttitudeSetpoint](../msg_docs/VehicleAttitudeSetpoint.md) -/fmu/in/vehicle_mocap_odometry | [px4_msgs::msg::VehicleOdometry](../msg_docs/VehicleOdometry.md) -/fmu/in/vehicle_rates_setpoint | [px4_msgs::msg::VehicleRatesSetpoint](../msg_docs/VehicleRatesSetpoint.md) -/fmu/in/vehicle_visual_odometry | [px4_msgs::msg::VehicleOdometry](../msg_docs/VehicleOdometry.md) -/fmu/in/vehicle_command | [px4_msgs::msg::VehicleCommand](../msg_docs/VehicleCommand.md) -/fmu/in/vehicle_command_mode_executor | [px4_msgs::msg::VehicleCommand](../msg_docs/VehicleCommand.md) -/fmu/in/vehicle_thrust_setpoint | [px4_msgs::msg::VehicleThrustSetpoint](../msg_docs/VehicleThrustSetpoint.md) -/fmu/in/vehicle_torque_setpoint | [px4_msgs::msg::VehicleTorqueSetpoint](../msg_docs/VehicleTorqueSetpoint.md) -/fmu/in/actuator_motors | [px4_msgs::msg::ActuatorMotors](../msg_docs/ActuatorMotors.md) -/fmu/in/actuator_servos | [px4_msgs::msg::ActuatorServos](../msg_docs/ActuatorServos.md) -/fmu/in/aux_global_position | [px4_msgs::msg::VehicleGlobalPosition](../msg_docs/VehicleGlobalPosition.md) -/fmu/in/fixed_wing_longitudinal_setpoint | [px4_msgs::msg::FixedWingLongitudinalSetpoint](../msg_docs/FixedWingLongitudinalSetpoint.md) -/fmu/in/fixed_wing_lateral_setpoint | [px4_msgs::msg::FixedWingLateralSetpoint](../msg_docs/FixedWingLateralSetpoint.md) -/fmu/in/longitudinal_control_configuration | [px4_msgs::msg::LongitudinalControlConfiguration](../msg_docs/LongitudinalControlConfiguration.md) -/fmu/in/lateral_control_configuration | [px4_msgs::msg::LateralControlConfiguration](../msg_docs/LateralControlConfiguration.md) +| Topic | Type | +| ------------------------------------------ | -------------------------------------------------------------------------------------------------- | +| /fmu/in/register_ext_component_request | [px4_msgs::msg::RegisterExtComponentRequest](../msg_docs/RegisterExtComponentRequest.md) | +| /fmu/in/unregister_ext_component | [px4_msgs::msg::UnregisterExtComponent](../msg_docs/UnregisterExtComponent.md) | +| /fmu/in/config_overrides_request | [px4_msgs::msg::ConfigOverrides](../msg_docs/ConfigOverrides.md) | +| /fmu/in/arming_check_reply | [px4_msgs::msg::ArmingCheckReply](../msg_docs/ArmingCheckReply.md) | +| /fmu/in/message_format_request | [px4_msgs::msg::MessageFormatRequest](../msg_docs/MessageFormatRequest.md) | +| /fmu/in/mode_completed | [px4_msgs::msg::ModeCompleted](../msg_docs/ModeCompleted.md) | +| /fmu/in/config_control_setpoints | [px4_msgs::msg::VehicleControlMode](../msg_docs/VehicleControlMode.md) | +| /fmu/in/distance_sensor | [px4_msgs::msg::DistanceSensor](../msg_docs/DistanceSensor.md) | +| /fmu/in/manual_control_input | [px4_msgs::msg::ManualControlSetpoint](../msg_docs/ManualControlSetpoint.md) | +| /fmu/in/offboard_control_mode | [px4_msgs::msg::OffboardControlMode](../msg_docs/OffboardControlMode.md) | +| /fmu/in/onboard_computer_status | [px4_msgs::msg::OnboardComputerStatus](../msg_docs/OnboardComputerStatus.md) | +| /fmu/in/obstacle_distance | [px4_msgs::msg::ObstacleDistance](../msg_docs/ObstacleDistance.md) | +| /fmu/in/sensor_optical_flow | [px4_msgs::msg::SensorOpticalFlow](../msg_docs/SensorOpticalFlow.md) | +| /fmu/in/goto_setpoint | [px4_msgs::msg::GotoSetpoint](../msg_docs/GotoSetpoint.md) | +| /fmu/in/telemetry_status | [px4_msgs::msg::TelemetryStatus](../msg_docs/TelemetryStatus.md) | +| /fmu/in/trajectory_setpoint | [px4_msgs::msg::TrajectorySetpoint](../msg_docs/TrajectorySetpoint.md) | +| /fmu/in/vehicle_attitude_setpoint | [px4_msgs::msg::VehicleAttitudeSetpoint](../msg_docs/VehicleAttitudeSetpoint.md) | +| /fmu/in/vehicle_mocap_odometry | [px4_msgs::msg::VehicleOdometry](../msg_docs/VehicleOdometry.md) | +| /fmu/in/vehicle_rates_setpoint | [px4_msgs::msg::VehicleRatesSetpoint](../msg_docs/VehicleRatesSetpoint.md) | +| /fmu/in/vehicle_visual_odometry | [px4_msgs::msg::VehicleOdometry](../msg_docs/VehicleOdometry.md) | +| /fmu/in/vehicle_command | [px4_msgs::msg::VehicleCommand](../msg_docs/VehicleCommand.md) | +| /fmu/in/vehicle_command_mode_executor | [px4_msgs::msg::VehicleCommand](../msg_docs/VehicleCommand.md) | +| /fmu/in/vehicle_thrust_setpoint | [px4_msgs::msg::VehicleThrustSetpoint](../msg_docs/VehicleThrustSetpoint.md) | +| /fmu/in/vehicle_torque_setpoint | [px4_msgs::msg::VehicleTorqueSetpoint](../msg_docs/VehicleTorqueSetpoint.md) | +| /fmu/in/actuator_motors | [px4_msgs::msg::ActuatorMotors](../msg_docs/ActuatorMotors.md) | +| /fmu/in/actuator_servos | [px4_msgs::msg::ActuatorServos](../msg_docs/ActuatorServos.md) | +| /fmu/in/aux_global_position | [px4_msgs::msg::VehicleGlobalPosition](../msg_docs/VehicleGlobalPosition.md) | +| /fmu/in/fixed_wing_longitudinal_setpoint | [px4_msgs::msg::FixedWingLongitudinalSetpoint](../msg_docs/FixedWingLongitudinalSetpoint.md) | +| /fmu/in/fixed_wing_lateral_setpoint | [px4_msgs::msg::FixedWingLateralSetpoint](../msg_docs/FixedWingLateralSetpoint.md) | +| /fmu/in/longitudinal_control_configuration | [px4_msgs::msg::LongitudinalControlConfiguration](../msg_docs/LongitudinalControlConfiguration.md) | +| /fmu/in/lateral_control_configuration | [px4_msgs::msg::LateralControlConfiguration](../msg_docs/LateralControlConfiguration.md) | +| /fmu/in/rover_position_setpoint | [px4_msgs::msg::RoverPositionSetpoint](../msg_docs/RoverPositionSetpoint.md) | +| /fmu/in/rover_speed_setpoint | [px4_msgs::msg::RoverSpeedSetpoint](../msg_docs/RoverSpeedSetpoint.md) | +| /fmu/in/rover_attitude_setpoint | [px4_msgs::msg::RoverAttitudeSetpoint](../msg_docs/RoverAttitudeSetpoint.md) | +| /fmu/in/rover_rate_setpoint | [px4_msgs::msg::RoverRateSetpoint](../msg_docs/RoverRateSetpoint.md) | +| /fmu/in/rover_throttle_setpoint | [px4_msgs::msg::RoverThrottleSetpoint](../msg_docs/RoverThrottleSetpoint.md) | +| /fmu/in/rover_steering_setpoint | [px4_msgs::msg::RoverSteeringSetpoint](../msg_docs/RoverSteeringSetpoint.md) | +| /fmu/in/landing_gear | [px4_msgs::msg::LandingGear](../msg_docs/LandingGear.md) | ## Subscriptions Multi @@ -85,192 +94,191 @@ They are not build into the module, and hence are neither published or subscribe ::: details See messages -- [SensorCorrection](../msg_docs/SensorCorrection.md) -- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md) -- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md) -- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md) -- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md) -- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md) -- [Px4ioStatus](../msg_docs/Px4ioStatus.md) -- [SatelliteInfo](../msg_docs/SatelliteInfo.md) -- [GeofenceResult](../msg_docs/GeofenceResult.md) -- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md) -- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md) -- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md) -- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md) -- [EventV0](../msg_docs/EventV0.md) -- [QshellRetval](../msg_docs/QshellRetval.md) -- [RoverThrottleSetpoint](../msg_docs/RoverThrottleSetpoint.md) -- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md) -- [RcChannels](../msg_docs/RcChannels.md) -- [SensorAccel](../msg_docs/SensorAccel.md) -- [GimbalDeviceAttitudeStatus](../msg_docs/GimbalDeviceAttitudeStatus.md) -- [EscStatus](../msg_docs/EscStatus.md) -- [RoverAttitudeSetpoint](../msg_docs/RoverAttitudeSetpoint.md) -- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md) -- [AirspeedWind](../msg_docs/AirspeedWind.md) -- [InputRc](../msg_docs/InputRc.md) -- [GpioIn](../msg_docs/GpioIn.md) -- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md) -- [VehicleImu](../msg_docs/VehicleImu.md) -- [Event](../msg_docs/Event.md) -- [SensorUwb](../msg_docs/SensorUwb.md) -- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md) -- [DatamanResponse](../msg_docs/DatamanResponse.md) -- [OrbTest](../msg_docs/OrbTest.md) -- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md) -- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md) -- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md) -- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md) -- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md) +- [BatteryInfo](../msg_docs/BatteryInfo.md) - [TakeoffStatus](../msg_docs/TakeoffStatus.md) -- [UlogStreamAck](../msg_docs/UlogStreamAck.md) -- [OrbTestLarge](../msg_docs/OrbTestLarge.md) -- [RoverSteeringSetpoint](../msg_docs/RoverSteeringSetpoint.md) +- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md) +- [Airspeed](../msg_docs/Airspeed.md) +- [PpsCapture](../msg_docs/PpsCapture.md) +- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md) - [CameraCapture](../msg_docs/CameraCapture.md) -- [VehicleRoi](../msg_docs/VehicleRoi.md) -- [ActuatorArmed](../msg_docs/ActuatorArmed.md) -- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md) -- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md) -- [GeofenceStatus](../msg_docs/GeofenceStatus.md) -- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md) -- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md) -- [PowerMonitor](../msg_docs/PowerMonitor.md) -- [RoverVelocityStatus](../msg_docs/RoverVelocityStatus.md) -- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md) -- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md) -- [TecsStatus](../msg_docs/TecsStatus.md) -- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md) -- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md) -- [Ping](../msg_docs/Ping.md) -- [LedControl](../msg_docs/LedControl.md) -- [Wind](../msg_docs/Wind.md) -- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md) -- [ActuatorTest](../msg_docs/ActuatorTest.md) -- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md) -- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md) -- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md) -- [Gripper](../msg_docs/Gripper.md) -- [SensorMag](../msg_docs/SensorMag.md) -- [DebugValue](../msg_docs/DebugValue.md) -- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md) -- [RcParameterMap](../msg_docs/RcParameterMap.md) -- [LandingGear](../msg_docs/LandingGear.md) -- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md) +- [Px4ioStatus](../msg_docs/Px4ioStatus.md) +- [FuelTankStatus](../msg_docs/FuelTankStatus.md) +- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md) - [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md) -- [UlogStream](../msg_docs/UlogStream.md) -- [GimbalControls](../msg_docs/GimbalControls.md) -- [RoverRateSetpoint](../msg_docs/RoverRateSetpoint.md) -- [LogMessage](../msg_docs/LogMessage.md) -- [RoverVelocitySetpoint](../msg_docs/RoverVelocitySetpoint.md) +- [AirspeedWind](../msg_docs/AirspeedWind.md) +- [OrbTest](../msg_docs/OrbTest.md) +- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md) - [GpioOut](../msg_docs/GpioOut.md) -- [TaskStackInfo](../msg_docs/TaskStackInfo.md) +- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md) +- [Gripper](../msg_docs/Gripper.md) +- [VehicleAirData](../msg_docs/VehicleAirData.md) +- [TuneControl](../msg_docs/TuneControl.md) +- [DebugVect](../msg_docs/DebugVect.md) +- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md) +- [HomePositionV0](../msg_docs/HomePositionV0.md) +- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md) +- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md) +- [EstimatorBias](../msg_docs/EstimatorBias.md) +- [GpioConfig](../msg_docs/GpioConfig.md) +- [SystemPower](../msg_docs/SystemPower.md) +- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md) +- [MissionResult](../msg_docs/MissionResult.md) +- [PowerButtonState](../msg_docs/PowerButtonState.md) +- [EscStatus](../msg_docs/EscStatus.md) +- [HealthReport](../msg_docs/HealthReport.md) +- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md) +- [SensorGyro](../msg_docs/SensorGyro.md) +- [GpioRequest](../msg_docs/GpioRequest.md) +- [DebugKeyValue](../msg_docs/DebugKeyValue.md) +- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md) +- [ParameterUpdate](../msg_docs/ParameterUpdate.md) +- [SensorAirflow](../msg_docs/SensorAirflow.md) +- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md) +- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md) +- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md) +- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md) +- [ActionRequest](../msg_docs/ActionRequest.md) +- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md) +- [PwmInput](../msg_docs/PwmInput.md) +- [PowerMonitor](../msg_docs/PowerMonitor.md) +- [Mission](../msg_docs/Mission.md) +- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md) +- [FigureEightStatus](../msg_docs/FigureEightStatus.md) +- [RadioStatus](../msg_docs/RadioStatus.md) +- [VehicleRoi](../msg_docs/VehicleRoi.md) +- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md) +- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md) +- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md) +- [Rpm](../msg_docs/Rpm.md) +- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md) +- [Ping](../msg_docs/Ping.md) +- [QshellReq](../msg_docs/QshellReq.md) +- [SensorMag](../msg_docs/SensorMag.md) +- [EstimatorStates](../msg_docs/EstimatorStates.md) +- [SensorUwb](../msg_docs/SensorUwb.md) +- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md) +- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md) +- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md) +- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md) +- [SensorHygrometer](../msg_docs/SensorHygrometer.md) +- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md) +- [AdcReport](../msg_docs/AdcReport.md) +- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md) +- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md) +- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md) +- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md) +- [SensorCorrection](../msg_docs/SensorCorrection.md) +- [UlogStream](../msg_docs/UlogStream.md) +- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md) +- [GpsInjectData](../msg_docs/GpsInjectData.md) +- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md) +- [LoggerStatus](../msg_docs/LoggerStatus.md) +- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md) +- [SensorBaro](../msg_docs/SensorBaro.md) +- [OrbTestMedium](../msg_docs/OrbTestMedium.md) +- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md) +- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md) +- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md) +- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md) +- [UlogStreamAck](../msg_docs/UlogStreamAck.md) +- [DatamanRequest](../msg_docs/DatamanRequest.md) +- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md) +- [PositionSetpoint](../msg_docs/PositionSetpoint.md) +- [DatamanResponse](../msg_docs/DatamanResponse.md) +- [LedControl](../msg_docs/LedControl.md) +- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md) +- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md) +- [Event](../msg_docs/Event.md) +- [ActuatorArmed](../msg_docs/ActuatorArmed.md) +- [GpioIn](../msg_docs/GpioIn.md) +- [SensorGyroFft](../msg_docs/SensorGyroFft.md) +- [SensorAccel](../msg_docs/SensorAccel.md) +- [SensorsStatus](../msg_docs/SensorsStatus.md) +- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md) +- [GeneratorStatus](../msg_docs/GeneratorStatus.md) +- [DifferentialPressure](../msg_docs/DifferentialPressure.md) +- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md) +- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md) +- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md) +- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md) +- [RoverRateStatus](../msg_docs/RoverRateStatus.md) +- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md) +- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md) - [VelocityLimits](../msg_docs/VelocityLimits.md) - [MagWorkerData](../msg_docs/MagWorkerData.md) -- [ParameterUpdate](../msg_docs/ParameterUpdate.md) -- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md) -- [SensorBaro](../msg_docs/SensorBaro.md) -- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md) -- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md) -- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md) -- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md) -- [Rpm](../msg_docs/Rpm.md) -- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md) -- [MountOrientation](../msg_docs/MountOrientation.md) -- [ActionRequest](../msg_docs/ActionRequest.md) -- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md) -- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md) -- [LoggerStatus](../msg_docs/LoggerStatus.md) -- [GeneratorStatus](../msg_docs/GeneratorStatus.md) -- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md) -- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md) -- [LandingTargetPose](../msg_docs/LandingTargetPose.md) -- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md) -- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md) -- [OrbitStatus](../msg_docs/OrbitStatus.md) -- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md) -- [EstimatorStatus](../msg_docs/EstimatorStatus.md) -- [DatamanRequest](../msg_docs/DatamanRequest.md) -- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md) -- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md) -- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md) - [Cpuload](../msg_docs/Cpuload.md) -- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md) -- [RoverRateStatus](../msg_docs/RoverRateStatus.md) -- [EscReport](../msg_docs/EscReport.md) -- [DebugArray](../msg_docs/DebugArray.md) -- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md) -- [SensorHygrometer](../msg_docs/SensorHygrometer.md) -- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md) -- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md) -- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md) -- [QshellReq](../msg_docs/QshellReq.md) -- [CameraStatus](../msg_docs/CameraStatus.md) -- [GpsInjectData](../msg_docs/GpsInjectData.md) -- [FigureEightStatus](../msg_docs/FigureEightStatus.md) -- [TransponderReport](../msg_docs/TransponderReport.md) -- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md) +- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md) +- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md) - [MavlinkLog](../msg_docs/MavlinkLog.md) -- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md) -- [FuelTankStatus](../msg_docs/FuelTankStatus.md) -- [Mission](../msg_docs/Mission.md) -- [PositionSetpoint](../msg_docs/PositionSetpoint.md) -- [MissionResult](../msg_docs/MissionResult.md) -- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md) -- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md) -- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md) -- [DifferentialPressure](../msg_docs/DifferentialPressure.md) -- [CellularStatus](../msg_docs/CellularStatus.md) -- [GpsDump](../msg_docs/GpsDump.md) -- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md) -- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md) -- [NavigatorStatus](../msg_docs/NavigatorStatus.md) -- [RoverPositionSetpoint](../msg_docs/RoverPositionSetpoint.md) -- [FollowTarget](../msg_docs/FollowTarget.md) -- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md) -- [EstimatorStates](../msg_docs/EstimatorStates.md) -- [SensorGyro](../msg_docs/SensorGyro.md) -- [SensorAirflow](../msg_docs/SensorAirflow.md) -- [ButtonEvent](../msg_docs/ButtonEvent.md) -- [DebugKeyValue](../msg_docs/DebugKeyValue.md) -- [GpioConfig](../msg_docs/GpioConfig.md) -- [CameraTrigger](../msg_docs/CameraTrigger.md) +- [SensorTemp](../msg_docs/SensorTemp.md) - [LandingGearWheel](../msg_docs/LandingGearWheel.md) -- [VehicleConstraints](../msg_docs/VehicleConstraints.md) -- [HealthReport](../msg_docs/HealthReport.md) -- [PowerButtonState](../msg_docs/PowerButtonState.md) -- [RadioStatus](../msg_docs/RadioStatus.md) -- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md) -- [EstimatorBias](../msg_docs/EstimatorBias.md) -- [DebugVect](../msg_docs/DebugVect.md) -- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md) -- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md) -- [PpsCapture](../msg_docs/PpsCapture.md) -- [SensorSelection](../msg_docs/SensorSelection.md) -- [SystemPower](../msg_docs/SystemPower.md) -- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md) -- [SensorGyroFft](../msg_docs/SensorGyroFft.md) -- [VehicleAirData](../msg_docs/VehicleAirData.md) +- [OrbTestLarge](../msg_docs/OrbTestLarge.md) - [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md) -- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md) -- [GpioRequest](../msg_docs/GpioRequest.md) -- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md) -- [RtlStatus](../msg_docs/RtlStatus.md) -- [Airspeed](../msg_docs/Airspeed.md) -- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md) -- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md) -- [IrlockReport](../msg_docs/IrlockReport.md) -- [HeaterStatus](../msg_docs/HeaterStatus.md) -- [AdcReport](../msg_docs/AdcReport.md) -- [PwmInput](../msg_docs/PwmInput.md) -- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md) -- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md) -- [OrbTestMedium](../msg_docs/OrbTestMedium.md) -- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md) -- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md) -- [TuneControl](../msg_docs/TuneControl.md) -- [WheelEncoders](../msg_docs/WheelEncoders.md) +- [CellularStatus](../msg_docs/CellularStatus.md) +- [QshellRetval](../msg_docs/QshellRetval.md) +- [OrbitStatus](../msg_docs/OrbitStatus.md) +- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md) +- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md) +- [LogMessage](../msg_docs/LogMessage.md) +- [SatelliteInfo](../msg_docs/SatelliteInfo.md) +- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md) +- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md) +- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md) +- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md) +- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md) +- [EstimatorStatus](../msg_docs/EstimatorStatus.md) +- [NeuralControl](../msg_docs/NeuralControl.md) +- [TaskStackInfo](../msg_docs/TaskStackInfo.md) +- [RcParameterMap](../msg_docs/RcParameterMap.md) +- [SensorSelection](../msg_docs/SensorSelection.md) +- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md) +- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md) +- [ActuatorTest](../msg_docs/ActuatorTest.md) +- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md) +- [MountOrientation](../msg_docs/MountOrientation.md) +- [CameraStatus](../msg_docs/CameraStatus.md) - [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md) -- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md) -- [SensorsStatus](../msg_docs/SensorsStatus.md) -::: +- [FollowTarget](../msg_docs/FollowTarget.md) +- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md) +- [ButtonEvent](../msg_docs/ButtonEvent.md) +- [DebugArray](../msg_docs/DebugArray.md) +- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md) +- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md) +- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md) +- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md) +- [VehicleImu](../msg_docs/VehicleImu.md) +- [GpsDump](../msg_docs/GpsDump.md) +- [WheelEncoders](../msg_docs/WheelEncoders.md) +- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md) +- [DebugValue](../msg_docs/DebugValue.md) +- [LandingTargetPose](../msg_docs/LandingTargetPose.md) +- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md) +- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md) +- [RtlStatus](../msg_docs/RtlStatus.md) +- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md) +- [GimbalControls](../msg_docs/GimbalControls.md) +- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md) +- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md) +- [HeaterStatus](../msg_docs/HeaterStatus.md) +- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md) +- [RcChannels](../msg_docs/RcChannels.md) +- [TecsStatus](../msg_docs/TecsStatus.md) +- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md) +- [InputRc](../msg_docs/InputRc.md) +- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md) +- [GeofenceResult](../msg_docs/GeofenceResult.md) +- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md) +- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md) +- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md) +- [NavigatorStatus](../msg_docs/NavigatorStatus.md) +- [CameraTrigger](../msg_docs/CameraTrigger.md) +- [EscReport](../msg_docs/EscReport.md) +- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md) +- [GeofenceStatus](../msg_docs/GeofenceStatus.md) +- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md) +- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md) +- [EventV0](../msg_docs/EventV0.md) +- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md) +- [VehicleConstraints](../msg_docs/VehicleConstraints.md) +- [IrlockReport](../msg_docs/IrlockReport.md) + ::: diff --git a/docs/en/modules/modules_driver.md b/docs/en/modules/modules_driver.md index 7801da4db3..2b0b2a6b7e 100644 --- a/docs/en/modules/modules_driver.md +++ b/docs/en/modules/modules_driver.md @@ -2,6 +2,7 @@ Subcategories: +- [Adc](modules_driver_adc.md) - [Airspeed Sensor](modules_driver_airspeed_sensor.md) - [Baro](modules_driver_baro.md) - [Camera](modules_driver_camera.md) @@ -46,66 +47,6 @@ MCP23009 [arguments...] status print status info ``` -## adc - -Source: [drivers/adc/board_adc](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/adc/board_adc) - -### Description - -ADC driver. - -### Usage {#adc_usage} - -``` -adc [arguments...] - Commands: - start - - test - [-n] Do not publish ADC report, only system power - - stop - - status print status info -``` - -## ads1115 - -Source: [drivers/adc/ads1115](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/adc/ads1115) - -### Description - -Driver to enable an external [ADS1115](https://www.adafruit.com/product/1085) ADC connected via I2C. - -The driver is included by default in firmware for boards that do not have an internal analog to digital converter, -such as [PilotPi](../flight_controller/raspberry_pi_pilotpi.md) or [CUAV Nora](../flight_controller/cuav_nora.md) -(search for `CONFIG_DRIVERS_ADC_ADS1115` in board configuration files). - -It is enabled/disabled using the -[ADC_ADS1115_EN](../advanced_config/parameter_reference.md#ADC_ADS1115_EN) -parameter, and is disabled by default. -If enabled, internal ADCs are not used. - -### Usage {#ads1115_usage} - -``` -ads1115 [arguments...] - Commands: - start - [-I] Internal I2C bus(es) - [-X] External I2C bus(es) - [-b ] board-specific bus (default=all) (external SPI: n-th bus - (default=1)) - [-f ] bus frequency in kHz - [-q] quiet startup (no message if no device found) - [-a ] I2C address - default: 72 - - stop - - status print status info -``` - ## atxxxx Source: [drivers/osd/atxxxx](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/osd/atxxxx) @@ -808,6 +749,30 @@ lsm303agr [arguments...] status print status info ``` +## mcp9808 + +Source: [drivers/temperature_sensor/mcp9808](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/temperature_sensor/mcp9808) + +### Usage {#mcp9808_usage} + +``` +mcp9808 [arguments...] + Commands: + start + [-I] Internal I2C bus(es) + [-X] External I2C bus(es) + [-b ] board-specific bus (default=all) (external SPI: n-th bus + (default=1)) + [-f ] bus frequency in kHz + [-q] quiet startup (no message if no device found) + [-a ] I2C address + default: 24 + + stop + + status print status info +``` + ## msp_osd Source: [drivers/osd/msp_osd](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/osd/msp_osd) diff --git a/docs/en/modules/modules_driver_adc.md b/docs/en/modules/modules_driver_adc.md new file mode 100644 index 0000000000..cecdbff037 --- /dev/null +++ b/docs/en/modules/modules_driver_adc.md @@ -0,0 +1,107 @@ +# Modules Reference: Adc (Driver) + +## TLA2528 + +Source: [drivers/adc/tla2528](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/adc/tla2528) + +### Usage {#TLA2528_usage} + +``` +TLA2528 [arguments...] + Commands: + start + [-I] Internal I2C bus(es) + [-X] External I2C bus(es) + [-b ] board-specific bus (default=all) (external SPI: n-th bus + (default=1)) + [-f ] bus frequency in kHz + [-q] quiet startup (no message if no device found) + + stop + + status print status info +``` + +## adc + +Source: [drivers/adc/board_adc](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/adc/board_adc) + +### Description + +ADC driver. + +### Usage {#adc_usage} + +``` +adc [arguments...] + Commands: + start + + test + [-n] Do not publish ADC report, only system power + + stop + + status print status info +``` + +## ads1115 + +Source: [drivers/adc/ads1115](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/adc/ads1115) + +### Description + +Driver to enable an external [ADS1115](https://www.adafruit.com/product/1085) ADC connected via I2C. + +The driver is included by default in firmware for boards that do not have an internal analog to digital converter, +such as [PilotPi](../flight_controller/raspberry_pi_pilotpi.md) or [CUAV Nora](../flight_controller/cuav_nora.md) +(search for `CONFIG_DRIVERS_ADC_ADS1115` in board configuration files). + +It is enabled/disabled using the +[ADC_ADS1115_EN](../advanced_config/parameter_reference.md#ADC_ADS1115_EN) +parameter, and is disabled by default. +If enabled, internal ADCs are not used. + +### Usage {#ads1115_usage} + +``` +ads1115 [arguments...] + Commands: + start + [-I] Internal I2C bus(es) + [-X] External I2C bus(es) + [-b ] board-specific bus (default=all) (external SPI: n-th bus + (default=1)) + [-f ] bus frequency in kHz + [-q] quiet startup (no message if no device found) + [-a ] I2C address + default: 72 + + stop + + status print status info +``` + +## ads7953 + +Source: [drivers/adc/ads7953](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/adc/ads7953) + +### Usage {#ads7953_usage} + +``` +ads7953 [arguments...] + Commands: + start + [-s] Internal SPI bus(es) + [-S] External SPI bus(es) + [-b ] board-specific bus (default=all) (external SPI: n-th bus + (default=1)) + [-c ] chip-select pin (for internal SPI) or index (for external SPI) + [-m ] SPI mode + [-f ] bus frequency in kHz + [-q] quiet startup (no message if no device found) + + stop + + status print status info +``` diff --git a/docs/en/modules/modules_driver_radio_control.md b/docs/en/modules/modules_driver_radio_control.md index 98489438e5..3cfb312593 100644 --- a/docs/en/modules/modules_driver_radio_control.md +++ b/docs/en/modules/modules_driver_radio_control.md @@ -4,10 +4,9 @@ Source: [drivers/rc/crsf_rc](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/rc/crsf_rc) - ### Description -This module parses the CRSF RC uplink protocol and generates CRSF downlink telemetry data +This module parses the CRSF RC uplink protocol and generates CRSF downlink telemetry data ### Usage {#crsf_rc_usage} @@ -17,6 +16,10 @@ crsf_rc [arguments...] start [-d ] RC device values: , default: /dev/ttyS3 + [-b ] RC baudrate + default: 420000 + + inject Inject frame data bytes (for testing) stop @@ -27,10 +30,9 @@ crsf_rc [arguments...] Source: [drivers/rc/dsm_rc](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/rc/dsm_rc) - ### Description -This module does Spektrum DSM RC input parsing. +This module does Spektrum DSM RC input parsing. ### Usage {#dsm_rc_usage} @@ -52,10 +54,9 @@ dsm_rc [arguments...] Source: [drivers/rc/ghst_rc](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/rc/ghst_rc) - ### Description -This module does Ghost (GHST) RC input parsing. +This module does Ghost (GHST) RC input parsing. ### Usage {#ghst_rc_usage} @@ -75,9 +76,10 @@ ghst_rc [arguments...] Source: [drivers/rc_input](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/rc_input) - ### Description + This module does the RC input parsing and auto-selecting the method. Supported methods are: + - PPM - SBUS - DSM @@ -85,7 +87,6 @@ This module does the RC input parsing and auto-selecting the method. Supported m - ST24 - TBS Crossfire (CRSF) - ### Usage {#rc_input_usage} ``` @@ -106,10 +107,9 @@ rc_input [arguments...] Source: [drivers/rc/sbus_rc](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/rc/sbus_rc) - ### Description -This module does SBUS RC input parsing. +This module does SBUS RC input parsing. ### Usage {#sbus_rc_usage} diff --git a/docs/en/msg_docs/AdcReport.md b/docs/en/msg_docs/AdcReport.md index 53ab9a2f07..50fde63ff5 100644 --- a/docs/en/msg_docs/AdcReport.md +++ b/docs/en/msg_docs/AdcReport.md @@ -1,15 +1,21 @@ # AdcReport (UORB message) +ADC raw data. +Communicates raw data from an analog-to-digital converter (ADC) to other modules, such as battery status. [source file](https://github.com/PX4/PX4-Autopilot/blob/main/msg/AdcReport.msg) ```c -uint64 timestamp # time since system start (microseconds) -uint32 device_id # unique device ID for the sensor that does not change between power cycles -int16[12] channel_id # ADC channel IDs, negative for non-existent, TODO: should be kept same as array index -int32[12] raw_data # ADC channel raw value, accept negative value, valid if channel ID is positive -uint32 resolution # ADC channel resolution -float32 v_ref # ADC channel voltage reference, use to calculate LSB voltage(lsb=scale/resolution) +# ADC raw data. +# +# Communicates raw data from an analog-to-digital converter (ADC) to other modules, such as battery status. + +uint64 timestamp # [us] Time since system start +uint32 device_id # [-] unique device ID for the sensor that does not change between power cycles +int16[16] channel_id # [-] ADC channel IDs, negative for non-existent, TODO: should be kept same as array index +int32[16] raw_data # [-] ADC channel raw value, accept negative value, valid if channel ID is positive +uint32 resolution # [-] ADC channel resolution +float32 v_ref # [V] ADC channel voltage reference, use to calculate LSB voltage(lsb=scale/resolution) ``` diff --git a/docs/en/msg_docs/EscReport.md b/docs/en/msg_docs/EscReport.md index 4a75bee418..277402ae69 100644 --- a/docs/en/msg_docs/EscReport.md +++ b/docs/en/msg_docs/EscReport.md @@ -1,7 +1,5 @@ # EscReport (UORB message) - - [source file](https://github.com/PX4/PX4-Autopilot/blob/main/msg/EscReport.msg) ```c @@ -18,6 +16,19 @@ 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 + uint16 failures # Bitmask to indicate the internal ESC faults int8 esc_power # Applied power 0-100 in % (negative values reserved) diff --git a/docs/en/msg_docs/InputRc.md b/docs/en/msg_docs/InputRc.md index 3f8bdb3da3..fbae6e0254 100644 --- a/docs/en/msg_docs/InputRc.md +++ b/docs/en/msg_docs/InputRc.md @@ -1,7 +1,5 @@ # InputRc (UORB message) - - [source file](https://github.com/PX4/PX4-Autopilot/blob/main/msg/InputRc.msg) ```c @@ -39,11 +37,13 @@ bool rc_lost # RC receiver connection status: True,if no frame has arrived in uint16 rc_lost_frame_count # Number of lost RC frames. Note: intended purpose: observe the radio link quality if RSSI is not available. This value must not be used to trigger any failsafe-alike functionality. uint16 rc_total_frame_count # Number of total RC frames. Note: intended purpose: observe the radio link quality if RSSI is not available. This value must not be used to trigger any failsafe-alike functionality. uint16 rc_ppm_frame_length # Length of a single PPM frame. Zero for non-PPM systems +uint16 rc_frame_rate # RC frame rate in msg/second. 0 = invalid uint8 input_source # Input source uint16[18] values # measured pulse widths for each of the supported channels int8 link_quality # link quality. Percentage 0-100%. -1 = invalid float32 rssi_dbm # Actual rssi in units of dBm. NaN = invalid +int8 link_snr # link signal to noise ratio in units of dB. -1 = invalid ``` diff --git a/docs/en/msg_docs/RoverVelocitySetpoint.md b/docs/en/msg_docs/RoverVelocitySetpoint.md deleted file mode 100644 index 65103082b8..0000000000 --- a/docs/en/msg_docs/RoverVelocitySetpoint.md +++ /dev/null @@ -1,15 +0,0 @@ -# RoverVelocitySetpoint (UORB message) - -Rover Velocity Setpoint - -[source file](https://github.com/PX4/PX4-Autopilot/blob/main/msg/RoverVelocitySetpoint.msg) - -```c -# Rover Velocity Setpoint - -uint64 timestamp # [us] Time since system start -float32 speed # [m/s] [@range -inf (Backwards), inf (Forwards)] Speed setpoint -float32 bearing # [rad] [@range -pi,pi] [@frame NED] [@invalid: NaN, speed is defined in body x direction] Bearing setpoint -float32 yaw # [rad] [@range -pi, pi] [@frame NED] [@invalid NaN, Defaults to vehicle yaw] Mecanum only: Yaw setpoint - -``` diff --git a/docs/en/msg_docs/RoverVelocityStatus.md b/docs/en/msg_docs/RoverVelocityStatus.md deleted file mode 100644 index dfd7756afa..0000000000 --- a/docs/en/msg_docs/RoverVelocityStatus.md +++ /dev/null @@ -1,18 +0,0 @@ -# RoverVelocityStatus (UORB message) - -Rover Velocity Status - -[source file](https://github.com/PX4/PX4-Autopilot/blob/main/msg/RoverVelocityStatus.msg) - -```c -# Rover Velocity Status - -uint64 timestamp # [us] Time since system start -float32 measured_speed_body_x # [m/s] [@range -inf (Backwards), inf (Forwards)] [@frame Body] Measured speed in body x direction -float32 adjusted_speed_body_x_setpoint # [m/s] [@range -inf (Backwards), inf (Forwards)] [@frame Body] Speed setpoint in body x direction that is being tracked (Applied slew rates) -float32 pid_throttle_body_x_integral # [] [@range -1, 1] Integral of the PID for the closed loop controller of the speed in body x direction -float32 measured_speed_body_y # [m/s] [@range -inf (Left), inf (Right)] [@frame Body] [@invalid NaN If not mecanum] Mecanum only: Measured speed in body y direction -float32 adjusted_speed_body_y_setpoint # [m/s] [@range -inf (Left), inf (Right)] [@frame Body] [@invalid NaN If not mecanum] Mecanum only: Speed setpoint in body y direction that is being tracked (Applied slew rates) -float32 pid_throttle_body_y_integral # [] [@range -1, 1] [@invalid NaN If not mecanum] Mecanum only: Integral of the PID for the closed loop controller of the speed in body y direction - -``` diff --git a/docs/en/msg_docs/SensorTemp.md b/docs/en/msg_docs/SensorTemp.md new file mode 100644 index 0000000000..5ed50541fe --- /dev/null +++ b/docs/en/msg_docs/SensorTemp.md @@ -0,0 +1,11 @@ +# SensorTemp (UORB message) + +[source file](https://github.com/PX4/PX4-Autopilot/blob/main/msg/SensorTemp.msg) + +```c +uint64 timestamp # time since system start (microseconds) + +uint32 device_id # unique device ID for the sensor that does not change between power cycles +float32 temperature # Temperature provided by sensor (Celsius) + +``` diff --git a/docs/en/msg_docs/VehicleCommand.md b/docs/en/msg_docs/VehicleCommand.md index 6c5e87ff5b..7f91701614 100644 --- a/docs/en/msg_docs/VehicleCommand.md +++ b/docs/en/msg_docs/VehicleCommand.md @@ -28,7 +28,7 @@ uint16 VEHICLE_CMD_DO_ORBIT = 34 # Start orbiting on the circumference of a circ uint16 VEHICLE_CMD_DO_FIGUREEIGHT = 35 # Start flying on the outline of a figure eight defined by the parameters. |[m] Major radius|[m] Minor radius|[m/s] Velocity|Orientation|Latitude/X|Longitude/Y|Altitude/Z| uint16 VEHICLE_CMD_NAV_ROI = 80 # Sets the region of interest (ROI) for a sensor set or the vehicle itself. This can then be used by the vehicles control system to control the vehicle attitude and the attitude of various sensors such as cameras. |[@enum VEHICLE_ROI] Region of interest mode.|MISSION index/ target ID.|ROI index (allows a vehicle to manage multiple ROI's)|Unused|x the location of the fixed ROI (see MAV_FRAME)|y|z| uint16 VEHICLE_CMD_NAV_PATHPLANNING = 81 # Control autonomous path planning on the MAV. |0: Disable local obstacle avoidance / local path planning (without resetting map), 1: Enable local path planning, 2: Enable and reset local path planning|0: Disable full path planning (without resetting map), 1: Enable, 2: Enable and reset map/occupancy grid, 3: Enable and reset planned route, but not occupancy grid|Unused|[deg] [@range 0, 360] Yaw angle at goal, in compass degrees|Latitude/X of goal|Longitude/Y of goal|Altitude/Z of goal| -uint16 VEHICLE_CMD_NAV_VTOL_TAKEOFF = 84 # Takeoff from ground / hand and transition to fixed wing. |Minimum pitch (if airspeed sensor present), desired pitch without sensor|Unused|Unused|Yaw angle (if magnetometer present), ignored without magnetometer|Latitude|Longitude|Altitude| +uint16 VEHICLE_CMD_NAV_VTOL_TAKEOFF = 84 # Takeoff from ground / hand and transition to fixed wing. |Minimum pitch (if airspeed sensor present), desired pitch without sensor|Transition heading, 0: Default, 3: Use specified transition heading|Unused|Yaw angle (if magnetometer present), ignored without magnetometer|Latitude|Longitude|Altitude| uint16 VEHICLE_CMD_NAV_VTOL_LAND = 85 # Transition to MC and land at location. |Unused|Unused|Unused|Desired yaw angle.|Latitude|Longitude|Altitude| uint16 VEHICLE_CMD_NAV_GUIDED_LIMITS = 90 # Set limits for external control. |[s] Timeout - maximum time that external controller will be allowed to control vehicle. 0 means no timeout|[m] Absolute altitude min AMSL - if vehicle moves below this alt, the command will be aborted and the mission will continue. 0 means no lower altitude limit|[m] Absolute altitude max - if vehicle moves above this alt, the command will be aborted and the mission will continue. 0 means no upper altitude limit|[m] Horizontal move limit (AMSL) - if vehicle moves more than this distance from it's location at the moment the command was executed, the command will be aborted and the mission will continue. 0 means no horizontal altitude limit|Unused|Unused|Unused| uint16 VEHICLE_CMD_NAV_GUIDED_MASTER = 91 # Set id of master controller. |System ID|Component ID|Unused|Unused|Unused|Unused|Unused| diff --git a/docs/en/msg_docs/index.md b/docs/en/msg_docs/index.md index a70fa245f5..1df0fa98f1 100644 --- a/docs/en/msg_docs/index.md +++ b/docs/en/msg_docs/index.md @@ -84,7 +84,7 @@ Graphs showing how these are used [can be found here](../middleware/uorb_graph.m - [ActuatorOutputs](ActuatorOutputs.md) - [ActuatorServosTrim](ActuatorServosTrim.md) — Servo trims, added as offset to servo outputs - [ActuatorTest](ActuatorTest.md) -- [AdcReport](AdcReport.md) +- [AdcReport](AdcReport.md) — ADC raw data. - [Airspeed](Airspeed.md) — Airspeed data from sensors - [AirspeedWind](AirspeedWind.md) — Wind estimate (from airspeed_selector) - [AutotuneAttitudeControlStatus](AutotuneAttitudeControlStatus.md) — Autotune attitude control status @@ -259,6 +259,7 @@ Graphs showing how these are used [can be found here](../middleware/uorb_graph.m The topic will not be updated when the vehicle is armed - [SensorSelection](SensorSelection.md) — Sensor ID's for the voted sensors output on the sensor_combined topic. Will be updated on startup of the sensor module and when sensor selection changes +- [SensorTemp](SensorTemp.md) - [SensorUwb](SensorUwb.md) — UWB distance contains the distance information measured by an ultra-wideband positioning system, such as Pozyx or NXP Rddrone. - [SensorsStatus](SensorsStatus.md) — Sensor check metrics. This will be zero for a sensor that's primary or unpopulated. From 526c64aab717bcb434019ce3b8757e453d0e14a1 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Wed, 26 Nov 2025 15:28:33 +1100 Subject: [PATCH 18/23] COM_ARM_WO_GPS clarifications (#25954) --- src/modules/commander/commander_params.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/modules/commander/commander_params.c b/src/modules/commander/commander_params.c index 2c53e36c66..e906a3e1f9 100644 --- a/src/modules/commander/commander_params.c +++ b/src/modules/commander/commander_params.c @@ -243,14 +243,16 @@ PARAM_DEFINE_FLOAT(COM_DISARM_LAND, 2.0f); PARAM_DEFINE_FLOAT(COM_DISARM_PRFLT, 10.0f); /** - * GPS preflight check + * Arming without GNSS configuration * - * Measures taken when a check defined by EKF2_GPS_CHECK is failing. + * Configures whether arming is allowed without GNSS, for modes that require a global position + * (specifically, in those modes when a check defined by EKF2_GPS_CHECK fails). + * The settings deny arming and warn, allow arming and warn, or silently allow arming. * * @group Commander * @value 0 Deny arming - * @value 1 Warning only - * @value 2 Disabled + * @value 1 Allow arming (with warning) + * @value 2 Allow arming (no warning) */ PARAM_DEFINE_INT32(COM_ARM_WO_GPS, 1); From 7bb12b15b5d15857b870bab3b28992a9edcb2817 Mon Sep 17 00:00:00 2001 From: mahima-yoga Date: Tue, 25 Nov 2025 12:06:38 +0100 Subject: [PATCH 19/23] fw_att_ctrl: zero initialize all member variables --- src/modules/fw_att_control/fw_pitch_controller.h | 10 +++++----- src/modules/fw_att_control/fw_roll_controller.h | 8 ++++---- src/modules/fw_att_control/fw_yaw_controller.h | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/modules/fw_att_control/fw_pitch_controller.h b/src/modules/fw_att_control/fw_pitch_controller.h index a71168f190..d8a40ab636 100644 --- a/src/modules/fw_att_control/fw_pitch_controller.h +++ b/src/modules/fw_att_control/fw_pitch_controller.h @@ -64,11 +64,11 @@ public: float get_body_rate_setpoint() { return _body_rate_setpoint; } private: - float _tc; - float _max_rate_pos; - float _max_rate_neg; - float _euler_rate_setpoint; - float _body_rate_setpoint; + float _tc{}; + float _max_rate_pos{}; + float _max_rate_neg{}; + float _euler_rate_setpoint{}; + float _body_rate_setpoint{}; }; #endif // FW_PITCH_CONTROLLER_H diff --git a/src/modules/fw_att_control/fw_roll_controller.h b/src/modules/fw_att_control/fw_roll_controller.h index a14277e3f0..5e47f0ffd0 100644 --- a/src/modules/fw_att_control/fw_roll_controller.h +++ b/src/modules/fw_att_control/fw_roll_controller.h @@ -63,10 +63,10 @@ public: float get_body_rate_setpoint() { return _body_rate_setpoint; } private: - float _tc; - float _max_rate; - float _euler_rate_setpoint; - float _body_rate_setpoint; + float _tc{}; + float _max_rate{}; + float _euler_rate_setpoint{}; + float _body_rate_setpoint{}; }; #endif // FW_ROLL_CONTROLLER_H diff --git a/src/modules/fw_att_control/fw_yaw_controller.h b/src/modules/fw_att_control/fw_yaw_controller.h index 7e97618a26..e6f9ff9795 100644 --- a/src/modules/fw_att_control/fw_yaw_controller.h +++ b/src/modules/fw_att_control/fw_yaw_controller.h @@ -71,9 +71,9 @@ public: float get_body_rate_setpoint() { return _body_rate_setpoint; } private: - float _max_rate; - float _euler_rate_setpoint; - float _body_rate_setpoint; + float _max_rate{}; + float _euler_rate_setpoint{}; + float _body_rate_setpoint{}; }; #endif // FW_YAW_CONTROLLER_H From a6d5c78d1034245a206de5e7a5666afa25648393 Mon Sep 17 00:00:00 2001 From: Balduin Date: Wed, 26 Nov 2025 09:14:06 +0100 Subject: [PATCH 20/23] Ignore max HAGL failsafe in front transition (#25982) * mission_block: readibility improvement * mission_block: ignore max hagl failsafe in front transition --- src/modules/navigator/mission_block.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/modules/navigator/mission_block.cpp b/src/modules/navigator/mission_block.cpp index 168debf23a..63a51042b1 100644 --- a/src/modules/navigator/mission_block.cpp +++ b/src/modules/navigator/mission_block.cpp @@ -1027,10 +1027,18 @@ void MissionBlock::updateFailsafeChecks() void MissionBlock::updateMaxHaglFailsafe() { const float target_alt = _navigator->get_position_setpoint_triplet()->current.alt; + const float max_alt = math::min(_navigator->get_local_position()->hagl_max_z, _navigator->get_local_position()->hagl_max_xy); + const float terrain_alt = _navigator->get_global_position()->terrain_alt; + const bool terrain_alt_valid = _navigator->get_global_position()->terrain_alt_valid; - if (_navigator->get_global_position()->terrain_alt_valid - && ((target_alt - _navigator->get_global_position()->terrain_alt) - > math::min(_navigator->get_local_position()->hagl_max_z, _navigator->get_local_position()->hagl_max_xy))) { + // If the HAGL failsafe is declared during front transition, we enter a + // FW hold at the current low altitude while not having finished the + // transition. This is dangerous and worse than possibly fusing neither + // optical flow nor airspeed for a couple seconds, so we bypass the + // failsafe here. + const bool in_transition_to_fw = _navigator->get_vstatus()->in_transition_to_fw; + + if (!in_transition_to_fw && terrain_alt_valid && (target_alt - terrain_alt) > max_alt) { // Handle case where the altitude setpoint is above the maximum HAGL (height above ground level) mavlink_log_info(_navigator->get_mavlink_log_pub(), "Target altitude higher than max HAGL\t"); events::send(events::ID("navigator_fail_max_hagl"), events::Log::Error, "Target altitude higher than max HAGL"); From 276cab8d3c14c22902ebe9d0d9ce081901c2165d Mon Sep 17 00:00:00 2001 From: Julian Oes Date: Sat, 22 Nov 2025 13:50:41 +1300 Subject: [PATCH 21/23] mavlink: don't silently ignore mavlink dev streams I don't think it makes sense to ignore required streams that easily. If we do use some streams that are only in the MAVLink development.xml dialect, then we will have to properly and explicitly ifdef them everywhere that we use them. Otherwise, this basically means that we will just swallow this warning on most (non mavlink-dev) platforms which can mask issues. --- src/modules/mavlink/mavlink_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/mavlink/mavlink_main.cpp b/src/modules/mavlink/mavlink_main.cpp index b81b1af9d5..c39579645b 100644 --- a/src/modules/mavlink/mavlink_main.cpp +++ b/src/modules/mavlink/mavlink_main.cpp @@ -1194,8 +1194,8 @@ Mavlink::configure_stream(const char *stream_name, const float rate) } // if we reach here, the stream list does not contain the stream. - // flash constrained target's don't include all streams, and some are only available for the development dialect -#if defined(CONSTRAINED_FLASH) || !defined(MAVLINK_DEVELOPMENT_H) + // flash constrained target's don't include all streams +#if defined(CONSTRAINED_FLASH) return PX4_OK; #else PX4_WARN("stream %s not found", stream_name); From a2299b02c81f72a0901fd904f8345f68367a9360 Mon Sep 17 00:00:00 2001 From: Michael Schaeuble Date: Mon, 24 Nov 2025 10:13:53 +0100 Subject: [PATCH 22/23] modes: make available modes user selectable with a registration option Some modes should only be run within the context of a mode executor and the user should not be able to select them in the GCS. With this change, the external component registration request can be used to set if a mode is selectable or not. --- .../msg/RegisterExtComponentReplyV0.msg | 15 ++++++ .../msg/RegisterExtComponentRequestV0.msg | 24 +++++++++ .../translations/all_translations.h | 2 + ...nslation_register_ext_component_reply_v1.h | 45 +++++++++++++++++ ...lation_register_ext_component_request_v1.h | 49 +++++++++++++++++++ msg/versioned/RegisterExtComponentReply.msg | 4 +- msg/versioned/RegisterExtComponentRequest.msg | 4 +- src/modules/commander/ModeManagement.cpp | 1 + .../mavlink/streams/AVAILABLE_MODES.hpp | 14 ++++++ 9 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 msg/px4_msgs_old/msg/RegisterExtComponentReplyV0.msg create mode 100644 msg/px4_msgs_old/msg/RegisterExtComponentRequestV0.msg create mode 100644 msg/translation_node/translations/translation_register_ext_component_reply_v1.h create mode 100644 msg/translation_node/translations/translation_register_ext_component_request_v1.h diff --git a/msg/px4_msgs_old/msg/RegisterExtComponentReplyV0.msg b/msg/px4_msgs_old/msg/RegisterExtComponentReplyV0.msg new file mode 100644 index 0000000000..4495bcdb90 --- /dev/null +++ b/msg/px4_msgs_old/msg/RegisterExtComponentReplyV0.msg @@ -0,0 +1,15 @@ +uint32 MESSAGE_VERSION = 0 + +uint64 timestamp # time since system start (microseconds) + +uint64 request_id # ID from the request +char[25] name # name from the request + +uint16 px4_ros2_api_version + +bool success +int8 arming_check_id # arming check registration ID (-1 if invalid) +int8 mode_id # assigned mode ID (-1 if invalid) +int8 mode_executor_id # assigned mode executor ID (-1 if invalid) + +uint8 ORB_QUEUE_LENGTH = 2 diff --git a/msg/px4_msgs_old/msg/RegisterExtComponentRequestV0.msg b/msg/px4_msgs_old/msg/RegisterExtComponentRequestV0.msg new file mode 100644 index 0000000000..b0798705ca --- /dev/null +++ b/msg/px4_msgs_old/msg/RegisterExtComponentRequestV0.msg @@ -0,0 +1,24 @@ +# Request to register an external component + +uint32 MESSAGE_VERSION = 0 + +uint64 timestamp # time since system start (microseconds) + +uint64 request_id # ID, set this to a random value +char[25] name # either the requested mode name, or component name + +uint16 LATEST_PX4_ROS2_API_VERSION = 1 # API version compatibility. Increase this on a breaking semantic change. Changes to any message field are detected separately and do not require an API version change. + +uint16 px4_ros2_api_version # Set to LATEST_PX4_ROS2_API_VERSION + +# Components to be registered +bool register_arming_check +bool register_mode # registering a mode also requires arming_check to be set +bool register_mode_executor # registering an executor also requires a mode to be registered (which is the owned mode by the executor) + +bool enable_replace_internal_mode # set to true if an internal mode should be replaced +uint8 replace_internal_mode # vehicle_status::NAVIGATION_STATE_* +bool activate_mode_immediately # switch to the registered mode (can only be set in combination with an executor) + + +uint8 ORB_QUEUE_LENGTH = 2 diff --git a/msg/translation_node/translations/all_translations.h b/msg/translation_node/translations/all_translations.h index 1322253715..e463911482 100644 --- a/msg/translation_node/translations/all_translations.h +++ b/msg/translation_node/translations/all_translations.h @@ -12,6 +12,8 @@ #include "translation_battery_status_v1.h" #include "translation_event_v1.h" #include "translation_home_position_v1.h" +#include "translation_register_ext_component_reply_v1.h" +#include "translation_register_ext_component_request_v1.h" #include "translation_vehicle_attitude_setpoint_v1.h" #include "translation_vehicle_status_v1.h" #include "translation_vehicle_local_position_v1.h" diff --git a/msg/translation_node/translations/translation_register_ext_component_reply_v1.h b/msg/translation_node/translations/translation_register_ext_component_reply_v1.h new file mode 100644 index 0000000000..7ff61d7d97 --- /dev/null +++ b/msg/translation_node/translations/translation_register_ext_component_reply_v1.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * Copyright (c) 2025 PX4 Development Team. + * SPDX-License-Identifier: BSD-3-Clause + ****************************************************************************/ +#pragma once + +// Translate RegisterExtComponentReply v0 <--> v1 +#include +#include + +class RegisterExtComponentReplyV1Translation { +public: + using MessageOlder = px4_msgs_old::msg::RegisterExtComponentReplyV0; + static_assert(MessageOlder::MESSAGE_VERSION == 0); + + using MessageNewer = px4_msgs::msg::RegisterExtComponentReply; + static_assert(MessageNewer::MESSAGE_VERSION == 1); + + static constexpr const char* kTopic = "fmu/out/register_ext_component_reply"; + + static void fromOlder(const MessageOlder &msg_older, MessageNewer &msg_newer) { + msg_newer.timestamp = msg_older.timestamp; + msg_newer.request_id = msg_older.request_id; + msg_newer.name = msg_older.name; + msg_newer.px4_ros2_api_version = msg_older.px4_ros2_api_version; + msg_newer.success = msg_older.success; + msg_newer.arming_check_id = msg_older.arming_check_id; + msg_newer.mode_id = msg_older.mode_id; + msg_newer.mode_executor_id = msg_older.mode_executor_id; + msg_newer.not_user_selectable = false; + } + + static void toOlder(const MessageNewer &msg_newer, MessageOlder &msg_older) { + msg_older.timestamp = msg_newer.timestamp; + msg_older.request_id = msg_newer.request_id; + msg_older.name = msg_newer.name; + msg_older.px4_ros2_api_version = msg_newer.px4_ros2_api_version; + msg_older.success = msg_newer.success; + msg_older.arming_check_id = msg_newer.arming_check_id; + msg_older.mode_id = msg_newer.mode_id; + msg_older.mode_executor_id = msg_newer.mode_executor_id; + } +}; + +REGISTER_TOPIC_TRANSLATION_DIRECT(RegisterExtComponentReplyV1Translation); diff --git a/msg/translation_node/translations/translation_register_ext_component_request_v1.h b/msg/translation_node/translations/translation_register_ext_component_request_v1.h new file mode 100644 index 0000000000..9f90b90784 --- /dev/null +++ b/msg/translation_node/translations/translation_register_ext_component_request_v1.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * Copyright (c) 2025 PX4 Development Team. + * SPDX-License-Identifier: BSD-3-Clause + ****************************************************************************/ +#pragma once + +// Translate RegisterExtComponentRequest v0 <--> v1 +#include +#include + +class RegisterExtComponentRequestV1Translation { +public: + using MessageOlder = px4_msgs_old::msg::RegisterExtComponentRequestV0; + static_assert(MessageOlder::MESSAGE_VERSION == 0); + + using MessageNewer = px4_msgs::msg::RegisterExtComponentRequest; + static_assert(MessageNewer::MESSAGE_VERSION == 1); + + static constexpr const char* kTopic = "fmu/in/register_ext_component_request"; + + static void fromOlder(const MessageOlder &msg_older, MessageNewer &msg_newer) { + msg_newer.timestamp = msg_older.timestamp; + msg_newer.request_id = msg_older.request_id; + msg_newer.name = msg_older.name; + msg_newer.px4_ros2_api_version = msg_older.px4_ros2_api_version; + msg_newer.register_arming_check = msg_older.register_arming_check; + msg_newer.register_mode = msg_older.register_mode; + msg_newer.register_mode_executor = msg_older.register_mode_executor; + msg_newer.enable_replace_internal_mode = msg_older.enable_replace_internal_mode; + msg_newer.replace_internal_mode = msg_older.replace_internal_mode; + msg_newer.activate_mode_immediately = msg_older.activate_mode_immediately; + msg_newer.not_user_selectable = false; + } + + static void toOlder(const MessageNewer &msg_newer, MessageOlder &msg_older) { + msg_older.timestamp = msg_newer.timestamp; + msg_older.request_id = msg_newer.request_id; + msg_older.name = msg_newer.name; + msg_older.px4_ros2_api_version = msg_newer.px4_ros2_api_version; + msg_older.register_arming_check = msg_newer.register_arming_check; + msg_older.register_mode = msg_newer.register_mode; + msg_older.register_mode_executor = msg_newer.register_mode_executor; + msg_older.enable_replace_internal_mode = msg_newer.enable_replace_internal_mode; + msg_older.replace_internal_mode = msg_newer.replace_internal_mode; + msg_older.activate_mode_immediately = msg_newer.activate_mode_immediately; + } +}; + +REGISTER_TOPIC_TRANSLATION_DIRECT(RegisterExtComponentRequestV1Translation); diff --git a/msg/versioned/RegisterExtComponentReply.msg b/msg/versioned/RegisterExtComponentReply.msg index 4495bcdb90..17ff6765c9 100644 --- a/msg/versioned/RegisterExtComponentReply.msg +++ b/msg/versioned/RegisterExtComponentReply.msg @@ -1,4 +1,4 @@ -uint32 MESSAGE_VERSION = 0 +uint32 MESSAGE_VERSION = 1 uint64 timestamp # time since system start (microseconds) @@ -12,4 +12,6 @@ int8 arming_check_id # arming check registration ID (-1 if invalid) int8 mode_id # assigned mode ID (-1 if invalid) int8 mode_executor_id # assigned mode executor ID (-1 if invalid) +bool not_user_selectable # mode cannot be selected by the user + uint8 ORB_QUEUE_LENGTH = 2 diff --git a/msg/versioned/RegisterExtComponentRequest.msg b/msg/versioned/RegisterExtComponentRequest.msg index b0798705ca..3b76aef15e 100644 --- a/msg/versioned/RegisterExtComponentRequest.msg +++ b/msg/versioned/RegisterExtComponentRequest.msg @@ -1,6 +1,6 @@ # Request to register an external component -uint32 MESSAGE_VERSION = 0 +uint32 MESSAGE_VERSION = 1 uint64 timestamp # time since system start (microseconds) @@ -19,6 +19,6 @@ bool register_mode_executor # registering an executor also requires a mod bool enable_replace_internal_mode # set to true if an internal mode should be replaced uint8 replace_internal_mode # vehicle_status::NAVIGATION_STATE_* bool activate_mode_immediately # switch to the registered mode (can only be set in combination with an executor) - +bool not_user_selectable # mode cannot be selected by the user uint8 ORB_QUEUE_LENGTH = 2 diff --git a/src/modules/commander/ModeManagement.cpp b/src/modules/commander/ModeManagement.cpp index b26bb99993..d5d800f8de 100644 --- a/src/modules/commander/ModeManagement.cpp +++ b/src/modules/commander/ModeManagement.cpp @@ -232,6 +232,7 @@ void ModeManagement::checkNewRegistrations(UpdateRequest &update_request) static_assert(sizeof(request.name) == sizeof(reply.name), "size mismatch"); memcpy(reply.name, request.name, sizeof(request.name)); reply.request_id = request.request_id; + reply.not_user_selectable = request.not_user_selectable; reply.px4_ros2_api_version = register_ext_component_request_s::LATEST_PX4_ROS2_API_VERSION; // validate diff --git a/src/modules/mavlink/streams/AVAILABLE_MODES.hpp b/src/modules/mavlink/streams/AVAILABLE_MODES.hpp index c0d7730188..27e5852129 100644 --- a/src/modules/mavlink/streams/AVAILABLE_MODES.hpp +++ b/src/modules/mavlink/streams/AVAILABLE_MODES.hpp @@ -38,6 +38,7 @@ #include #include #include +#include class MavlinkStreamAvailableModes : public MavlinkStream { @@ -71,6 +72,8 @@ private: char name[sizeof(register_ext_component_reply_s::name)] {}; }; ExternalModeName *_external_mode_names{nullptr}; + uint8_t _not_user_selectable_mask{0}; + static_assert(MAX_NUM_EXTERNAL_MODES <= (sizeof(_not_user_selectable_mask) * CHAR_BIT), "Mask too small"); uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)}; uORB::Subscription _register_ext_component_reply_sub{ORB_ID(register_ext_component_reply)}; @@ -116,6 +119,10 @@ private: } else if (_external_mode_names) { strncpy(available_modes.mode_name, _external_mode_names[external_mode_index].name, sizeof(available_modes.mode_name)); available_modes.mode_name[sizeof(available_modes.mode_name) - 1] = '\0'; + + if ((_not_user_selectable_mask & (1 << external_mode_index)) > 0) { + available_modes.properties |= MAV_MODE_PROPERTY_NOT_USER_SELECTABLE; + } } } else { // Internal @@ -205,6 +212,13 @@ private: if (_external_mode_names && mode_index < MAX_NUM_EXTERNAL_MODES) { memcpy(_external_mode_names[mode_index].name, reply.name, sizeof(ExternalModeName::name)); + + if (reply.not_user_selectable) { + _not_user_selectable_mask |= (1 << mode_index); + + } else { + _not_user_selectable_mask &= ~(1 << mode_index); + } } dynamic_update = true; From d97a8d7d3b9be0925fdf975c08733b6314c6af80 Mon Sep 17 00:00:00 2001 From: Michael Schaeuble Date: Mon, 24 Nov 2025 10:29:47 +0100 Subject: [PATCH 23/23] mode: control auto set home from an external mode The mode executor can run land mode which updates the home position to the landing location. This can be not the desirable behavior and the home position should stay at the original location. A flag is added to the configuration overrides to control if the home position is updated or not. --- msg/px4_msgs_old/msg/ConfigOverridesV0.msg | 21 ++++++++++ .../translations/all_translations.h | 1 + .../translation_config_overrides_v1.h | 41 +++++++++++++++++++ msg/versioned/ConfigOverrides.msg | 4 +- src/modules/commander/Commander.cpp | 7 ++-- src/modules/commander/ModeManagement.cpp | 4 ++ 6 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 msg/px4_msgs_old/msg/ConfigOverridesV0.msg create mode 100644 msg/translation_node/translations/translation_config_overrides_v1.h diff --git a/msg/px4_msgs_old/msg/ConfigOverridesV0.msg b/msg/px4_msgs_old/msg/ConfigOverridesV0.msg new file mode 100644 index 0000000000..b274adfbec --- /dev/null +++ b/msg/px4_msgs_old/msg/ConfigOverridesV0.msg @@ -0,0 +1,21 @@ +# Configurable overrides by (external) modes or mode executors + +uint32 MESSAGE_VERSION = 0 + +uint64 timestamp # time since system start (microseconds) + +bool disable_auto_disarm # Prevent the drone from automatically disarming after landing (if configured) + +bool defer_failsafes # Defer all failsafes that can be deferred (until the flag is cleared) +int16 defer_failsafes_timeout_s # Maximum time a failsafe can be deferred. 0 = system default, -1 = no timeout + + +int8 SOURCE_TYPE_MODE = 0 +int8 SOURCE_TYPE_MODE_EXECUTOR = 1 +int8 source_type + +uint8 source_id # ID depending on source_type + +uint8 ORB_QUEUE_LENGTH = 4 + +# TOPICS config_overrides config_overrides_request diff --git a/msg/translation_node/translations/all_translations.h b/msg/translation_node/translations/all_translations.h index e463911482..12a8763ec6 100644 --- a/msg/translation_node/translations/all_translations.h +++ b/msg/translation_node/translations/all_translations.h @@ -10,6 +10,7 @@ #include "translation_arming_check_reply_v1.h" #include "translation_arming_check_request_v1.h" #include "translation_battery_status_v1.h" +#include "translation_config_overrides_v1.h" #include "translation_event_v1.h" #include "translation_home_position_v1.h" #include "translation_register_ext_component_reply_v1.h" diff --git a/msg/translation_node/translations/translation_config_overrides_v1.h b/msg/translation_node/translations/translation_config_overrides_v1.h new file mode 100644 index 0000000000..1f7e813951 --- /dev/null +++ b/msg/translation_node/translations/translation_config_overrides_v1.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * Copyright (c) 2025 PX4 Development Team. + * SPDX-License-Identifier: BSD-3-Clause + ****************************************************************************/ +#pragma once + +// Translate ConfigOverrides v0 <--> v1 +#include +#include + +class ConfigOverridesV1Translation { +public: + using MessageOlder = px4_msgs_old::msg::ConfigOverridesV0; + static_assert(MessageOlder::MESSAGE_VERSION == 0); + + using MessageNewer = px4_msgs::msg::ConfigOverrides; + static_assert(MessageNewer::MESSAGE_VERSION == 1); + + static constexpr const char* kTopic = "fmu/in/config_overrides_request"; + + static void fromOlder(const MessageOlder &msg_older, MessageNewer &msg_newer) { + msg_newer.timestamp = msg_older.timestamp; + msg_newer.disable_auto_disarm = msg_older.disable_auto_disarm; + msg_newer.defer_failsafes = msg_older.defer_failsafes; + msg_newer.defer_failsafes_timeout_s = msg_older.defer_failsafes_timeout_s; + msg_newer.disable_auto_set_home = false; + msg_newer.source_type = msg_older.source_type; + msg_newer.source_id = msg_older.source_id; + } + + static void toOlder(const MessageNewer &msg_newer, MessageOlder &msg_older) { + msg_older.timestamp = msg_newer.timestamp; + msg_older.disable_auto_disarm = msg_newer.disable_auto_disarm; + msg_older.defer_failsafes = msg_newer.defer_failsafes; + msg_older.defer_failsafes_timeout_s = msg_newer.defer_failsafes_timeout_s; + msg_older.source_type = msg_newer.source_type; + msg_older.source_id = msg_newer.source_id; + } +}; + +REGISTER_TOPIC_TRANSLATION_DIRECT(ConfigOverridesV1Translation); diff --git a/msg/versioned/ConfigOverrides.msg b/msg/versioned/ConfigOverrides.msg index b274adfbec..51fd86b037 100644 --- a/msg/versioned/ConfigOverrides.msg +++ b/msg/versioned/ConfigOverrides.msg @@ -1,6 +1,6 @@ # Configurable overrides by (external) modes or mode executors -uint32 MESSAGE_VERSION = 0 +uint32 MESSAGE_VERSION = 1 uint64 timestamp # time since system start (microseconds) @@ -8,7 +8,7 @@ bool disable_auto_disarm # Prevent the drone from automatically disarmin bool defer_failsafes # Defer all failsafes that can be deferred (until the flag is cleared) int16 defer_failsafes_timeout_s # Maximum time a failsafe can be deferred. 0 = system default, -1 = no timeout - +bool disable_auto_set_home # Prevent the drone from automatically setting the home position on arm or takeoff int8 SOURCE_TYPE_MODE = 0 int8 SOURCE_TYPE_MODE_EXECUTOR = 1 diff --git a/src/modules/commander/Commander.cpp b/src/modules/commander/Commander.cpp index 4f6bfa0faf..3923eb379f 100644 --- a/src/modules/commander/Commander.cpp +++ b/src/modules/commander/Commander.cpp @@ -638,7 +638,7 @@ transition_result_t Commander::arm(arm_disarm_reason_t calling_reason, bool run_ events::send(events::ID("commander_armed_by"), events::Log::Info, "Armed by {1}", calling_reason); - if (_param_com_home_en.get() && !_mission_in_progress) { + if (_param_com_home_en.get() && !_mission_in_progress && !_config_overrides.disable_auto_set_home) { _home_position.setHomePosition(); } @@ -1850,7 +1850,8 @@ void Commander::run() _mission_in_progress = (_vehicle_status.nav_state == vehicle_status_s::NAVIGATION_STATE_AUTO_MISSION) && !_mission_result_sub.get().finished; - _home_position.update(_param_com_home_en.get(), !isArmed() && _vehicle_land_detected.landed && !_mission_in_progress); + _home_position.update(_param_com_home_en.get(), !isArmed() && _vehicle_land_detected.landed && !_mission_in_progress + && !_config_overrides.disable_auto_set_home); handleAutoDisarm(); @@ -2140,7 +2141,7 @@ void Commander::landDetectorUpdate() } // automatically set or update home position - if (_param_com_home_en.get() && !_mission_in_progress) { + if (_param_com_home_en.get() && !_mission_in_progress && !_config_overrides.disable_auto_set_home) { // set the home position when taking off if (!_vehicle_land_detected.landed) { if (was_landed) { diff --git a/src/modules/commander/ModeManagement.cpp b/src/modules/commander/ModeManagement.cpp index d5d800f8de..ae2dee41ff 100644 --- a/src/modules/commander/ModeManagement.cpp +++ b/src/modules/commander/ModeManagement.cpp @@ -563,6 +563,10 @@ void ModeManagement::updateActiveConfigOverrides(uint8_t nav_state, config_overr current_overrides.disable_auto_disarm = true; } + if (executor_overrides.disable_auto_set_home) { + current_overrides.disable_auto_set_home = true; + } + if (executor_overrides.defer_failsafes) { current_overrides.defer_failsafes = true; current_overrides.defer_failsafes_timeout_s = executor_overrides.defer_failsafes_timeout_s;