diff --git a/docs/uk/SUMMARY.md b/docs/uk/SUMMARY.md index e84b2ff989..a7af3f7979 100644 --- a/docs/uk/SUMMARY.md +++ b/docs/uk/SUMMARY.md @@ -432,6 +432,7 @@ - [Стандартна конфігурація](config/index.md) - [OEM Configuration](advanced_config/oem.md) + - [Bootloader Secure Boot](advanced_config/bootloader_secure_boot.md) - [Розширені налаштування](advanced_config/index.md) - [Using PX4's Navigation Filter (EKF2)](advanced_config/tuning_the_ecl_ekf.md) @@ -541,8 +542,10 @@ - [AirspeedValidated](msg_docs/AirspeedValidated.md) - [ArmingCheckReply](msg_docs/ArmingCheckReply.md) - [ArmingCheckRequest](msg_docs/ArmingCheckRequest.md) + - [AuxGlobalPosition](msg_docs/AuxGlobalPosition.md) - [BatteryStatus](msg_docs/BatteryStatus.md) - [ConfigOverrides](msg_docs/ConfigOverrides.md) + - [Event](msg_docs/Event.md) - [FixedWingLateralSetpoint](msg_docs/FixedWingLateralSetpoint.md) - [FixedWingLongitudinalSetpoint](msg_docs/FixedWingLongitudinalSetpoint.md) - [GotoSetpoint](msg_docs/GotoSetpoint.md) @@ -570,6 +573,26 @@ - [VehicleRatesSetpoint](msg_docs/VehicleRatesSetpoint.md) - [VehicleStatus](msg_docs/VehicleStatus.md) - [VtolVehicleStatus](msg_docs/VtolVehicleStatus.md) + - [Wind](msg_docs/Wind.md) + - [Historic (old) Versions](msg_docs/versioned_old_messages.md) + - [AirspeedValidatedV0](msg_docs/AirspeedValidatedV0.md) + - [ArmingCheckReplyV0](msg_docs/ArmingCheckReplyV0.md) + - [ArmingCheckRequestV0](msg_docs/ArmingCheckRequestV0.md) + - [BatteryStatusV0](msg_docs/BatteryStatusV0.md) + - [ConfigOverridesV0](msg_docs/ConfigOverridesV0.md) + - [EventV0](msg_docs/EventV0.md) + - [HomePositionV0](msg_docs/HomePositionV0.md) + - [RegisterExtComponentReplyV0](msg_docs/RegisterExtComponentReplyV0.md) + - [RegisterExtComponentRequestV0](msg_docs/RegisterExtComponentRequestV0.md) + - [RegisterExtComponentRequestV1](msg_docs/RegisterExtComponentRequestV1.md) + - [VehicleAttitudeSetpointV0](msg_docs/VehicleAttitudeSetpointV0.md) + - [VehicleCommandAckV0](msg_docs/VehicleCommandAckV0.md) + - [VehicleGlobalPositionV0](msg_docs/VehicleGlobalPositionV0.md) + - [VehicleLocalPositionV0](msg_docs/VehicleLocalPositionV0.md) + - [VehicleStatusV0](msg_docs/VehicleStatusV0.md) + - [VehicleStatusV1](msg_docs/VehicleStatusV1.md) + - [VehicleStatusV2](msg_docs/VehicleStatusV2.md) + - [VehicleStatusV3](msg_docs/VehicleStatusV3.md) - [Unversioned Messages](msg_docs/unversioned_messages.md) - [ActionRequest](msg_docs/ActionRequest.md) - [ActuatorArmed](msg_docs/ActuatorArmed.md) @@ -581,7 +604,6 @@ - [Airspeed](msg_docs/Airspeed.md) - [AirspeedWind](msg_docs/AirspeedWind.md) - [AutotuneAttitudeControlStatus](msg_docs/AutotuneAttitudeControlStatus.md) - - [AuxGlobalPosition](msg_docs/AuxGlobalPosition.md) - [BatteryInfo](msg_docs/BatteryInfo.md) - [ButtonEvent](msg_docs/ButtonEvent.md) - [CameraCapture](msg_docs/CameraCapture.md) @@ -622,9 +644,10 @@ - [EstimatorStates](msg_docs/EstimatorStates.md) - [EstimatorStatus](msg_docs/EstimatorStatus.md) - [EstimatorStatusFlags](msg_docs/EstimatorStatusFlags.md) - - [Event](msg_docs/Event.md) - [FailsafeFlags](msg_docs/FailsafeFlags.md) - [FailureDetectorStatus](msg_docs/FailureDetectorStatus.md) + - [FiducialMarkerPosReport](msg_docs/FiducialMarkerPosReport.md) + - [FiducialMarkerYawReport](msg_docs/FiducialMarkerYawReport.md) - [FigureEightStatus](msg_docs/FigureEightStatus.md) - [FixedWingLateralGuidanceStatus](msg_docs/FixedWingLateralGuidanceStatus.md) - [FixedWingLateralStatus](msg_docs/FixedWingLateralStatus.md) @@ -707,6 +730,7 @@ - [PowerButtonState](msg_docs/PowerButtonState.md) - [PowerMonitor](msg_docs/PowerMonitor.md) - [PpsCapture](msg_docs/PpsCapture.md) + - [PrecLandStatus](msg_docs/PrecLandStatus.md) - [PurePursuitStatus](msg_docs/PurePursuitStatus.md) - [PwmInput](msg_docs/PwmInput.md) - [Px4ioStatus](msg_docs/Px4ioStatus.md) @@ -753,6 +777,7 @@ - [SensorsStatusImu](msg_docs/SensorsStatusImu.md) - [SystemPower](msg_docs/SystemPower.md) - [TakeoffStatus](msg_docs/TakeoffStatus.md) + - [TargetGnss](msg_docs/TargetGnss.md) - [TaskStackInfo](msg_docs/TaskStackInfo.md) - [TecsStatus](msg_docs/TecsStatus.md) - [TelemetryStatus](msg_docs/TelemetryStatus.md) @@ -779,28 +804,15 @@ - [VehicleThrustSetpoint](msg_docs/VehicleThrustSetpoint.md) - [VehicleTorqueSetpoint](msg_docs/VehicleTorqueSetpoint.md) - [VelocityLimits](msg_docs/VelocityLimits.md) + - [VteAidSource1d](msg_docs/VteAidSource1d.md) + - [VteAidSource3d](msg_docs/VteAidSource3d.md) + - [VteBiasInitStatus](msg_docs/VteBiasInitStatus.md) + - [VteInput](msg_docs/VteInput.md) + - [VteOrientation](msg_docs/VteOrientation.md) + - [VtePosition](msg_docs/VtePosition.md) - [Vtx](msg_docs/Vtx.md) - [WheelEncoders](msg_docs/WheelEncoders.md) - - [Wind](msg_docs/Wind.md) - [YawEstimatorStatus](msg_docs/YawEstimatorStatus.md) - - [AirspeedValidatedV0](msg_docs/AirspeedValidatedV0.md) - - [ArmingCheckReplyV0](msg_docs/ArmingCheckReplyV0.md) - - [ArmingCheckRequestV0](msg_docs/ArmingCheckRequestV0.md) - - [BatteryStatusV0](msg_docs/BatteryStatusV0.md) - - [ConfigOverridesV0](msg_docs/ConfigOverridesV0.md) - - [EventV0](msg_docs/EventV0.md) - - [HomePositionV0](msg_docs/HomePositionV0.md) - - [RegisterExtComponentReplyV0](msg_docs/RegisterExtComponentReplyV0.md) - - [RegisterExtComponentRequestV0](msg_docs/RegisterExtComponentRequestV0.md) - - [RegisterExtComponentRequestV1](msg_docs/RegisterExtComponentRequestV1.md) - - [VehicleAttitudeSetpointV0](msg_docs/VehicleAttitudeSetpointV0.md) - - [VehicleCommandAckV0](msg_docs/VehicleCommandAckV0.md) - - [VehicleGlobalPositionV0](msg_docs/VehicleGlobalPositionV0.md) - - [VehicleLocalPositionV0](msg_docs/VehicleLocalPositionV0.md) - - [VehicleStatusV0](msg_docs/VehicleStatusV0.md) - - [VehicleStatusV1](msg_docs/VehicleStatusV1.md) - - [VehicleStatusV2](msg_docs/VehicleStatusV2.md) - - [VehicleStatusV3](msg_docs/VehicleStatusV3.md) - [MAVLink Messaging](mavlink/index.md) - [Adding Messages](mavlink/adding_messages.md) - [Streaming Messages](mavlink/streaming_messages.md) @@ -961,8 +973,9 @@ - [Релізи](releases/index.md) - [Release Process](releases/release_process.md) - [main (alpha)](releases/main.md) - - [1.17 (alpha)](releases/1.17.md) - - [1.16 (stable)](releases/1.16.md) + - [v1.18 (alpha)](releases/1.18.md) + - [1.17 (stable)](releases/1.17.md) + - [1.16](releases/1.16.md) - [1.15](releases/1.15.md) - [1.14](releases/1.14.md) - [1.13](releases/1.13.md) diff --git a/docs/uk/advanced_config/bootloader_secure_boot.md b/docs/uk/advanced_config/bootloader_secure_boot.md new file mode 100644 index 0000000000..aba76feaa1 --- /dev/null +++ b/docs/uk/advanced_config/bootloader_secure_boot.md @@ -0,0 +1,140 @@ +# Bootloader Secure Boot + +Secure boot is a feature that ensures that only cryptographically authorized PX4 firmware is executed. +This is used by OEMs to ensure that only their validated, tested firmware runs on the vehicle — protecting safety, brand integrity, and regulatory compliance, and stopping others from running unauthorized software on their hardware. + +The _PX4 Bootloader_ can verify a cryptographic signature over the PX4 firmware before it is run. +When enabled, only a firmware image signed with a private key whose matching public key is baked into the bootloader will boot. +For any unsigned image, tampered image, or image signed by the wrong key, the device will wait in the bootloader screen (where it can be recovered safely over USB), and will not start the rest of the PX4 flight stack. + +:::warning +This feature is intended for OEMs. + +If you flash a bootloader that trusts a public key whose private counterpart you have lost, you can no longer sign new firmware for that device and will need a debug probe to recover it. +Keep private keys backed up and never commit them to source control. +::: + +## How It Works + +PX4's secure boot uses [ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) signatures (via [monocypher](https://monocypher.org)). +The signing key is 32 bytes and the resulting signature is 64 bytes. +Verification is fast (no random number generator is required on the device), and the implementation is small enough to fit in a 128 KB bootloader sector alongside the rest of the bootloader. + +A signed firmware image lays out in flash like this: + +```txt ++---------------------------+ APP_LOAD_ADDRESS ─┐ +| Vector table | │ ++---------------------------+ APP_LOAD_ADDRESS │ +| Image TOC | + BOARD_IMAGE_TOC_OFFSET │ BOOT region ++---------------------------+ │ (hashed and signed) +| .text / .rodata / .data | │ ++---------------------------+ &_boot_signature ─┤ +| 64-byte ed25519 signature | │ SIG1 ++---------------------------+ ─┘ +``` + +The **Table of Contents (TOC)** is a small data structure compiled into the firmware that tells the bootloader which region to hash and which key slot to verify against. +Its format is defined in [`src/include/image_toc.h`](https://github.com/PX4/PX4-Autopilot/blob/main/src/include/image_toc.h). +For px4_fmu-v6x the TOC declares two entries: **BOOT** (the firmware bytes to verify) and **SIG1** (the 64-byte ed25519 signature to verify them against). + +On reset the bootloader reads the TOC at a fixed offset, computes an ed25519 signature over the BOOT region, and compares it to the SIG1 entry. +If the signature verifies it jumps to the app; otherwise it stays in the bootloader and waits for a new upload. + +The host-side uploader (`Tools/px4_uploader.py`) also asks the bootloader to verify the signature before sending the final reboot, via a dedicated `VERIFY_SIG` opcode. +This means a signature mismatch is reported as a clean error from `px_uploader.py` instead of a silent "device stays in bootloader after reboot". + +## Trying It Out + +PX4 ships a secure-boot example for **px4_fmu-v6x**. +This consists of two build variants: + +- `px4_fmu-v6x_bootloader_secureboot` — the secure bootloader, with ed25519 verification enabled, and the upstream _test public key_ baked in. +- `px4_fmu-v6x_secureboot` — PX4 firmware, with TOC and automatic signing. + +Кроки наступні: + +1. Build and flash the secure bootloader (one-time, via SWD) + - Build the bootloader: + + ```sh + make px4_fmu-v6x_bootloader_secureboot + ``` + + - Flash the resulting `build/px4_fmu-v6x_bootloader_secureboot/px4_fmu-v6x_bootloader_secureboot.elf` via a debug probe. + See [Bootloader Update](../advanced_config/bootloader_update). + + ::: tip + This is the only step that needs SWD — once the secure bootloader is in place, all firmware updates go over USB. + +::: + +2. Build and upload signed firmware + + ```sh + make px4_fmu-v6x_secureboot upload + ``` + + The build produces an unsigned `.bin`, signs it with the upstream test key (`Tools/test_keys/test_keys.json`), wraps it in a `.px4` envelope marked `image_signed: true`, and uploads it. + You will see something like: + + ```sh + Verify ▕██████████████████████████████▏ 100% + Verifying image signature... passed + Uploaded in 18s + ``` + +If you upload an image that the bootloader can't verify (e.g. an unsigned `.px4`, a tampered `.bin`, or one signed with a different key), `px_uploader.py` reports the failure before reboot: + +```sh +Upload failed: Signature verification failed: image will not boot. +The bootloader computed a signature over the flashed image that does not +match any public key it trusts. +``` + +## Generating Your Own Keys + +The default test key is committed to the PX4 tree, so a real deployment must replace it (in order to protect the public key). +Generate a new ed25519 key pair with: + +```shell +python3 Tools/secure_bootloader/generate_signing_keys.py /path/to/my_key +``` + +This writes: + +- `my_key.json` — the private key used by `sign_firmware.py`. **Keep this private. Do not commit it.** +- `my_key.pub` — the public key as a C-array fragment, suitable for `#include` in the bootloader's keystore. + +Make the following changes use your new keys in the build: + +1. **Update the bootloader to trust your public key.** + + Edit `boards/px4/fmu-v6x/bootloader_secureboot.px4board` and change `CONFIG_PUBLIC_KEY0` to point at `my_key.pub`. Rebuild and reflash the bootloader via SWD. + +2. **Tell the app build to sign with the matching private key.** + + Either edit `boards/px4/fmu-v6x/secureboot.px4board` and change `CONFIG_BOARD_SECUREBOOT_KEY` to point at `my_key.json`, or set the environment variable at build time: + + ```sh + BOARD_SECUREBOOT_KEY=/path/to/my_key.json make px4_fmu-v6x_secureboot upload + ``` + +The keys used must always be the corresponding cryptographic pair — if you flash a bootloader that trusts a key whose private half you don't have, you can only recover via SWD. + +## Enabling Secure Boot on a New Board + +To enable secure boot up on a board that doesn't already have a `secureboot` variant, you'll need: + +- a `toc.c` file placed in the board's `src/` (modeled on `boards/px4/fmu-v6x/src/toc.c`), +- a linker script with `_main_toc` reserved at a fixed offset past the vector table and a `.signature` section at the end of FLASH (see `boards/px4/fmu-v6x/nuttx-config/scripts/secureboot-script.ld`) +- a `secureboot.px4board` setting `CONFIG_BOARD_SECUREBOOT=y` and the linker prefix, +- a `bootloader_secureboot.px4board` enabling `CONFIG_BOARD_CRYPTO`, `CONFIG_DRIVERS_SW_CRYPTO`, `CONFIG_DRIVERS_STUB_KEYSTORE` and the public-key path, +- `BOOTLOADER_USE_SECURITY` + `BOOTLOADER_SIGNING_ALGORITHM` + `BOARD_IMAGE_TOC_OFFSET` defines in the board's `hw_config.h`, gated on `PX4_CRYPTO`. + +The fmu-v6x variant files are kept small and self-contained for exactly this reason — they are intended to be copied as a starting point. + +## Дивіться також + +- [Оновлення бутлоадера](../advanced_config/bootloader_update.md) +- [OEM/Factory Configuration](../advanced_config/oem.md) diff --git a/docs/uk/advanced_config/bootloader_update.md b/docs/uk/advanced_config/bootloader_update.md index 3557956d15..378ebdde90 100644 --- a/docs/uk/advanced_config/bootloader_update.md +++ b/docs/uk/advanced_config/bootloader_update.md @@ -2,7 +2,7 @@ _PX4 Bootloader_ використовується для завантаження прошивки для [Pixhawk boards](../flight_controller/pixhawk_series.md) (PX4FMU, PX4IO). -Зазвичай контролери Pixhawk поставляються з попередньо встановленою відповідною версією завантажувача. +Pixhawk controllers usually come with an appropriate bootloader version pre-installed. Однак у деяких випадках його може бути відсутній, або може бути присутня старіша версія, яку потрібно оновити, або плата може бути відключена і потребує стирання та перевстановлення завантажувача. Ця тема пояснює, як побудувати завантажувач PX4 та кілька методів для його прошивки на плату. @@ -38,7 +38,7 @@ You can enable this key in your own custom firmware if needed. 2. [Оновіть прошивку](../config/firmware.md#custom) з образом, що містить новий/потрібний завантажувач. ::: info - The updated bootloader might be included the default firmware for your board or supplied in custom firmware. + The updated bootloader might be included in the default firmware for your board or supplied in custom firmware. ::: @@ -51,7 +51,7 @@ You can enable this key in your own custom firmware if needed. Зазвичай на цьому етапі ви можливо захочете [оновити прошивку](../config/firmware.md) ще раз, використовуючи правильно/ново встановлений загрузчик. -An specific example of this process for updating the [FMUv2 bootloader](#fmuv2-bootloader-update) is given below. +A specific example of this process for updating the [FMUv2 bootloader](#fmuv2-bootloader-update) is given below. ## Створення завантажувача PX4 @@ -89,7 +89,7 @@ PX4 boards up to FMUv5X (before STM32H7) used the [PX4 bootloader](https://githu 1. Отримайте бінарний файл, який містить завантажувальник (або від команди розробників, або [зіберіть його самостійно](#building-the-px4-bootloader)). 2. Get a [Debug Probe](../debug/swd_debug.md#debug-probes-for-px4-hardware). - Підключіть зонд до комп'ютера за допомогою USB та налаштуйте `gdbserver`. + Connect the probe to your PC via USB and setup the `gdbserver`. 3. Перейдіть до каталогу, що містить бінарний файл, і запустіть команду для обраного вами завантажувача в терміналі: @@ -151,7 +151,7 @@ PX4 boards up to FMUv5X (before STM32H7) used the [PX4 bootloader](https://githu ::: -8. Використовуйте таку команду, щоб знайти SWD Pixhawk і підключитися до нього: +8. Use the following command to scan for the Pixhawk's SWD and connect to it: ```sh (gdb) mon swdp_scan @@ -211,4 +211,5 @@ This example explains how you can use [QGC Bootloader Update](#qgc-bootloader-up ## Дивіться також +- [Bootloader Secure Boot](../advanced_config/bootloader_secure_boot.md) - [OEM/Factory Configuration](../advanced_config/oem.md) diff --git a/docs/uk/advanced_config/oem.md b/docs/uk/advanced_config/oem.md index d5b2cba842..dbc5423b8c 100644 --- a/docs/uk/advanced_config/oem.md +++ b/docs/uk/advanced_config/oem.md @@ -1,6 +1,6 @@ # OEM/Factory Configuration -This topic lists configuration and calibration topics that are more relevant to manufacturers/OEMs (though is some cases individual developers may find some relevant). +This topic lists configuration and calibration topics that are more relevant to manufacturers/OEMs (though in some cases individual developers may find some relevant). - [IMU Factory Calibration](../advanced_config/imu_factory_calibration.md) - [Sensor Thermal Compensation](../advanced_config/sensor_thermal_calibration.md) @@ -8,6 +8,7 @@ This topic lists configuration and calibration topics that are more relevant to - [Розширена орієнтація контролера](../advanced_config/advanced_flight_controller_orientation_leveling.md) - [Static Pressure Buildup](../advanced_config/static_pressure_buildup.md) - [Оновлення бутлоадера](../advanced_config/bootloader_update.md) +- [Bootloader Secure Boot](../advanced_config/bootloader_secure_boot.md) ## Дивіться також diff --git a/docs/uk/advanced_features/vision_target_estimator.md b/docs/uk/advanced_features/vision_target_estimator.md index afabe61142..126ee6446a 100644 --- a/docs/uk/advanced_features/vision_target_estimator.md +++ b/docs/uk/advanced_features/vision_target_estimator.md @@ -1,16 +1,16 @@ -# Vision Target Estimator (VTEST) +# Vision Target Estimator (VTE) -The Vision Target Estimator (VTEST) estimates where a target is, relative to the vehicle, by combining a camera-based detection of the target (for example an ArUco fiducial marker) with one or more absolute position references: the vehicle's own GNSS, the mission landing waypoint, and/or a GNSS receiver mounted on the target itself. +The Vision Target Estimator (VTE) estimates where a target is, relative to the vehicle, by combining a camera-based detection of the target (for example an ArUco fiducial marker) with one or more absolute position references: the vehicle's own GNSS, the mission landing waypoint, and/or a GNSS receiver mounted on the target itself. Its main use is [precision landing](../advanced_features/precland.md), where the vehicle needs to touch down on a small, well-defined spot rather than the approximate mission waypoint. -This page is for developers who want to enable VTEST on a custom build, tune it for their vehicle, or integrate a new vision pipeline that publishes landing-target observations. +This page is for developers who want to enable VTE on a custom build, tune it for their vehicle, or integrate a new vision pipeline that publishes landing-target observations. It assumes familiarity with PX4 and basic state estimation, but does not require prior knowledge of the module itself. For more depth see the [Vision Target Estimator deep dive](../advanced_features/vision_target_estimator_advanced.md). :::warning -VTEST is a beta feature, disabled in default board configurations, and should only be enabled on custom builds after careful bench and flight testing. +VTE is a beta feature, disabled in default board configurations, and should only be enabled on custom builds after careful bench and flight testing. ::: ## Table of Contents @@ -24,10 +24,10 @@ The estimator is not part of the default PX4 board configurations. To enable a build that includes the module you need to modify the [KConfig board configuration](../hardware/porting_guide_config.md) for your target board (or create a custom `.px4board` file). The keys and values that need to be present are: -- `CONFIG_MODULES_VISION_TARGET_ESTIMATOR=y`: _Enable_ VTEST in firmware +- `CONFIG_MODULES_VISION_TARGET_ESTIMATOR=y`: _Enable_ VTE in firmware - `CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=n`: _Disable_ the landing target estimator (both modules publish [`landing_target_pose`](../msg_docs/LandingTargetPose.md) and will conflict if enabled together). - `CONFIG_MAVLINK_DIALECT="development"`: Enable using the development dialect. - Note that this step will no longer be required once the MAVLink messages used by VTEST have been validated. + Note that this step will no longer be required once the MAVLink messages used by VTE have been validated. Two prebuilt targets are available: @@ -36,40 +36,146 @@ Two prebuilt targets are available: For the experimental moving-target build, see [Moving-target mode](../advanced_features/vision_target_estimator_advanced.md#moving-target-mode-experimental). +## Estimator Overview + +This section describes how the filter works internally. +It is recommended background reading to understand the underlying mechanics, though it is not strictly required to set up or operate the feature. + +### Architecture and Core Loop + +The Vision Target Estimator runs two independent estimators at a fixed 50 Hz: + +- **Position filter:** Tracks where the target is relative to the vehicle. + It is structured as three decoupled 1D Kalman filters (one per NED axis). +- **Orientation filter:** Tracks the target yaw on its own state. + +Each filter alternates between two operations: + + + +- **Prediction step:** Propagates the state forward using the vehicle motion model. + +::: details +Click to view the mathematical model + + The per-axis position state is $x = [ r, v^{uav}, b ]^T$: the relative NED displacement (target minus vehicle), the vehicle velocity, and the offset between the absolute target reference (GNSS or mission waypoint) and the vision-derived target position. + Assuming constant NED acceleration input $a^{uav}$ over the integration interval $dt$: + + $$ + \begin{aligned} + r_{k+1} &= r_k - dt\thinspace v^{uav}_k - \tfrac{1}{2}\thinspace dt^2\thinspace a^{uav} \\ + v^{uav}_{k+1} &= v^{uav}_k + dt\thinspace a^{uav} \\ + b_{k+1} &= b_k + \end{aligned} + $$ + + Once the bias is known, GNSS can keep the estimate centred on the target even if vision drops out. + + The yaw filter tracks $x = [ \psi, \dot{\psi} ]^T$ with a constant-rate prediction (yaw wrapped to $[-\pi, \pi]$): + + $$ + \begin{aligned} + \psi_{k+1} &= \text{wrap}\negthinspace\left(\psi_k + dt\thinspace\dot{\psi}_k\right) \\ + \dot{\psi}_{k+1} &= \dot{\psi}_k + \end{aligned} + $$ + + Unknown physical disturbances are modelled as continuous-time Gaussian white noise. + The runtime spectral densities ([VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC), [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC), [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC)) and the initial-variance parameters are listed in [Noise](#noise); for the full derivation see [Dynamic model process noise](../advanced_features/vision_target_estimator_advanced.md#dynamic-model-process-noise). + + For the experimental moving-target mode that adds target velocity and acceleration states, see [Moving-target mode](../advanced_features/vision_target_estimator_advanced.md#moving-target-mode-experimental). + +::: + +- **Update step:** Corrects the state whenever a new sensor observation arrives and is accepted for fusion. + See [Aid-source diagnostics](../advanced_features/vision_target_estimator_advanced.md#aid-source-diagnostics) to debug the fusion update step. + +### Initialization and Task Scheduling + +Fusion starts as soon as the filter is initialized. +The position filter requires a recent vehicle velocity estimate along with at least one position-like observation to begin. +The orientation filter starts immediately upon receiving the first valid vision yaw sample. + +The estimators only run while a runtime **task** is active. +Tasks are evaluated in priority order, and the first task whose readiness conditions are satisfied is the one that executes. +See [Task Selection](#task-selection) to learn how to select tasks via bitmask. + +### Bias Estimation {#bias-estimation} + +The position filter actively estimates the bias between the absolute target reference (GNSS or mission waypoint) and the vision-derived target position. +Once this bias is observed, the corrected absolute reference effectively becomes a second relative-position sensor. +This allows the vehicle to safely touch down on the target even if vision is briefly lost (e.g., due to motion blur, partial occlusion, or the marker leaving the camera's field of view near the ground). +See [Bias Initialisation](#bias-initialisation) and [Noise](#noise) for bias configuration. + +:::details +Click to view the bias initialization logic + +The GNSS bias $b$ becomes observable only when both GNSS and vision are available, and VTE takes one of two paths depending on which source arrived first. + +- **Vision-first:** When vision is already the active position reference, the bias is activated immediately on the first joint sample. +- **GNSS-first:** When GNSS is active first, VTE low-pass filters the early raw samples (tuned by [VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR) and [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT)) so that vision is only fused once the offset has settled. + +For the full state-reset rules, the LPF exit condition, and the stale-GNSS fallback, see [Bias initialization design](../advanced_features/vision_target_estimator_advanced.md#bias-initialization-design). +::: + +### Time Alignment (Latency Compensation) {#time-alignment} + +Vision and GNSS measurements often reach the autopilot with non-negligible transport or processing latency. +VTE compensates for this by fusing delayed samples against the predicted state at their _original_ timestamp, rather than the current one. +This relies on an **Out-of-Sequence Measurements (OOSM)** approximation using a history-consistent projected correction strategy. +For buffer sizing and algorithm specifics, see [OOSM Implementation](../advanced_features/vision_target_estimator_advanced.md#oosm-implementation). + +### Fallbacks and Timeouts + +If no measurement is fused for a sustained period, the affected filter will coast for a brief window before resetting. +Once reset, it will automatically retry as soon as an enabled fusion source becomes available again. +See [Timeouts](#timeouts) to configure the duration of these fallback windows. + ## Налаштування ### Module Enable -- Set [VTE_EN](../advanced_config/parameter_reference.md#VTE_EN)=1 to run the estimator (reboot required). -- [VTE_POS_EN](../advanced_config/parameter_reference.md#VTE_POS_EN) and [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) enable the position and orientation filters individually (reboot required). - Both are on by default; disable the yaw filter if your vision pipeline does not report target heading. +Set the [VTE_EN](../advanced_config/parameter_reference.md#VTE_EN) parameter `1` to run the estimator (reboot required). + +To enable position and/or yaw tracking set the following parameters (then reboot): + +- [VTE_POS_EN](../advanced_config/parameter_reference.md#VTE_POS_EN): Set to `1` to enable position estimation (track the target position relative to the vehicle). +- [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN): Set to `1` to enable orientation estimation (track the target yaw). + + This is disabled by default. + Enable it if your vision pipeline reports a target heading. ### Timeouts The default timeouts are appropriate for a typical precision-landing approach where measurements keep arriving until touchdown. -You only need to raise them when you know in advance that there will be a long gap with no fresh data, for example a vision-only setup where the marker is larger than the camera field of view during the final descent and you do not want the estimator to time out before touchdown. +Raise them only when you expect a gap in fresh data. +A common example is a vision-only setup where the marker leaves the camera frame in the final metres of descent. When that applies: -- Raise [VTE_TGT_TOUT](../advanced_config/parameter_reference.md#VTE_TGT_TOUT) past the expected gap so the published target pose stays marked valid; the precision-landing controller stops following the target once this expires. +- Raise [VTE_TGT_TOUT](../advanced_config/parameter_reference.md#VTE_TGT_TOUT) past the expected gap so the published target pose stays marked valid. + The precision-landing controller stops following the target once this expires. - Raise [VTE_BTOUT](../advanced_config/parameter_reference.md#VTE_BTOUT) past the expected gap if you want the filter to coast on its last estimate. Otherwise the filter is reset and will restart as soon as enabled fusion sources reappear. -Measurements timestamped in the future relative to the latest filter prediction are always rejected and reported on the corresponding innovation topic. +Measurements timestamped in the future relative to the latest filter prediction are always rejected. ### Measurement Freshness [VTE_M_REC_TOUT](../advanced_config/parameter_reference.md#VTE_M_REC_TOUT) and [VTE_M_UPD_TOUT](../advanced_config/parameter_reference.md#VTE_M_UPD_TOUT) decide how long an incoming sample stays usable: -- [VTE_M_REC_TOUT](../advanced_config/parameter_reference.md#VTE_M_REC_TOUT) is the maximum age at which a new measurement is still eligible for fusion +- [VTE_M_REC_TOUT](../advanced_config/parameter_reference.md#VTE_M_REC_TOUT) is the maximum age at which a new measurement is still eligible for fusion. - [VTE_M_UPD_TOUT](../advanced_config/parameter_reference.md#VTE_M_UPD_TOUT) bounds how long a cached observation remains valid inside the filter state. -These are independent of the timeouts above; tune them to the dynamics of your platform and target, not to a fixed value: +These are independent of the timeouts above. +Tune them to the dynamics of your platform and target, not to a fixed value: - For fast-moving targets and aggressive vehicles, keep both values **short**: stale data describes a world that has already changed, so fusing it pulls the filter in the wrong direction. - For larger vehicles with slow dynamics and modest roll, pitch, yaw rates, the defaults (or even larger values) work fine: a slightly older sample is still informative because the relative geometry has not significantly changed. -If you are unsure, leave the defaults and watch the logs: tracking lag or overshoot on a fast platform usually means these values are too large; legitimate fusions being missed because samples arrive just outside the window means they are too tight. +If you are unsure, leave the defaults and watch the logs. +Tracking lag or overshoot on a fast platform usually means these values are too large. +Legitimate fusions being missed because samples arrive just outside the window means they are too small. ### Task Selection @@ -82,9 +188,11 @@ Set the indicated bit to enable the corresponding task. | 1 | DEBUG (always active) | :::warning -Precision landing yaw control is disabled by default. -Enable [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN) when you want the mission controller to align the vehicle with the target heading, and configure the landing waypoint for precision landing (see [Mission precision landing](../advanced_features/precland.md#mission)). -Without both settings the aircraft will only track the position estimate from the Vision Target Estimator. +The controller only consumes the VTE output once the landing waypoint is configured for precision landing (see [Mission precision landing](../advanced_features/precland.md#mission)). +Without it, the VTE keeps running but its estimates are ignored. + +Yaw alignment is additionally gated by [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN), which is disabled by default. +With precision landing enabled but `PLD_YAW_EN` disabled, only the position estimate is tracked. ::: ### Sensor Fusion Selection @@ -95,89 +203,134 @@ Without both settings the aircraft will only track the position estimate from th | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | 0 | Target GNSS position | | 1 | Vehicle GNSS velocity | -| 2 | Vision-relative position | +| 2 | Vision-based relative pose | | 3 | Mission landing waypoint | | 4 | Target GNSS velocity ([moving mode](../advanced_features/vision_target_estimator_advanced.md#moving-target-mode-experimental) only) | Bit 2 also enables processing of `fiducial_marker_yaw_report` in the orientation filter. -:::tip **Enable more than one source when you can.** -Each source observes a different combination of states: vision contributes a direct relative position, vehicle GNSS velocity directly constrains the vehicle velocity state, and target GNSS or the mission landing waypoint contribute the absolute reference needed to estimate the GNSS/vision bias. -Multiple sources are what make the filter robust to any single one momentarily dropping out. +Each source observes a different combination of states (see the per-source observation models in the details block below), so multiple sources keep the filter robust through momentary dropouts. -**Vehicle GNSS velocity is the most important non-vision source.** -With only vision enabled, the vehicle velocity state is only indirectly observable. -A short vision dropout then produces a visible relative-position drift that snaps back when vision returns. -With vehicle GNSS velocity enabled, the velocity state is observed directly and the relative position stays more stable through vision dropout. -The deep dive plots both cases side by side in [Vision dropout behaviour](../advanced_features/vision_target_estimator_advanced.md#vision-dropout-behaviour). -Only disable this source when you have a specific reason, for example no GNSS available. +- **Vehicle GNSS velocity is important.** Only disable this source when you have a specific reason, for example no GNSS available. + Without it, vision dropouts cause a visible relative-position drift that snaps back when vision returns. + The deep dive plots both cases side by side in [Vision dropout behaviour](../advanced_features/vision_target_estimator_advanced.md#vision-dropout-behaviour). -**An absolute reference makes precision landing robust to vision loss.** -Fusing an absolute reference (target GNSS or the mission landing waypoint) lets the filter estimate the bias between the absolute frame and the vision frame. -Once the bias is observed, the corrected absolute observation effectively becomes a second relative-position sensor: the vehicle can still touch down on the target even when vision is no longer available (for example because the marker leaves the camera field of view in the final metres of descent, or because of motion blur or partial occlusion). -This is especially important for large targets where vision is expected to drop out before touchdown. -The deep dive analyses this on a real flight in [Vision occlusion during descent](../advanced_features/vision_target_estimator_advanced.md#vision-occlusion-during-descent). +- **An absolute reference makes precision landing robust to vision loss.** Fusing an absolute reference (target GNSS or the mission landing waypoint) lets the filter estimate the bias between the absolute frame and the vision frame. + Once the bias is observed, the corrected absolute observation effectively becomes a second relative-position sensor: the vehicle can still touch down on the target even when vision is no longer available (for example because the marker leaves the camera field of view in the final metres of descent, or because of motion blur or partial occlusion). + This is especially important for large targets where vision is expected to drop out before touchdown. + The deep dive analyses this on a real flight in [Vision occlusion during descent](../advanced_features/vision_target_estimator_advanced.md#vision-occlusion-during-descent). + +::: info **Target GNSS position and mission landing waypoint are mutually exclusive.** Both provide the absolute reference for the same GNSS/vision bias, and only one bias can be estimated at a time. If both bits are set, the module disables the mission landing waypoint at startup and prints a warning, but it is cleaner to pick one explicitly: use target GNSS when a receiver is mounted on the target (most accurate), and the mission landing waypoint when no receiver is available. ::: -For each source's uORB topic, observation model, and fusion notes, see [Measurement sources](#measurement-sources) at the end of the page. + -### Noise and Gating +::::details Click to view measurement source specifications and uORB topics + +All measurements are fused sequentially. +For each observation $z$ a one-row Jacobian is formed and applied to a single axis (position filter) or to the yaw state (orientation filter). +Enabled sensors are defined by the [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bitmask. +The state symbols used in the `H` column ($r$, $v^{uav}$, $b$, $v^{t}$, $\psi$) are defined in the [Dynamic models](#dynamic-models) block above. + +| Source | Тема uORB | H structure | Примітки | +| ----------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Target GNSS position | [`target_gnss`](../msg_docs/TargetGnss.md) | $z = r + b$ once the bias is observable, otherwise $z = r$ | The vehicle GNSS sample is interpolated to the target timestamp using the vehicle velocity so the two receivers share a common epoch. Requires [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 0. Before bias activation, this source is held back if the estimator is already vision-referenced. | +| Mission landing waypoint | `navigator_mission_item` with validated `position_setpoint_triplet` fallback | $z = r$ | Provides a fallback absolute reference when target GNSS is unavailable. At precision-land task start VTE caches the logical landing waypoint published by [Navigator](../modules/modules_controller.md#navigator) and keeps using that cached point even after precland rewrites the live triplet. The triplet remains a fallback for modes that do not publish `navigator_mission_item`. Enable [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 3 and avoid combining it with target GNSS because only one GNSS bias can be estimated. Before bias activation, this source is held back if the estimator is already vision-referenced. | +| Vision pose | [`fiducial_marker_pos_report`](../msg_docs/FiducialMarkerPosReport.md) | $z = r$ after rotating the measurement (`rel_pos`) into NED using `q` | Uses the message variances, lower-bounded by [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE). Recent vision fusions are required for EKF aiding. During the initial GNSS/vision bias averaging phase, valid vision samples update the bias low-pass filter but are not fused into the position state yet. This averaging phase only exists when GNSS became the active reference first. | +| Vehicle GNSS velocity | `sensor_gps` | $z = v^{uav}$ | Removes rotation-induced velocity using the vehicle GPS antenna offset parameters (`SENS_GPS0_OFF*`). Enable [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 1. | +| Target GNSS velocity (moving mode) | `target_gnss` | $z = v^{t}$ | Only used by the experimental [Moving-target mode](../advanced_features/vision_target_estimator_advanced.md#moving-target-mode-experimental). | +| Vision yaw | [`fiducial_marker_yaw_report`](../msg_docs/FiducialMarkerYawReport.md) | $z = \psi$ | Only source used by the orientation filter. Requires [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) and [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 2. Variance is taken from the message and lower-bounded by [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE). | + +All innovation data are published on dedicated topics (`vte_aid_gps_pos_target`, `vte_aid_fiducial_marker`, `vte_aid_ev_yaw`, etc.), making it easy to inspect residuals and test ratios in logs. +Every fusion attempt is published, including rejections: the per-axis `fusion_status` enum records the outcome (fused immediately, fused via OOSM history replay, rejected by the NIS gate, rejected as too old or too new, etc.), so tuning sessions can isolate time skew, noise mismatch, or buffer staleness without guessing. + +:::info +UWB and IRLock are candidates for future development once representative test data is available. +::: + +:::: + +### Noise + +This section covers how the [Kalman filter](https://en.wikipedia.org/wiki/Kalman_filter) at the heart of VTE weighs sensor measurements against its own prediction. +Noise parameters set how much trust to place in each input. +The wrong balance shows up as either an over-responsive estimator that chases per-sample jitter or one that lags real motion. +Skip this section if the filter performs well with default settings on your platform. Start from the defaults: they are tuned for a typical setup of consumer GNSS plus a marker-based vision pipeline. Re-tune only when log analysis points at a specific symptom. -The deep dive walks through what a healthy filter looks like in [Plot examples](../advanced_features/vision_target_estimator_advanced.md#plot-examples) and how to balance the parameters in [Balancing process and observation noise](../advanced_features/vision_target_estimator_advanced.md#balancing-process-and-observation-noise). +The deep dive walks through what a healthy filter looks like in [Expected Plot Dashboards](../advanced_features/vision_target_estimator_advanced.md#expected-plot-dashboards) and how to balance the parameters in [Balancing process and observation noise](../advanced_features/vision_target_estimator_advanced.md#balancing-process-and-observation-noise). + +:::details +Click to view a guide for advanced noise tuning - **Initial state variances** ([VTE_POS_UNC_IN](../advanced_config/parameter_reference.md#VTE_POS_UNC_IN), [VTE_VEL_UNC_IN](../advanced_config/parameter_reference.md#VTE_VEL_UNC_IN), [VTE_BIA_UNC_IN](../advanced_config/parameter_reference.md#VTE_BIA_UNC_IN), [VTE_ACC_UNC_IN](../advanced_config/parameter_reference.md#VTE_ACC_UNC_IN), [VTE_YAW_UNC_IN](../advanced_config/parameter_reference.md#VTE_YAW_UNC_IN)) seed the filter at initialization or reset. - Lower them only if you see aggressive transients on `vte_position` immediately after activation; raise them if convergence is very slow. - Updates while the estimator is already running take effect on the next start. + - Lower them only if you see aggressive transients on `vte_position` immediately after activation. + - Raise them if convergence is very slow. + Updates while the estimator is already running take effect on the next start. - **Process noise** ([VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC), [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC), [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC), and [VTE_ACC_T_UNC](../advanced_config/parameter_reference.md#VTE_ACC_T_UNC) for moving-target builds) controls how fast the predicted state variance grows between measurements, which in turn sets how strongly each new observation moves the filter. - Raise these when the estimator lags real motion or repeated innovations show that the prediction uncertainty is too optimistic; lower them when the state follows per-sample jitter rather than the underlying trend. - For a step-by-step recipe with worked examples, see [Balancing process and observation noise](../advanced_features/vision_target_estimator_advanced.md#balancing-process-and-observation-noise). -- **Bias averaging** ([VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR), [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT)) only takes effect when GNSS becomes active before vision; the defaults work for typical consumer GNSS plus marker-based vision. - Set `VTE_BIA_AVG_TOUT=0` to skip averaging and activate the bias on the first joint sample. - Raise `VTE_BIA_AVG_THR` if a noisy vision pipeline cannot satisfy the stability criterion within the timeout. -- **Outlier gates** ([VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE), [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE)) default to a $95\%$ chi-squared confidence interval (3.84). - Tighten the gate if outliers from a noisy sensor are still being fused and visibly pulling the state; loosen it if `vte_aid_*.fusion_status` shows legitimate samples rejected as `STATUS_REJECT_NIS`. - The [troubleshooting checklist](../advanced_features/vision_target_estimator_advanced.md#troubleshooting-checklist) and the rejection-pattern walkthrough in [Plot examples](../advanced_features/vision_target_estimator_advanced.md#plot-examples) help tell the two cases apart. + - Lower them when the state follows per-sample jitter rather than the underlying trend. + - Raise them when the estimator lags real motion or repeated innovations show that the prediction uncertainty is too optimistic. + - For a step-by-step recipe with worked examples, see [Balancing process and observation noise](../advanced_features/vision_target_estimator_advanced.md#balancing-process-and-observation-noise). - **Sensor noise floors** ([VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE), [VTE_GPS_V_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_V_NOISE), [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE), [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE)) are lower bounds on the per-sample standard deviation each sensor is allowed to report. - Raise the floor for a sensor that under-reports its noise (you will see the filter chasing every sample of that sensor in `vte_position` and the corresponding `vte_aid_*.observation`); leave it alone if the reported variance already exceeds the floor. - Do not push these towards zero: a very small floor tells the filter to trust every sample fully, which makes it chase per-sample jitter and can drive the controller into oscillations. - The runtime enforces a hard minimum to keep Kalman gains bounded, but the safer practice is to set a realistic floor that matches the actual sensor accuracy. - See [Between observation sources](../advanced_features/vision_target_estimator_advanced.md#between-observation-sources) for typical mis-tunes. + - Do not push these towards zero: a very small floor tells the filter to trust every sample fully, which makes it chase per-sample jitter and can drive the controller into oscillations. + The runtime enforces a hard minimum to keep Kalman gains bounded, but the safer practice is to set a realistic floor that matches the actual sensor accuracy. + - Raise the floor for a sensor that under-reports its noise (you will see the filter chasing every sample of that sensor in `vte_position` and the corresponding `vte_aid_*.observation`) + - Do not modify the floor if the reported variance already exceeds the floor. + - See [Between observation sources](../advanced_features/vision_target_estimator_advanced.md#between-observation-sources) for typical mis-tunes. + +::: + +### Outlier Detection + +Gating thresholds decide which samples to fuse and which to reject as outliers. +It is controlled by the position and yaw NIS gates ([VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE), [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE)), which default to a 95% chi-squared confidence interval. +There is no need to modify the default unless log analysis shows repeated `fusion_status = STATUS_REJECT_NIS` on valid samples or corrupted samples still passing fusion. +For the gating logic and tuning workflow, see [Outlier Detection](../advanced_features/vision_target_estimator_advanced.md#outlier-detection). + +### Bias Initialisation + +**Bias averaging** ([VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR), [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT)) only takes effect when GNSS becomes active before vision. +The defaults work for typical consumer GNSS plus marker-based vision. +See [Bias initialization design](../advanced_features/vision_target_estimator_advanced.md#bias-initialization-design) for the full state-machine behaviour. + +- Set `VTE_BIA_AVG_TOUT=0` to skip averaging and activate the bias on the first joint sample. +- Raise `VTE_BIA_AVG_THR` if a noisy vision pipeline cannot satisfy the stability criterion within the timeout. ### Sensor-specific Settings -- **GNSS antenna offsets** - `VisionTargetEst` reads `vehicle_gps_position.antenna_offset_{x,y,z}` to remove position- and rotation-induced velocity offsets before forming GNSS measurements. +- **GNSS antenna offsets**: The VTE removes position- and rotation-induced velocity offsets before forming GNSS measurements. Configure the vehicle GPS antenna location with [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY), and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ). -### EKF2 Aiding +During the final descent, GNSS-derived horizontal velocity can degrade (multipath, low-altitude geometry) right when the vehicle needs it most. +VTE can feed its vision-derived relative velocity to [EKF2](../advanced_config/tuning_the_ecl_ekf.md) as an auxiliary measurement to keep the local-position estimate stable when GNSS quality drops near the ground. -For a static target, the relative velocity tracked by the Vision Target Estimator can be fed into the main vehicle state estimator ([EKF2](../advanced_config/tuning_the_ecl_ekf.md)) as an auxiliary velocity measurement. +:::details +Click for more details on EKF2 aiding (auxiliary velocity) + +For a static target, the relative velocity tracked by the position filter (see [Estimator overview](#estimator-overview)) can be fed into the main vehicle state estimator ([EKF2](../advanced_config/tuning_the_ecl_ekf.md)) as an auxiliary velocity measurement. This is especially useful during the final descent, where the camera is typically the most accurate source of horizontal velocity available to the vehicle. -The auxiliary velocity is exposed to EKF2 whenever `landing_target_pose.rel_vel_ekf2_valid` is true, which requires: +VTE exposes the auxiliary velocity to EKF2 when: -- `landing_target_pose.rel_pos_valid = true`, and -- `landing_target_pose.rel_vel_valid = true`, -- `landing_target_pose.is_static = true`, and -- a vision-relative position measurement has been fused within [VTE_M_REC_TOUT](../advanced_config/parameter_reference.md#VTE_M_REC_TOUT). +- the target is static, +- the published relative position and relative velocity are both valid, and +- a vision measurement has been fused recently (within [VTE_M_REC_TOUT](../advanced_config/parameter_reference.md#VTE_M_REC_TOUT)). -The recent vision-relative measurement requirement is intentional: GNSS and mission position can keep the target estimate valid, but they are not true relative measurements and must not enable EKF2 relative-velocity aiding by themselves. +The recent-vision requirement is intentional. +GNSS and mission position can keep the target estimate valid, but they are not true relative measurements and must not drive EKF2 relative-velocity aiding by themselves. -The decision to actually fuse this signal as an EKF2 auxiliary velocity lives in EKF2 and is gated by [EKF2_AVEL_EN](../advanced_config/parameter_reference.md#EKF2_AVEL_EN). -EKF2 only fuses the data when: +EKF2 then decides whether to actually fuse the signal. +This decision is gated by [EKF2_AVEL_EN](../advanced_config/parameter_reference.md#EKF2_AVEL_EN): with that parameter disabled, EKF2 ignores the input even when VTE flags it as valid. -- [EKF2_AVEL_EN](../advanced_config/parameter_reference.md#EKF2_AVEL_EN)=1, -- `landing_target_pose.rel_vel_ekf2_valid = true`. +::: -If any condition fails, EKF2 ignores the input. - -### MAVLink Messages +## MAVLink Messages The estimator receives target information through two MAVLink messages emitted by an onboard companion (vision pipeline and/or external GNSS receiver): @@ -189,28 +342,10 @@ These messages are currently in the MAVLink development dialect. To make them available in PX4 builds the `CONFIG_MAVLINK_DIALECT="development"` key must be set in the build configuration. ::: -#### Data rates +:::details +Click to view MAVLink message integration (TARGET_RELATIVE, TARGET_ABSOLUTE) -The estimator runs its prediction step at 50 Hz regardless of the measurement cadence, and each new sample is only fused if it is fresher than the [Measurement Freshness](#measurement-freshness) window. -The minimum rate you actually need is application-dependent: a slow approach with a static target tolerates a few Hz, while fast-dynamics setups (such as the moving-target filter tracking a manoeuvring platform) typically need tens of Hz so the prediction does not drift too far between updates. -To check whether your rate is sufficient, watch how the state covariance in `vte_position` grows between fused samples: substantial growth before the next observation means the prediction is doing more work than the data supports, and you should either publish faster or accept the reduced confidence. - -#### Companion computer responsibilities - -- **Timestamp** each sample at capture in a clock that is synchronised with the autopilot (typically through `mavlink_timesync`). - The OOSM history replay tolerates transport latency, but only if timestamps are consistent. -- **Report consistent variances** in `pos_std` and `yaw_std` (for [TARGET_RELATIVE](https://mavlink.io/en/messages/development.html#TARGET_RELATIVE)) and `position_std` / `vel_std` (for `TARGET_ABSOLUTE`). - Under-reporting variance is the most common cause of overshoots; the [Sensor noise floors](#noise-and-gating) only clamp the lower bound and cannot rescue an over-confident sensor. -- **Set the coordinate frame** for [TARGET_RELATIVE](https://mavlink.io/en/messages/development.html#TARGET_RELATIVE) (`TARGET_OBS_FRAME`) and provide the `q_sensor` rotation when the camera frame differs from vehicle-carried NED. - -#### Bypassing MAVLink - -If you publish target observations from a different onboard pipeline (for example a ROS 2 node running on the companion), you can write the same data directly to the uORB topics that the estimator subscribes to: `fiducial_marker_pos_report` and `fiducial_marker_yaw_report` for vision, and `target_gnss` for an external receiver. -The timing and variance guidance above still applies, and `VTE_EN=1` must be set so the estimator runs and consumes those topics. - -#### Message Overview - -##### TARGET_RELATIVE (ID 511) +**TARGET_RELATIVE (ID 511)** [TARGET_RELATIVE](https://mavlink.io/en/messages/development.html#TARGET_RELATIVE) extends the [LANDING_TARGET](https://mavlink.io/en/messages/common.html#LANDING_TARGET) message with a full 3D report that includes orientation and measurement uncertainty: @@ -223,7 +358,7 @@ The timing and variance guidance above still applies, and `VTE_EN=1` must be set - When `VTE_EN=1`, the message is split into `fiducial_marker_pos_report` and `fiducial_marker_yaw_report`. `VisionTargetEst` consumes these uORB topics to drive the position and orientation filters (using `fiducial_marker_pos_report.q` to rotate `fiducial_marker_pos_report.rel_pos` into NED at `timestamp_sample`). -##### TARGET_ABSOLUTE (ID 510) +**TARGET_ABSOLUTE (ID 510)** [TARGET_ABSOLUTE](https://mavlink.io/en/messages/development.html#TARGET_ABSOLUTE) reports the target's absolute state when it carries its own GNSS (and optionally IMU). A capability bitmap advertises which fields are valid. @@ -233,11 +368,32 @@ PX4 maps the available content into the `target_gnss` uORB topic: - Bit 1 (velocity) forwards the NED velocity vector (`vel`) and its standard deviations (`vel_std`). - Additional fields (acceleration, quaternion `q_target`, rates, uncertainties) are not supported and reserved for future fusion logic once flight testing is available. +::: + +### Measurement Rates + +The estimator runs its prediction step at 50 Hz regardless of the measurement cadence, and each new sample is only fused if it is fresher than the [Measurement Freshness](#measurement-freshness) window. +The minimum data rate is application-dependent: a slow approach with a static target tolerates a few Hz, while fast-dynamics setups (such as the moving-target filter tracking a manoeuvring platform) typically need tens of Hz so the prediction does not drift too far between updates. +To check whether your rate is sufficient, watch how `vte_position` behaves between fused samples. +If the state visibly diverges between measurements and snaps back when a new sample arrives, the prediction is doing more work than the data supports and you should publish faster. + +### Companion Computer Responsibilities + +- **Timestamp** each sample at capture in a clock that is synchronised with the autopilot (typically through `mavlink_timesync`). + The Out-of-Sequence Measurements ([OOSM](../advanced_features/vision_target_estimator_advanced.md#oosm-implementation)) history replay tolerates transport latency, but only if timestamps are consistent. +- **Report consistent variances** in `pos_std` and `yaw_std` (for [TARGET_RELATIVE](https://mavlink.io/en/messages/development.html#TARGET_RELATIVE)) and `position_std` / `vel_std` (for `TARGET_ABSOLUTE`). + Under-reporting variance is the most common cause of overshoots. + The [Sensor noise floors](#noise) only clamp the lower bound and cannot rescue an over-confident sensor. +- **Set the coordinate frame** for [TARGET_RELATIVE](https://mavlink.io/en/messages/development.html#TARGET_RELATIVE) (`TARGET_OBS_FRAME`) and provide the `q_sensor` rotation when the camera frame differs from vehicle-carried NED. + +### Bypassing MAVLink + +If you publish target observations from a different onboard pipeline (for example a ROS 2 node running on the companion), you can write the same data directly to the uORB topics that the estimator subscribes to: `fiducial_marker_pos_report` and `fiducial_marker_yaw_report` for vision, and `target_gnss` for an external receiver. +The timing and variance guidance above still applies. + ## Симуляція Gazebo Classic -Run the SITL world `gazebo-classic_iris_irlock` to simulate precision landing using the VTEST fusing vision (ArUco-based) and target GNSS aiding. -The world name is retained for historical reasons. -The models were introduced in [PX4/PX4-SITL_gazebo-classic#950](https://github.com/PX4/PX4-SITL_gazebo-classic/pull/950). +Run the SITL world `gazebo-classic_iris_irlock` to simulate precision landing using the VTE fusing vision (ArUco-based) and target GNSS aiding. :::tip The ArUco vision observation path implemented in `Tools/simulation/gazebo-classic/sitl_gazebo-classic/src/gazebo_aruco_plugin.cpp` provides a concrete example of how to obtain a vision-based observation of a target and how to publish the [TARGET_RELATIVE](https://mavlink.io/en/messages/development.html#TARGET_RELATIVE) message. @@ -261,12 +417,13 @@ The ArUco vision observation path implemented in `Tools/simulation/gazebo-classi - **Pad visibility**: In `Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/land_pad/land_pad.sdf`, increase the visual box size to `1.5 1.5 0.01` so the pad stays in view longer while the vehicle descends. If vision still detects the pad too late in the descent, complement this by planning a lower-altitude mission so the marker enters the camera field of view earlier. -- **Acceptance radius**: If the vehicle hovers above the pad without ever transitioning to descent, raise [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD). Try 2 m first to confirm the rest of the chain works, then tighten it once the filter is well tuned. +- **Acceptance radius**: If the vehicle hovers above the pad without ever transitioning to descent, raise [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD). + Try 2 m first to confirm the rest of the chain works, then tighten it once the filter is well tuned. - **Mission waypoint bias**: Enable vision and mission position aiding in [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) (set bits 2 and 3, disable bit 0). Place the landing waypoint 3 to 4 m away from the pad in QGroundControl to watch the UAV correct towards the pad once it is detected. In the logs, observe how the GNSS bias compensates for the distance between the land waypoint and the actual pad. - **Measurement noise experiments**: The ArUco plugin publishes nominal standard deviations through `set_std_x` and `set_std_y` in `Tools/simulation/gazebo-classic/sitl_gazebo-classic/src/gazebo_aruco_plugin.cpp`. - Modify these assignments, and optionally the camera noise block in `.../models/aruco_cam/aruco_cam.sdf`, to see how innovation gates react to noisier vision. + Modify these, and optionally the camera noise block in `.../models/aruco_cam/aruco_cam.sdf`, to see how innovation gates react to noisier vision. ::: @@ -283,108 +440,24 @@ vision_target_estimator status which reports whether the module is alive, which task is currently active, which filters are running, and which aid sources are enabled. It is the quickest way to confirm a configuration is taking effect before opening a log. +For deeper inspection, the following uORB topics are the most useful entry points into a log: + - `landing_target_pose.rel_pos_valid` and `.abs_pos_valid` indicate whether recent measurements support relative and absolute positioning. - `vte_position` exposes every state component (relative position, vehicle velocity, GNSS bias, and optional target motion) together with diagonal covariance entries. - `vte_orientation` provides yaw, yaw-rate, and their variances. - `vte_input` records the downsampled NED acceleration and attitude quaternion actually fed to the position prediction step. - `vte_bias_init_status` shows raw and filtered GNSS/vision bias while the initial averaging phase is active. -- Innovations published on `vte_aid_*` topics include the raw measurement, innovation, innovation variance, chi-squared test ratio, the `fusion_status` enum (per-axis on the 3D variant), and OOSM diagnostics (`time_since_meas_ms`, `history_steps`). - See [aid-source diagnostics](./vision_target_estimator_advanced.md#aid-source-diagnostics) for the full status table. +- Innovations published on `vte_aid_*` topics include the raw measurement, innovation, innovation variance, chi-squared test ratio, the `fusion_status` enum (per-axis on the 3D variant), and Out-of-Sequence Measurements ([OOSM](../advanced_features/vision_target_estimator_advanced.md#oosm-implementation)) diagnostics (`time_since_meas_ms`, `history_steps`). + See [aid-source diagnostics](../advanced_features/vision_target_estimator_advanced.md#aid-source-diagnostics) for the full status table. ## Operational Notes - Accurate timestamp alignment between measurement sources is critical. Large skews will cause innovations to fail the NIS gate and be rejected. - Absolute target pose is only published when `vehicle_local_position` reports a valid local frame. -- When you expect yaw alignment during landing, enable [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN) and configure the mission land item for precision landing as described in [Precision landing](../advanced_features/precland.md#mission). - In practice this means setting the QGroundControl land waypoint `Precision landing` drop-down (or `MAV_CMD_NAV_LAND` `param2`) to Opportunistic or Required so the controller requests the estimator output. - Otherwise only positional cues are used. +- Configure the mission land item for precision landing as described in [Precision landing](../advanced_features/precland.md#mission) so the controller actually consumes the VTE output. + In practice this means setting the QGroundControl land waypoint `Precision landing` drop-down (or `MAV_CMD_NAV_LAND` `param2`) to Opportunistic or Required. + Without it, the VTE estimates are ignored even when the filter is running. +- For yaw alignment during landing, also enable [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN). + With precision landing enabled but `PLD_YAW_EN` disabled, only the position estimate is tracked. - For extended parameter tuning see [Balancing process and observation noise](../advanced_features/vision_target_estimator_advanced.md#balancing-process-and-observation-noise), for log-analysis checklists see [Troubleshooting checklist](../advanced_features/vision_target_estimator_advanced.md#troubleshooting-checklist), and for developer workflows see [Development and debugging tips](../advanced_features/vision_target_estimator_advanced.md#development-and-debugging-tips). - -## Estimator Overview - -This section describes how the filter works internally. -It is recommended background reading and not required to set up or operate the feature. - -The Vision Target Estimator runs two independent estimators at a fixed 50 Hz: a **position filter** that tracks where the target is relative to the vehicle, and an **orientation filter** that tracks the target yaw. -The position filter is structured as three decoupled 1D Kalman filters, one per NED axis, so each axis can be tuned and validated independently. - -Each Kalman filter alternates between two operations: - -- A **prediction step** propagates the state forward at 50 Hz using the vehicle motion model. -- An **update step** corrects the state whenever a new sensor observation arrives and passes outlier detection. - Outliers are rejected by a chi-squared gate on the innovation (tunable through [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) and [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE), defaulting to a 95% confidence interval). - -Fusion starts as soon as the filter is initialized: the position filter needs a recent vehicle velocity estimate together with at least one position-like observation; the orientation filter starts on the first valid vision yaw sample. - -The estimators only run while a runtime **task** is active. -[VTE_TASK_MASK](../advanced_config/parameter_reference.md#VTE_TASK_MASK) selects which tasks are eligible (currently precision landing and a debug-always-on bit). -Tasks are evaluated in priority order, and the first task whose readiness conditions are satisfied is the one that runs. - -If no measurement is fused for a sustained period, the affected filter resets and retries automatically once an enabled fusion source becomes available again. -See [Timeouts](#timeouts) for the relevant tuning knobs. - -### Dynamic Models - -The per-axis position state is $x = [ r, v^{uav}, b ]^T$: the relative NED displacement (target minus vehicle), the vehicle velocity, and the offset between the absolute target reference (GNSS or mission waypoint) and the vision-derived target position. -Assuming constant NED acceleration input $a^{uav}$ over the integration interval $dt$: - -$$ -\begin{aligned} -r_{k+1} &= r_k - dt\thinspace v^{uav}_k - \tfrac{1}{2}\thinspace dt^2\thinspace a^{uav} \\ -v^{uav}_{k+1} &= v^{uav}_k + dt\thinspace a^{uav} \\ -b_{k+1} &= b_k -\end{aligned} -$$ - -Once the bias is known, GNSS can keep the estimate centred on the target even if vision drops out. - -The yaw filter tracks $x = [ \psi, \dot{\psi} ]^T$ with a constant-rate prediction (yaw wrapped to $[-\pi, \pi]$): - -$$ -\begin{aligned} -\psi_{k+1} &= \text{wrap}\negthinspace\left(\psi_k + dt\thinspace\dot{\psi}_k\right) \\ -\dot{\psi}_{k+1} &= \dot{\psi}_k -\end{aligned} -$$ - -Unknown physical disturbances are modelled as continuous-time Gaussian white noise. -The runtime spectral densities ([VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC), [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC), [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC)) and the initial-variance parameters are listed in [Noise and Gating](#noise-and-gating); for the full derivation see [Dynamic model process noise](../advanced_features/vision_target_estimator_advanced.md#dynamic-model-process-noise). - -For the experimental moving-target mode that adds target velocity and acceleration states, see [Moving-target mode](../advanced_features/vision_target_estimator_advanced.md#moving-target-mode-experimental). - -### Bias Estimation - -The GNSS bias $b$ becomes observable only when both GNSS and vision are available, and VTE takes one of two paths depending on which source arrived first. -When vision is already the active position reference, the bias is activated immediately on the first joint sample. -When GNSS is active first, VTE low-pass filters the early raw samples (tuned by [VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR) and [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT)) so that vision is only fused once the offset has settled. - -For the full state-reset rules, the LPF exit condition, and the stale-GNSS fallback, see [Bias initialization design](../advanced_features/vision_target_estimator_advanced.md#bias-initialization-design). - -### Time Alignment - -Vision and GNSS observations can arrive delayed due to transport and processing latency. -The position and orientation filters therefore support an **Out-of-Sequence Measurements (OOSM)** approximation which uses a **history-consistent projected correction** strategy. -For the algorithm, the buffer sizing, and the approximation assumptions, see [OOSM Implementation](../advanced_features/vision_target_estimator_advanced.md#oosm-implementation) in the deep dive. - -### Measurement Sources - -All measurements are fused sequentially. -For each observation `z` a one-row Jacobian is formed and applied to a single axis (position filter) or to the yaw state (orientation filter). -Enabled sensors are defined by the [VTE_AID_MASK](#sensor-fusion-selection) bitmask. - -| Source | Тема uORB | H structure | Примітки | -| ----------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Target GNSS position | [`target_gnss`](../msg_docs/TargetGnss.md) | $z = r + b$ once the bias is observable, otherwise $z = r$ | The vehicle GNSS sample is interpolated to the target timestamp using the vehicle velocity so the two receivers share a common epoch. Requires [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 0. Before bias activation, this source is held back if the estimator is already vision-referenced. | -| Mission landing waypoint | `navigator_mission_item` with validated `position_setpoint_triplet` fallback | $z = r$ | Provides a fallback absolute reference when target GNSS is unavailable. At precision-land task start VTEST caches the logical landing waypoint published by Navigator and keeps using that cached point even after precland rewrites the live triplet. The triplet remains a fallback for modes that do not publish `navigator_mission_item`. Enable [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 3 and avoid combining it with target GNSS because only one GNSS bias can be estimated. Before bias activation, this source is held back if the estimator is already vision-referenced. | -| Vision pose | [`fiducial_marker_pos_report`](../msg_docs/FiducialMarkerPosReport.md) | $z = r$ after rotating the measurement (`rel_pos`) into NED using `q` | Uses the message variances, lower-bounded by [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE). Recent vision fusions are required for EKF aiding. During the initial GNSS/vision bias averaging phase, valid vision samples update the bias low-pass filter but are not fused into the position state yet. This averaging phase only exists when GNSS became the active reference first. | -| Vehicle GNSS velocity | `sensor_gps` | $z = v^{uav}$ | Removes rotation-induced velocity using `vehicle_gps_position.antenna_offset_{x,y,z}`, which are populated from the vehicle GPS antenna offset parameters (`SENS_GPS0_OFF*`). Enable [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 1. | -| Target GNSS velocity (moving mode) | `target_gnss` | $z = v^{t}$ | Only used by the experimental [Moving-target mode](../advanced_features/vision_target_estimator_advanced.md#moving-target-mode-experimental). | -| Vision yaw | [`fiducial_marker_yaw_report`](../msg_docs/FiducialMarkerYawReport.md) | $z = \psi$ | Only source used by the orientation filter. Requires [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) and [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 2. Variance is taken from the message and lower-bounded by [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE). | - -All innovation data are published on dedicated topics (`vte_aid_gps_pos_target`, `vte_aid_fiducial_marker`, `vte_aid_ev_yaw`, etc.), making it easy to inspect residuals and test ratios in logs. -Every fusion attempt is published, including rejections: the per-axis `fusion_status` enum records the outcome (fused immediately, fused via OOSM history replay, rejected by the NIS gate, rejected as too old or too new, etc.), so tuning sessions can isolate time skew, noise mismatch, or buffer staleness without guessing. - -:::info -UWB and IRLock are candidates for future development once representative test data is available. -::: diff --git a/docs/uk/advanced_features/vision_target_estimator_advanced.md b/docs/uk/advanced_features/vision_target_estimator_advanced.md index bd2b4ae20d..82427fbf7b 100644 --- a/docs/uk/advanced_features/vision_target_estimator_advanced.md +++ b/docs/uk/advanced_features/vision_target_estimator_advanced.md @@ -11,24 +11,26 @@ It documents the system architecture of the Vision Target Estimator, and outline ## System Architecture -The implementation is split across a scheduler, a task layer, and two independent estimators: +The module has three layers: a scheduler, a task layer, and two independent estimators. - `VisionTargetEst` (`src/modules/vision_target_estimator/VisionTargetEst.cpp`) owns the work-queue task. - Its main loop handles generic vehicle inputs (`vehicle_attitude`, `vehicle_acceleration`, `vehicle_local_position`, `vehicle_gps_position`, and angular rates), downsamples acceleration, publishes [`vte_input`](../msg_docs/VteInput.md), and sends the samples to the position and orientation filters every 20 ms (50 Hz). - It also owns a priority-ordered registry of runtime tasks and keeps the generic logic for task dispatch, estimator start/stop, idle scheduling, and timeout handling. + Its main loop subscribes to vehicle inputs (`vehicle_attitude`, `vehicle_acceleration`, `vehicle_local_position`, `vehicle_gps_position`, and angular rates). + It downsamples acceleration, publishes [`vte_input`](../msg_docs/VteInput.md), and forwards the samples to the position and orientation filters every 20 ms (50 Hz). + It also holds the task registry and the generic logic for task dispatch, estimator start/stop, idle scheduling, and timeout handling. - `tasks/VteTask.h` defines the task interface and the `VTE_TASK_MASK` bit constants. A task owns all state that only exists for one VTE use-case, such as subscriptions to external status topics, cached mission setpoints, and end-of-task conditions. `VisionTargetEst` polls each enabled task, then activates the first task in the registry whose readiness conditions are satisfied. -- `tasks/PrecLandTask.cpp` implements the precision-landing task. - It monitors [`prec_land_status`](../msg_docs/PrecLandStatus.md), caches the land waypoint from `navigator_mission_item` (with `position_setpoint_triplet` as a fallback), and completes when precland stops or touchdown is detected. + - `tasks/PrecLandTask.cpp` implements the precision-landing task. + It monitors [`prec_land_status`](../msg_docs/PrecLandStatus.md), caches the land waypoint from `navigator_mission_item` (with `position_setpoint_triplet` as a fallback), and completes when precland stops or touchdown is detected. - `VTEPosition` (`Position/VTEPosition.cpp`) owns the three per-axis position filters. It maintains observation buffers, enforces timeouts, and publishes `landing_target_pose`, [`vte_position`](../msg_docs/VtePosition.md), and every `vte_aid_*` innovation topic. - The state vector is `[r, v^uav, b]` (relative position, vehicle velocity, GNSS-vs-vision bias); see [Dynamic models](../advanced_features/vision_target_estimator.md#dynamic-models). - - It also runs the bias-initialization state machine described in [Bias Initialization Design](#bias-initialization-design), so the bias `b` is reconciled before it is fused. - - The math is delegated to `Position/KF_position.cpp`, which calls the SymForce-generated routines documented in [SymForce-generated derivations](#symforce-generated-derivations). + The state vector is $[r, v^{uav}, b]$ (relative position, vehicle velocity, GNSS-vs-vision bias); see [Dynamic models](../advanced_features/vision_target_estimator.md#dynamic-models). + - It also runs the bias-initialization state machine described in [Bias Initialization Design](#bias-initialization-design). + - The math is delegated to `Position/KF_position.cpp`, which calls the SymForce-generated functions documented in [SymForce-generated derivations](#symforce-generated-derivations). - Helper unions `SensorFusionMaskU` and `ObsValidMaskU` mirror the bit layout of [`VTE_AID_MASK`](../advanced_features/vision_target_estimator.md#sensor-fusion-selection), making it straightforward to add new observation types ([Adding new measurement sources](#adding-new-measurement-sources)). -- `VTEOrientation` (`Orientation/VTEOrientation.cpp`) handles yaw fusion with the same measurement staging helpers as the position filter, on a smaller `[psi, psi_dot]` state. - The math lives in `Orientation/KF_orientation.cpp`; prediction and the transition matrix are SymForce-generated, while innovation and correction stay hand-written so yaw can be wrapped to $[-\pi, \pi]$. +- `VTEOrientation` (`Orientation/VTEOrientation.cpp`) handles yaw fusion with the same measurement staging helpers as the position filter, on a smaller $[\psi, \dot\psi]$ state. + The math lives in `Orientation/KF_orientation.cpp`. + Prediction and the transition matrix are SymForce-generated, while innovation and correction stay hand-written so yaw can be wrapped to $[-\pi, \pi]$. - Shared utilities live in `common.h` and `VTEOosm.h` (templated OOSM manager, see [OOSM Implementation](#oosm-implementation)). ```text @@ -44,6 +46,26 @@ VisionTargetEst (work item, 50 Hz) └── shared utilities common.h, VTEOosm.h (templated OOSM history buffer) ``` +## Filter Observability + +Some states are observed directly by a sensor; others are inferred through the prediction model. +The indirectly observed states are the weak spots of the filter: when their driving sensor drops out, errors integrate into the rest of the state. + +In the position state $[r, v^{uav}, b]$, vision measures $r$ directly but never touches $v^{uav}$. +Vehicle velocity is only constrained through the position prediction. +While vision keeps arriving, that indirect coupling keeps $v^{uav}$ close to truth. +The moment vision drops out, any residual in $v^{uav}$ integrates straight into `vte_position.rel_pos` and the filter drifts. + +The same applies to the moving-target velocity $v^{t}$. +Without a direct observation, the filter infers it from successive position fixes, which is noisier and breaks down during dropouts. + +**Recommendation:** enable a direct velocity observation when available. + +- Vehicle: vehicle GNSS velocity ([VTE_AID_MASK](../advanced_features/vision_target_estimator.md#sensor-fusion-selection) bit 1). +- Moving target: target GNSS velocity ([VTE_AID_MASK](../advanced_features/vision_target_estimator.md#sensor-fusion-selection) bit 4). + +See [Vision dropout behaviour](#vision-dropout-behaviour) for a worked plot of both cases. + ## Bias Initialization Design The bias state exists because the absolute target reference and the relative vision reference do not necessarily agree: @@ -62,26 +84,46 @@ Naive bias initialization is not robust: - **Instantaneous bias from the first sample** trusts a single early vision frame. If that frame is noisy and vision is lost soon after, the estimator can continue descending with the wrong corrected GNSS offset. -The implementation therefore uses two different bias-initialization paths depending on which position source is trusted first: +The implementation therefore uses two different bias-initialization paths depending on which position source is trusted first. -1. **Startup prerequisites**: `VTEPosition::initializeEstimator()` requires a recent local-velocity or UAV-GNSS-velocity estimate before the filter can start. - This is needed to initialize the `v^{uav}` state and also to support the GNSS-to-vision time alignment used by the bias logic. -2. **Raw bias sample**: whenever a valid GNSS-relative sample exists, the code computes the initial bias from `selectBiasGnssSample(sample_time)`, where `sample_time` is the vision timestamp. - If the GNSS-relative sample is older than vision but still valid, the helper propagates it forward with the UAV velocity estimate. - In other words, the bias logic uses `pos_rel_gnss(t_vision)`, not the stale stored `pos_rel_gnss`. -3. **Why the behavior is asymmetric**: if GNSS is already driving the position state, feeding in raw vision before the bias is ready would mix two frames that can differ by metres. - That is why VTE delays vision in the GNSS-first case. - If vision is already driving the position state, the safer choice is the opposite: keep the trusted vision-based `r` and solve for the bias immediately when GNSS and vision overlap for the first time. -4. **Immediate activation case**: when the estimator is already vision-referenced, VTE computes `b = pos_rel_gnss(t_vision) - pos_rel_vision` and keeps `r = pos_rel_vision`. - The same immediate-activation path is also used when [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT)=0, even if GNSS was active first. -5. **Averaging case**: when GNSS is active first and averaging is enabled, vision updates the LPF at the vision rate while GNSS remains the active position source. - The raw sample is still `pos_rel_gnss(t_vision) - pos_rel_vision`, so the rate mismatch between GNSS and vision does not force the estimator to discard intermediate vision frames. -6. **Exit condition**: the LPF is accepted only after 5 consecutive raw-bias delta norms stay below [VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR) and at least `2 * tau` has elapsed (`tau = 0.3 s`), or when [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT) expires. -7. **Activation after averaging**: once the LPF is accepted, the state reset is `activateBiasEstimate(gnss_sample - filtered_bias, filtered_bias)`, which means `r = pos_rel_gnss(t_vision) - b_filtered`, `b = b_filtered`. -8. **Stale-GNSS fallback**: if GNSS goes stale during averaging, `selectBiasGnssSample()` fails and the code intentionally switches to the current vision position while keeping the current filtered bias. - This is the only bias-initialization branch that does not use `pos_rel_gnss(t_vision)`, because no valid GNSS sample exists anymore. -9. **No re-initialization after recovery**: once the bias is set for the current estimator run, a temporary vision dropout does not restart the averaging phase. - When vision returns, the existing bias stays active. +Open the box below if you are debugging a bias that fails to converge, jumps unexpectedly, or stays at zero in cases where you expected averaging to kick in. + +:::details +Click to view the bias initialization state machine + +#### Prerequisites and Startup Conditions + +- **Before the filter starts.** A recent UAV velocity estimate (local or GNSS) must be available. + It seeds the $v^{uav}$ state and lets the bias logic align GNSS and vision in time. +- **Sampling the raw bias.** The raw bias is always evaluated at the vision timestamp `t_vision`. + If the most recent GNSS-relative sample is older than vision, it is propagated forward using the UAV velocity. + The bias logic therefore uses `pos_rel_gnss(t_vision)`, not the stale stored value. + +#### Initialization Paths: GNSS-First vs Vision-First + +- **Why the behaviour is asymmetric.** + - If GNSS is already driving the position state, feeding in raw vision before the bias is ready would mix two frames that can differ by metres.That is why VTE delays vision in the GNSS-first case. + - If vision is already driving the position state, the safer choice is the opposite: keep the trusted vision-based $r$ and solve for the bias immediately when GNSS and vision overlap for the first time. +- **Immediate activation (vision-first).** When the estimator is already vision-referenced, VTE computes `b = pos_rel_gnss(t_vision) - pos_rel_vision` and keeps `r = pos_rel_vision`. + The same immediate-activation path is also used when [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT) is 0, even if GNSS was active first. +- **Averaging (GNSS-first).** When GNSS is active first and averaging is enabled, vision updates the LPF at the vision rate while GNSS remains the active position source. + The raw sample is still `pos_rel_gnss(t_vision) - pos_rel_vision`, so the rate mismatch between GNSS and vision does not force the estimator to discard intermediate vision frames. + +#### Filter Convergence and Exit Criteria + +- **Exit condition.** The LPF is accepted after 5 consecutive raw-bias delta norms stay below [VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR) and at least `2 * tau` has elapsed (`tau = 0.3 s`). + If neither condition fires, the LPF is also accepted when [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT) expires. +- **Activation after averaging.** Once the LPF is accepted, the state resets via `activateBiasEstimate()`. + This sets `r = pos_rel_gnss(t_vision) - b_filtered` and `b = b_filtered`. + +#### Fallbacks and Recovery + +- **Stale-GNSS fallback.** If GNSS goes stale during averaging, `selectBiasGnssSample()` fails and VTE intentionally switches to the current vision position while keeping the current filtered bias. + This is the only bias-initialization branch that does not use `pos_rel_gnss(t_vision)`, because no valid GNSS sample exists anymore. +- **No re-initialization after recovery.** Once the bias is set for the current estimator run, a temporary vision dropout does not restart the averaging phase. + When vision returns, the existing bias stays active. + +::: For the runtime tuning of the bias state (how aggressively it follows new observations once activated), see [Tuning the bias state](#tuning-the-bias-state) in the next section. @@ -95,23 +137,33 @@ Two distinct noise tunings shape the filter's behaviour, and the right trade-off A stiffer prediction (smaller process noise) shrinks the Kalman gain because the predicted covariance $P$ is smaller, so each observation moves the state less. The two interact through the Kalman gain $K \approx P / (P + R)$, where $P$ is the predicted state variance (grown by the process noise between updates) and $R$ is the observation variance the sensor reports for this sample. -The `VTE_*_NOISE` parameters can only raise $R$, not lower it: they impose a minimum below which a sensor's reported variance is clamped. -So two knobs shape $K$ for the same fusion step: how fast $P$ grows (set by the process-noise spectral densities) and how much $R$ is allowed to drop (set by the noise minima `VTE_*_NOISE` on each sensor). +It is therefore important to have a realistic $R$ from each sensor. +For vision this is the responsibility of the vision pipeline running on the onboard companion: it must publish a `cov_rel_pos` that reflects the marker accuracy at the current range and lighting. +For GNSS it is up to the receiver to publish a realistic `eph`/`epv` and velocity accuracy. +The `VTE_*_NOISE` parameters do not improve $R$: they only act as a safety floor when a sensor under-reports its variance. Pushing either knob to an extreme produces the same failure mode: -- $P$ much larger than $R$ (loose prediction, or a noise minimum so low that $R$ matches a sensor under-reporting its noise) $\rightarrow K \approx 1 \rightarrow$ the state chases every sample. -- $P$ much smaller than $R$ (stiff prediction, or a noise minimum so high that good sensor variance is overridden) $\rightarrow K \approx 0 \rightarrow$ the filter under-reacts to legitimate corrections. +- $P$ much larger than $R$ (loose prediction, or a sensor under-reporting its noise without a floor to catch it) $\rightarrow K \approx 1 \rightarrow$ the state chases every sample. +- $P$ much smaller than $R$ (stiff prediction, or a noise floor set so high it overrides good sensor variance) $\rightarrow K \approx 0 \rightarrow$ the filter under-reacts to legitimate corrections. Tune them together so the resulting gain produces the response speed and noise rejection you actually want. +Each step toward a smoother state is also a step toward slower response to legitimate motion. +After every change, watch `vte_aid_*.innovation`: a healthy filter has zero-mean white-noise innovations, while a growing mean or persistent offset means the response has been damped too much. ### Between Observation Sources How much the filter trusts vision relative to GNSS at any given moment is decided by the per-sample **observation variance** each sensor reports ([`fiducial_marker_pos_report.cov_rel_pos`](../msg_docs/FiducialMarkerPosReport.md), `sensor_gps.eph`, `sensor_gps.epv`, [`target_gnss.s_acc_m_s`](../msg_docs/TargetGnss.md)). -The bias-initialization section above explained how the two _frames_ are reconciled; this part covers how trust is split between sources within a single fusion step. +The bias-initialization section above explained how the two _frames_ are reconciled. +This part covers how trust is split between sources within a single fusion step. -The estimator can only override the sensor in one direction. -Each fused source has a noise-floor parameter that imposes a lower bound on its standard deviation; the effective observation variance used for fusion is: +To inspect this in flight, overlay `vte_aid_fiducial_marker.observation_variance` and `vte_aid_gps_pos_target.observation_variance` (or `vte_aid_gps_pos_mission`) on a typical descent and compare each curve to the accuracy you actually expect from the sensor at that operating distance. +A healthy plot shows that the two sources are roughly equal, with `vte_position.cov_rel_pos` staying below both, as shown in the [Nominal Behaviour dashboard](#nominal-behaviour). + +### Observation Noise Floors + +When a sensor under-reports its own noise, the filter ends up trusting it more than it should. +Each fused source has a noise-floor parameter that imposes a lower bound on its standard deviation, so the effective observation variance used for fusion is: $$ R_{\text{eff}} = \max\bigl(R_{\text{reported}},\ \text{VTE\_*\_NOISE}^2\bigr). @@ -124,9 +176,9 @@ $$ | [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) | m | 0.50 | GNSS position (target and mission) | | [VTE_GPS_V_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_V_NOISE) | m/s | 0.30 | UAV and target GNSS velocity | -These are **standard deviations**, not variances; the estimator squares them internally before clamping. -They only matter when the sensor under-reports its own noise. -If the reported variance already sits above the floor, the parameter has no effect. +These are **standard deviations**, not variances. +The estimator squares them internally before clamping. +The floor only matters when the sensor under-reports its own noise: if the reported variance already sits above the floor, the parameter has no effect. Two common mis-tunes: @@ -134,266 +186,50 @@ Two common mis-tunes: 2. **Floor too loose** (for example `VTE_GPS_P_NOISE = 5.0` with an RTK receiver reporting 3 cm `eph`): the floor wins and the filter throws away the receiver's confidence. `vte_position.cov_rel_pos` stays close to the prediction variance and the bias is never refined during descent. -To tune, overlay `vte_aid_fiducial_marker.observation_variance` and `vte_aid_gps_pos_target.observation_variance` (or `vte_aid_gps_pos_mission`) on a typical descent and compare each curve to the accuracy you actually expect from the sensor at the relevant operating distance. -A healthy plot shows a crossover where the two sources are roughly equal, with `vte_position.cov_rel_pos` staying below both, as shown in the [estimator-output plot](#plot-examples) further down this page. - ### Process Noise: Variance Rates All process-noise parameters are continuous-time **power spectral densities** (PSDs). A PSD describes the strength of a continuous white-noise process: it is the variance the noise injects per second into the state it directly drives, with units chosen so that `PSD × time` is the variance of that state. See [Spectral density (Wikipedia)](https://en.wikipedia.org/wiki/Spectral_density) for background. -| Параметр | Drives directly | Unit | What it represents | -| ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | -| [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) | `bias` (m) | $m^2/s$ | PSD of the bias random walk | -| [VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC) | `vel_uav` (m/s) | $m^2/s^3$ | PSD of white acceleration noise on the UAV acceleration input | -| [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC) | `yaw_rate` (rad/s) | $rad^2/s^3$ | PSD of white yaw-acceleration noise | -| [VTE_ACC_T_UNC](../advanced_config/parameter_reference.md#VTE_ACC_T_UNC) | `acc_target` (m/s²) | $(m/s^2)^2/s = m^2/s^5$ | PSD of white jerk noise driving the target-acceleration random walk (moving-target builds) | +| Параметр | Drives directly | Unit | What it represents | +| ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------- | +| [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) | `bias` (m) | m²/s | PSD of the bias random walk | +| [VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC) | `vel_uav` (m/s) | m²/s³ | PSD of white acceleration noise on the UAV acceleration input | +| [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC) | `yaw_rate` (rad/s) | rad²/s³ | PSD of white yaw-acceleration noise | +| [VTE_ACC_T_UNC](../advanced_config/parameter_reference.md#VTE_ACC_T_UNC) | `acc_target` (m/s²) | (m/s²)²/s = m²/s⁵ | PSD of white jerk noise driving the target-acceleration random walk (moving-target builds) | The unit always follows the same rule: it is `[unit of the directly driven state]² / s`. -The bias is in metres, so its PSD is `m²/s`; the UAV velocity is in m/s, so the acceleration PSD that drives it is `(m/s)²/s = m²/s³`; and so on. +The bias is in metres, so its PSD is `m²/s`. +The UAV velocity is in m/s, so the acceleration PSD that drives it is `(m/s)²/s = m²/s³`, and so on. The YAML may list the same unit in two equivalent forms (for example `m²/s³` and `(m/s²)²/Hz`, since `Hz = 1/s`), but both refer to the same physical quantity. -**Variance rate, not linear drift rate.** This is the most common source of confusion. +:::info +**Variance-rate rule (key formula).** A spectral density is _not_ a velocity. -Every predict step the integrated process-noise contribution adds a term proportional to `spectral_density * dt` to the directly driven variance, so the 1-sigma expected change of that quantity grows with the _square root_ of elapsed time: +Each predict step adds `spectral_density * dt` to the variance of the directly driven state. +The 1-sigma allowance therefore grows with the _square root_ of elapsed time: $$ \sigma(t) = \sqrt{\text{spectral density} \cdot t} $$ +The tuning sections below reference this rule directly. +Set the PSD so the resulting $\sigma(t)$ over a representative interval matches the realistic physical uncertainty. +::: + Because the noise is scaled by `dt` at every predict step, the value is independent of the filter update rate. Running the filter at 25 Hz, 50 Hz, or 100 Hz produces the same long-term allowance, so no retuning is required if the rate changes. -### Tuning the UAV Acceleration Process Noise + -[VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC) (unit: $m^2/s^3$, default $0.02$) is the PSD of un-modelled UAV acceleration that drives the `vel_uav` state. -Larger values let measurements pull the state harder between updates; smaller values lock the state to the IMU-driven prediction. +:::details +Click to view the dynamic-model for the process noise -Applying the $\sigma_v(t) = \sqrt{\text{VTE\_ACC\_D\_UNC} \cdot t}$ rule gives the 1-sigma velocity allowance the filter accumulates between updates: +This section covers the math behind the process-noise parameters. +You only need it if you want to understand how the spectral densities propagate through the prediction model. -| Elapsed time | `VTE_ACC_D_UNC = 0.02` (default) | `VTE_ACC_D_UNC = 0.2` | `VTE_ACC_D_UNC = 1.0` | -| --------------------- | --------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------ | -| 0.1 s | $\sqrt{0.002}\approx 0.045$ m/s | $\sqrt{0.02}\approx 0.14$ m/s | $\sqrt{0.1}\approx 0.32$ m/s | -| 1 s | $\sqrt{0.02}\approx 0.14$ m/s | $\sqrt{0.2}\approx 0.45$ m/s | $\sqrt{1.0} = 1.00$ m/s | -| 10 s | $\sqrt{0.2}\approx 0.45$ m/s | $\sqrt{2.0}\approx 1.41$ m/s | $\sqrt{10}\approx 3.16$ m/s | - -A useful first estimate comes from `vte_input.acc_xyz`: on a representative segment, read off the peak swing $\sigma_a$ and the time scale $\tau$ over which a given deviation persists, then use $\sigma_a^2 \cdot \tau$. -For example, a trace wandering between $-0.05$ and $+0.10$ m/s² in periods of order 1 s ($\sigma_a \approx 0.075$ m/s², $\tau \approx 1$ s) gives a starting value of $\approx 0.006$ $m^2/s^3$. - -Symptoms and fixes (visible on `vte_position.rel_pos` overlaid with the matching `vte_aid_*.observation`): - -1. **Staircase between fusions**: the state drifts away from the observation between samples and snaps back at each fusion. - `VTE_ACC_D_UNC` is too low. - Raise it. - Before pushing it far, first check `vte_input.acc_xyz` for a persistent bias (attitude/gravity leakage, lever-arm error, or real vehicle acceleration); raising process noise does not remove the bias itself. -2. **State copies the per-sample jitter** of the measurement, and the vehicle oscillates near the ground: `VTE_ACC_D_UNC` is too high. - Lower it, or raise the measurement-noise floor of the chased sensor ([VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) for vision, [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) for GPS). - -After every change, `vte_aid_*.innovation` should look like zero-mean white noise rather than ramping with one sign or carrying a persistent offset. - -### Tuning the Bias State - -Once the bias is activated, two parameters govern how aggressively the filter lets `vte_position.bias` follow new observations: - -- [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) (unit: $m^2/s$, default $0.001$) is the random-walk **process-noise spectral density** of the bias state. - Every predict step adds `VTE_BIAS_UNC * dt` to the bias variance, so this parameter is the runtime knob governing how much the bias can change between observations once the filter is settled. -- [VTE_BIA_UNC_IN](../advanced_config/parameter_reference.md#VTE_BIA_UNC_IN) (unit: $m^2$, default $1.0$) is the **initial** bias variance applied at filter initialization and at bias activation. - Once fusion has run for a few seconds, the runtime covariance is dominated by `VTE_BIAS_UNC` and the measurement updates, so this parameter does **not** influence steady-state bias behaviour. - Keep it large so initialization can absorb initial misalignments. - -Applying the $\sigma(t) = \sqrt{\text{VTE\_BIAS\_UNC} \cdot t}$ rule, `VTE_BIAS_UNC = 0.01` $m^2/s$ does _not_ mean the bias is allowed to change linearly by 10 cm every second. Concretely: - -| Elapsed time | $\sigma_{bias}$ with `VTE_BIAS_UNC = 0.01` $m^2/s$ | $\sigma_{bias}$ with `VTE_BIAS_UNC = 0.001` $m^2/s$ (default) | $\sigma_{bias}$ with `VTE_BIAS_UNC = 0.0001` $m^2/s$ (min) | -| ------------ | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -| 1 s | $\sqrt{0.01}\approx 0.10$ m | $\sqrt{0.001}\approx 0.032$ m | $\sqrt{0.0001} = 0.01$ m | -| 10 s | $\sqrt{0.10}\approx 0.32$ m | $\sqrt{0.01}\approx 0.10$ m | $\sqrt{0.001}\approx 0.032$ m | -| 36 s | $\sqrt{0.36}= 0.60$ m | $\sqrt{0.036}\approx 0.19$ m | $\sqrt{0.0036}= 0.06$ m | -| 100 s | $\sqrt{1.0}= 1.00$ m | $\sqrt{0.1}\approx 0.32$ m | $\sqrt{0.01}= 0.10$ m | - -Pick `VTE_BIAS_UNC` such that $\sqrt{\text{VTE\_BIAS\_UNC} \cdot T}$ matches the realistic physical drift of the absolute reference (target GNSS or mission waypoint, relative to the vision frame) over a representative interval `T`. -For consumer GNSS this is typically a few centimetres over tens of seconds. -RTK is even slower. - -Symptoms and fixes: - -1. **`vte_position.bias` jumps to chase a single bad vision sample that just passed the [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) gate**: `VTE_BIAS_UNC` is too high. - The runtime bias variance has grown to the point where the Kalman gain on bias dominates the response to vision innovations, so the filter passes the inconsistency into the bias state. - Lower the value. -2. **`vte_position.bias` never settles after activation and keeps drifting on a stationary target**: `VTE_BIAS_UNC` is too low. - The bias variance is too tight to absorb legitimate slow corrections, so the filter pushes them into `pos_rel` or rejects them via the NIS gate. - Raise the value. -3. **Bias activates correctly but corrected GNSS drifts visibly during a vision dropout**: `VTE_BIAS_UNC` allows more drift than the real receiver, so the bias has been overfit to recent vision. - Combine a lower `VTE_BIAS_UNC` with a stricter [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) or a higher [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) floor to keep borderline vision samples out of the bias state. - -`VTE_BIAS_UNC` complements the outlier-rejection gate ([VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE)) and the vision-noise floor ([VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE)). -A well-tuned filter combines all three: a realistic bias variance rate, a sensible NIS threshold, and a vision-noise floor that matches the actual quality of the relative-position sensor. - -### Tuning the Yaw Rate - -The yaw filter uses [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC) as the spectral density of white yaw-acceleration noise that drives the yaw-rate state, with the same $\sqrt{\text{spectral density} \cdot t}$ semantics for yaw-rate growth. - -**Worked example.** With the default $0.004$ $rad^2/s^3$, the 1-sigma yaw-rate change the filter allows is about $3.6$ deg/s after $1$ s and $11.5$ deg/s after $10$ s, which is plenty of slack for a static target. -A value of $0.04$ allows an order of magnitude more (about $11.5$ deg/s already after one second), which is what makes the filter chase every yaw observation rather than holding the predicted heading. - -**Case study: yaw oscillation.** The [Orientation Filter plot](#plot-examples) further down was generated with [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE) at 4 deg (about 0.07 rad) and [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC) at $0.004$, both current defaults. -With earlier, more aggressive defaults (0.05 rad / 0.04) the filter jumped to follow every yaw observation, the controller chased the resulting setpoint changes, and the drone visibly oscillated. -The oscillation itself then degraded the next vision samples (motion blur and larger lever-arm effects make yaw harder to estimate), feeding the loop. -Trusting the process model more (smaller `VTE_YAW_ACC_UNC`) and the observations less (larger `VTE_EVA_NOISE`) breaks that loop: the state stays close to the underlying yaw trend, the drone holds steady, and the observations themselves become cleaner. -Lower these defaults only if the target is truly rotating or your camera is exceptionally accurate. - -### When the State Follows Per-Sample Jitter - -If the state in your logs follows the per-sample jitter rather than the underlying trend (the [Smoothing Through Bounded Noise](#smoothing-through-bounded-noise) plot illustrates the healthy case), three knobs make the output smoother: - -1. **Raise the observation-noise floors** [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) (vision), [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE) (vision yaw), or [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) (GNSS) so the effective per-sample variance matches the actual sensor noise. - This is the right fix whenever the sensor under-reports its own accuracy: a larger $R$ shrinks the Kalman gain, so each sample moves the state less. - The clamping mechanism and typical mis-tunes are detailed in [Between observation sources](#between-observation-sources) above. -2. **Reduce the prediction process noise** [VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC), and for moving targets [VTE_ACC_T_UNC](../advanced_config/parameter_reference.md#VTE_ACC_T_UNC), only when the predicted state is already unbiased and the problem is excessive responsiveness to zero-mean jitter. - A smaller predicted variance $P$ also shrinks the Kalman gain. - If GNSS bias drift is contributing to the jitter, the same applies to [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC); see [Tuning the bias state](#tuning-the-bias-state) for worked examples. - Set the prediction noise too low and the filter lags real motion or rejects legitimate dynamics. -3. **Tighten the chi-squared gate** [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) (or [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE)) only if the noise is a mix of in-distribution jitter and occasional outliers. - Against uniformly bounded noise every sample stays inside the gate, so lowering the threshold just throws good data away. - This knob targets outliers, not jitter. - -The underlying trade-off is the process-noise versus measurement-noise balance: each step toward a smoother state is also a step toward slower response to legitimate motion. -Watch `vte_aid_*.innovation` after retuning. -A healthy filter still has zero-mean white-noise innovations; a growing mean or persistent offset signals that the response has been damped too much. - -## Time Alignment - -Vision and GNSS observations can arrive delayed due to transport and processing latency. -The position and orientation filters therefore support an **Out-of-Sequence Measurements (OOSM)** approximation which uses a **history-consistent projected correction** strategy. - -### OOSM Implementation - -Each filter maintains a fixed-size ring buffer of recent state snapshots spanning roughly the last half second of operation (25 samples ≈ 0.5 s at 50 Hz). -For the position filter the snapshot stores $(t, x, P, a^{uav})$; for the orientation filter it stores $(t, x, P)$. -When a delayed scalar measurement arrives with timestamp $t_{meas}$: - -1. **Retrieve**: fetch the closest: - $(x_{old}, P_{old}, a^{uav}_{old})$ before $t_{meas}$. - - $$ - t_{old} ≤ t_{meas} - $$ - -2. **Predict**: use the KF model to predict the state $(x_{meas}, P_{meas})$ using $\Delta t = t_{meas} - t_{old}$ (for the orientation filter the control-input term is omitted). - - $$ - x_{meas} = \Phi(\Delta t) x_{old} + G a^{uav}_{old} \\ - P_{meas} = \Phi(\Delta t)P_{old}\Phi^T(\Delta t) + Q_d(\Delta t) - $$ - -3. **Innovate**: compute the innovation $y$ and innovation variance $S$: - - $$ - y = z - Hx_{meas} \\ - S = H P_{meas} H^T + R - $$ - -4. **Correct**: compute the optimal correction vector: - - $$ - \delta x_{meas} = Ky \\ \thickspace K = P_{meas} H^T S^{-1} - $$ - -5. **Project**: project this correction forward with the state transition matrix $\Phi(\Delta t)$: - - $$ - \delta x(t) = \Phi(t - t_{meas})\thinspace \delta x_{meas} = \Phi(t - t_{meas})\thinspace Ky - $$ - -6. **Apply**: apply the projected correction to the current live state _and_ to every stored history sample $i$ that occurred after $t_{meas}$, i.e. $t_{i} > t_{meas}$. - The corrected posterior at $t_{meas}$ is also written back into the history (replacing or inserting a sample at that timestamp), so a second delayed measurement in the same interval replays from the already-corrected state instead of from the stale pre-measurement floor. - - $$ - K_{i} = \Phi(t_{i} - t_{meas})K \\ - x_{i} = x_{i} + K_{i}y \\ - P_{i} = P_{i} - K_{i}SK_{i}^T - $$ - -Updating the history buffer keeps it self-consistent for subsequent delayed measurements and provides the practical benefits of a lag-smoother while remaining deterministic (fixed buffer, bounded runtime) and avoiding a full backward smoother over the timeline. - -The state prediction includes the control input, $x_{k+1} = \Phi x_k + G u_k$. -When projecting the correction forward, the $Gu_{k}$ term does not need to be used explicitly because it cancels out: - -$$ -(x'_{k+1} - x_{k+1}) = (\Phi x'_k + G u_k) - (\Phi x_k + G u_k) \\ -\Delta x_{k+1} = \Phi (x'_k - x_k) = \Phi \Delta x_k -$$ - -### OOSM Approximation Assumptions - -In Algorithm I of _Zhang et al. Optimal Update with Out-of-Sequence Measurements_, the optimal gain for an Out-of-Sequence Measurement (OOSM) depends on $U_{k,d}$, which represents the cross-covariance between the current state $x_k$ and the past-state error $\tilde{x}_{d|k}$: - -$$ -\hat{x}_{k|k,d} = \hat{x}_{k|k} + K_d (z_d - H_d \hat{x}_{d|k}) \\ -K_d = U_{k,d} H_d^T S_d^{-1} -$$ - -With the optimal recursion Eq. 5: - -$$ -U_{n+1,d} = (I - K_{n+1} H_{n+1})F_{n+1,n} U_{n,d} -$$ - -$F_{n+1,n}$ propagates the correlation forward in time based on system dynamics. -$(I - K_{n+1}H_{n+1})$ reduces the correlation based on the information gained from intermediate measurements processed between $t_d$ and $t_k$. - -**First approximation: projected gain** - -To avoid the computational complexity and storage required to track every intermediate gain $K_n$ and measurement matrix $H_n$, we approximate the cross-covariance term. -We assume that the reduction in correlation due to intermediate updates is negligible for the purpose of the OOSM projection. -Mathematically, this assumes the update factor is close to the identity matrix: - -$$ -(I - K_{n}H_{n}) \approx I -$$ - -Under this assumption, the recursion in Eq. (5) simplifies to a pure dynamic propagation: - -$$U_{n+1,d} \approx F_{n+1,n} U_{n,d}$$ - -By iterating this simplified recursion from the measurement time $d$ to the current time $k$, and recognizing that the initial cross-covariance $U_{d,d}$ corresponds to the prediction covariance $P_{d|d-1}$ (or $P_{d|k-l}$ in the paper's notation Eq. 6), we obtain: - -$$U_{k,d} \approx F_{k,d} U_{d,d} \approx \Phi_{k,d} P_{d|d-1}$$ - -Substituting this approximation back into the gain formula: -$$K_d \approx (\Phi_{k,d} P_{d|d-1}) H_d^T S_d^{-1}$$ - -Since the standard Kalman gain at time $d$ is $K = P_{d|d-1} H_d^T S_d^{-1}$, the OOSM gain simplifies to: - -$$K_d \approx \Phi_{k,d} K$$ - -Effectively, this justifies the "Project" step in the implementation: we calculate the correction vector using the snapshot at $t_{meas}$ and propagate it forward using only the state transition matrix $\Phi(\Delta t)$ ($F_{k,d}$), ignoring the complex coupling effects of intermediate measurements described in the optimal recursion. -This reduces storage complexity from $O(N)$ matrices to a simple circular buffer of snapshots while ensuring the correction remains consistent with the system's motion model. - -**Second approximation: stored prediction instead of full smoothing** - -The paper's globally optimal update uses the smoothed past-state estimate and covariance. - -- Optimal innovation: The innovation in Eq. (3) is defined as - $$\tilde{z}_{d|k} = z_d - H_d \hat{x}_{d|k}$$ - This $\hat{x}_{d|k}$ is the estimate of the state at time $d$ conditioned on all measurements up to time $k$. -- Optimal covariance: The innovation covariance $S_d$ in Eq. (4) uses $P_{d|k}$, which is the error covariance at time $d$ given all data up to $k$. - -The approximation: The current implementation calculates the innovation using a snapshot retrieved from history ($x_{old}$) and predicted to the measurement time ($x_{meas}$). -Since this snapshot was saved before the subsequent measurements ($z_{d+1} \dots z_k$) were processed, it only contains information available up to time $d$. - -- State approximation: The predicted state $\hat{x}_{d|d^-}$ (or filtered state $\hat{x}_{d|d}$) is substituted for the smoothed state $\hat{x}_{d|k}$. - $$\hat{x}_{d|k} \approx \hat{x}_{d|d^-}$$ -- Covariance approximation: Similarly, $S$ is calculated using $P_{meas}$ (which is $P_{d|d^-}$), substituting the prediction covariance for the smoothed covariance. - $$P_{d|k} \approx P_{d|d^-}$$ - -Justification and impact: Calculating the exact $\hat{x}_{d|k}$ and $P_{d|k}$ would require the backward-smoothing machinery described in the paper (Section 4.1), which means storing all intermediate measurements and transition matrices. -By using the stored snapshot, the implementation avoids this storage overhead. -This approximation assumes that the measurements received between $t_{meas}$ and $t_{now}$ ($z_{d+1} \dots z_k$) would not have significantly altered the estimate of the state at $t_{meas}$ had they been available. - -## Dynamic Model Process Noise - -### Process Noise Computation +#### Process Noise Computation {#process-noise-computation} The deterministic prediction uses the measured inputs to advance the mean state. Process noise describes how wrong that prediction might be. @@ -409,16 +245,16 @@ $$ де: -- `r` is target position relative to the vehicle. -- `v^{uav}` is the vehicle velocity. -- `a^{uav}_{meas}` is the NED acceleration sample from `vte_input.acc_xyz`. -- `w_a` is unknown acceleration error on top of the measured acceleration. -- `w_b` is unknown GNSS/vision bias drift. +- $r$ is target position relative to the vehicle. +- $v^{uav}$ is the vehicle velocity. +- $a^{uav}_{meas}$ is the NED acceleration sample from `vte_input.acc_xyz`. +- $w_a$ is unknown acceleration error on top of the measured acceleration. +- $w_b$ is unknown GNSS/vision bias drift. -This is the key intuition: [VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC) is an acceleration-error spectral density, but that error is applied to the **derivative of velocity**. +The key intuition: [VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC) is an acceleration-error spectral density, but that error is applied to the **derivative of velocity**. Position is affected one integration later because relative position depends on vehicle velocity. -Over one prediction interval `dt`, a white acceleration-error spectral density `q_a = VTE_ACC_D_UNC` contributes: +Over one prediction interval $dt$, a white acceleration-error spectral density $q_a = $ `VTE_ACC_D_UNC` contributes: $$ \Delta\,\text{var}(v^{uav}) = q_a\,dt, \qquad \Delta\,\text{var}(r) = q_a\,\frac{dt^3}{3}, \qquad \Delta\,\text{cov}(r, v^{uav}) = -q_a\,\frac{dt^2}{2}, @@ -426,7 +262,7 @@ $$ The negative covariance term is expected: in the static-target model, a positive vehicle-velocity error makes the predicted relative position decrease. -The bias noise is simpler. +Bias noise is simpler. Bias does not feed any other state in the prediction model, so [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) contributes only: $$ @@ -450,10 +286,10 @@ Q = \int_{0}^{dt} G(\tau)\, Q_c\, G^T(\tau)\, d\tau, $$ but users normally do not need to manipulate this formula. -Practically, tune the spectral densities using the variance-rate interpretation in [Process noise: variance rates](#process-noise-variance-rates). -The yaw filter uses the same idea for [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC): yaw-acceleration error drives yaw-rate first, and yaw angle after one integration. +Practically, tune the spectral densities using the [variance-rate rule](#process-noise-variance-rates). +The yaw filter uses the same idea for [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC): yaw-acceleration error drives yaw rate first, and yaw angle after one integration. -### Assumptions +#### Assumptions - **Gaussian white noise.** Unknown physical disturbances are modelled as zero-mean continuous-time Gaussian white noise. For the UAV, that means unmeasured forces (gusts, motor jitter not captured by the accelerometer) enter as white acceleration noise on top of the measured input. @@ -463,6 +299,293 @@ The yaw filter uses the same idea for [VTE_YAW_ACC_UNC](../advanced_config/param - **Axis decoupling.** The three NED axes are integrated independently. Cross-axis aerodynamic coupling exists in reality, but ignoring it keeps each filter one-dimensional with negligible loss in precision-landing accuracy. +::: + +### When the State Follows Per-Sample Jitter + +If the state in your logs follows the per-sample jitter rather than the underlying trend (the [Smoothing Through Bounded Noise](#smoothing-through-bounded-noise) plot shows the healthy case), two knobs make the output smoother: + +1. **Raise the observation-noise floors** [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) (vision), [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE) (vision yaw), or [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) (GNSS) so the effective per-sample variance matches the actual sensor noise. + This is the right fix whenever the sensor under-reports its own accuracy. + See [Observation Noise Floors](#observation-noise-floors) for the clamping mechanism and typical mis-tunes. +2. **Reduce the prediction process noise** [VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC), and for moving targets [VTE_ACC_T_UNC](../advanced_config/parameter_reference.md#VTE_ACC_T_UNC), only when the predicted state is already unbiased and the problem is excessive responsiveness to zero-mean jitter. + If GNSS bias drift is contributing to the jitter, the same applies to [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC); see [Tuning the bias state](#tuning-the-bias-state) for worked examples. + Set the prediction noise too low and the filter lags real motion or rejects legitimate dynamics. + +:::info +**The chi-squared gate does not fix jitter.** +Tightening [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) or [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE) only helps when the noise mixes in-distribution jitter with occasional outliers. +Against uniformly bounded noise every sample stays inside the gate, so lowering the threshold just throws good data away. +See [Outlier Detection](#outlier-detection). +::: + +### Outlier Detection + +The chi-squared gate rejects measurements that disagree strongly with the filter prediction. +It uses `test_ratio = innov² / S` with $S = H P H^T + R$, where $R$ is the observation variance. +A sample is rejected when `test_ratio` exceeds [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) (or [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE) for yaw), and the rejection appears as `STATUS_REJECT_NIS` on the corresponding `vte_aid_*` topic. + +How the gate reacts depends on $R$: + +- If $R$ is under-reported, even small innovations exceed the gate and healthy data is rejected. +- If $R$ is over-reported, even corrupted samples pass the gate and pollute the state. + +When `STATUS_REJECT_NIS` fires repeatedly, the first fix is the noise floor, not the threshold. +Raise the floor on the rejecting sensor ([VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) / [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE) for vision, [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) / [VTE_GPS_V_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_V_NOISE) for GNSS) so it matches the actual sensor accuracy, and compare against `observation_variance` on the corresponding `vte_aid_*` topic. +Adjust [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) and [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE) only once the floors are realistic, and only when a mix of legitimate samples and occasional outliers remains. +The default 3.84 corresponds to a 5 % false-rejection rate: larger values are more permissive, smaller ones reject more aggressively. + +### Noise parameter tuning + +Open the worked examples below for per-parameter 1-sigma drift tables, starter values derived from log signals, and symptom/fix tables for the UAV-acceleration, bias, and yaw-rate process-noise parameters. + +:::details +Click to view parameter tuning examples + +#### Tuning the UAV Acceleration Process Noise + +[VTE_ACC_D_UNC](../advanced_config/parameter_reference.md#VTE_ACC_D_UNC) (unit: m²/s³, default 0.02) is the PSD of un-modelled UAV acceleration that drives the `vel_uav` state. +Larger values let measurements pull the state harder between updates. +Smaller values lock the state to the IMU-driven prediction. + +Applying the [variance-rate rule](#process-noise-variance-rates) to `VTE_ACC_D_UNC` gives the 1-sigma velocity allowance the filter accumulates between updates: + +| Elapsed time | `VTE_ACC_D_UNC = 0.02` (default) | `VTE_ACC_D_UNC = 0.2` | `VTE_ACC_D_UNC = 1.0` | +| --------------------- | --------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------ | +| 0.1 s | $\sqrt{0.002}\approx 0.045$ m/s | $\sqrt{0.02}\approx 0.14$ m/s | $\sqrt{0.1}\approx 0.32$ m/s | +| 1 s | $\sqrt{0.02}\approx 0.14$ m/s | $\sqrt{0.2}\approx 0.45$ m/s | $\sqrt{1.0} = 1.00$ m/s | +| 10 s | $\sqrt{0.2}\approx 0.45$ m/s | $\sqrt{2.0}\approx 1.41$ m/s | $\sqrt{10}\approx 3.16$ m/s | + +A useful first estimate comes from `vte_input.acc_xyz`: on a representative segment, read off the peak swing $\sigma_a$ and the time scale $\tau$ over which a given deviation persists, then use $\sigma_a^2 \cdot \tau$. +For example, a trace wandering between -0.05 and +0.10 m/s² in periods of order 1 s (so $\sigma_a \approx 0.075$ m/s² and $\tau \approx 1$ s) gives a starting value of about 0.006 m²/s³. + +Symptoms and fixes (visible on `vte_position.rel_pos` overlaid with the matching `vte_aid_*.observation`): + +| Symptom | Likely cause | Fix | +| ------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Staircase between fusions**: state drifts away from the observation between samples, snaps back at each fusion. | `VTE_ACC_D_UNC` too low. | Raise `VTE_ACC_D_UNC`. First check `vte_input.acc_xyz` for a persistent bias (attitude/gravity leakage, lever-arm error, real vehicle acceleration); raising process noise does not remove the bias itself. | +| **State copies the per-sample jitter** of the measurement, vehicle oscillates near the ground. | `VTE_ACC_D_UNC` too high. | Lower `VTE_ACC_D_UNC`, or raise the measurement-noise floor of the chased sensor ([VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) for vision, [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) for GPS). | + +After every change, `vte_aid_*.innovation` should look like zero-mean white noise rather than ramping with one sign or carrying a persistent offset. + +#### Tuning the Bias State {#tuning-the-bias-state} + +Once the bias is activated, two parameters govern how aggressively the filter lets `vte_position.bias` follow new observations: + +- [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) (unit: m²/s, default 0.001) is the random-walk PSD of the bias state. + It controls how much the bias can change between observations once the filter is settled. + See the [variance-rate rule](#process-noise-variance-rates). +- [VTE_BIA_UNC_IN](../advanced_config/parameter_reference.md#VTE_BIA_UNC_IN) (unit: m², default 1.0) is the **initial** bias variance applied at filter initialization and at bias activation. + Once fusion has run for a few seconds the runtime covariance is dominated by `VTE_BIAS_UNC`, so this parameter does **not** influence steady-state behaviour. + Keep it large so initialization can absorb initial misalignments. + +The 1-sigma bias change is non-linear in time: `VTE_BIAS_UNC = 0.01` m²/s does _not_ mean the bias can move 10 cm per second. + +| Elapsed time | $\sigma_{bias}$ with `VTE_BIAS_UNC = 0.01` m²/s | $\sigma_{bias}$ with `VTE_BIAS_UNC = 0.001` m²/s (default) | $\sigma_{bias}$ with `VTE_BIAS_UNC = 0.0001` m²/s (min) | +| ------------ | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| 1 s | $\sqrt{0.01}\approx 0.10$ m | $\sqrt{0.001}\approx 0.032$ m | $\sqrt{0.0001} = 0.01$ m | +| 10 s | $\sqrt{0.10}\approx 0.32$ m | $\sqrt{0.01}\approx 0.10$ m | $\sqrt{0.001}\approx 0.032$ m | +| 36 s | $\sqrt{0.36}= 0.60$ m | $\sqrt{0.036}\approx 0.19$ m | $\sqrt{0.0036}= 0.06$ m | +| 100 s | $\sqrt{1.0}= 1.00$ m | $\sqrt{0.1}\approx 0.32$ m | $\sqrt{0.01}= 0.10$ m | + +Pick `VTE_BIAS_UNC` so that the 1-sigma drift over a representative interval matches the realistic physical drift of the absolute reference (target GNSS or mission waypoint, relative to the vision frame). +For consumer GNSS this is typically a few centimetres over tens of seconds. +RTK is even slower. + +Symptoms and fixes: + +| Symptom | Likely cause | Fix | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`vte_position.bias` jumps to chase a single bad vision sample** that just passed the [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) gate. | `VTE_BIAS_UNC` too high; bias variance dominates the response to vision innovations. | Lower `VTE_BIAS_UNC`. | +| **`vte_position.bias` never settles** after activation and keeps drifting on a stationary target. | `VTE_BIAS_UNC` too low; bias variance is too tight to absorb legitimate slow corrections. | Raise `VTE_BIAS_UNC`. | +| Bias activates correctly but corrected GNSS drifts visibly during a vision dropout. | `VTE_BIAS_UNC` allows more drift than the real receiver; bias overfit to recent vision. | Lower `VTE_BIAS_UNC`. Combine with a stricter [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) or a higher [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) floor to keep borderline vision samples out of the bias state. | + +`VTE_BIAS_UNC` complements the outlier-rejection gate ([VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE)) and the vision-noise floor ([VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE)). +A well-tuned filter combines all three: a realistic bias variance rate, a sensible NIS threshold, and a vision-noise floor that matches the actual quality of the relative-position sensor. + +#### Tuning the Yaw Rate + +The yaw filter uses [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC) as the spectral density of white yaw-acceleration noise that drives the yaw-rate state. +The same [variance-rate rule](#process-noise-variance-rates) applies to yaw-rate growth. + +**Worked example.** With the default 0.004 rad²/s³, the 1-sigma yaw-rate change the filter allows is about 3.6 deg/s after 1 s and 11.5 deg/s after 10 s, which is plenty of slack for a static target. +A value of 0.04 allows an order of magnitude more (about 11.5 deg/s already after one second), which makes the filter chase every yaw observation rather than hold the predicted heading. + +Lower [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC) only if your camera is more accurate than the default values. +If the yaw state ends up oscillating, the [Orientation Filter case study](#orientation-filter-case-study-yaw-oscillation) walks through how overly aggressive yaw tuning amplifies vision noise into a feedback loop, and how trusting the process model more breaks that loop. + +::: + +## Time Alignment + +Vision and GNSS observations can arrive delayed due to transport and processing latency. +The position and orientation filters therefore support an **Out-of-Sequence Measurements (OOSM)** approximation which uses a **history-consistent projected correction** strategy. + +Open the algorithm below if you need the exact six-step recipe (retrieve, predict, innovate, correct, project, apply) used to fuse a delayed sample against the historical state. + + + +:::details +Click to view OOSM algorithm steps + +Each filter maintains a fixed-size ring buffer of recent state snapshots spanning roughly the last half second of operation (25 samples ≈ 0.5 s at 50 Hz). +For the position filter the snapshot stores $(t, x, P, a^{uav})$; for the orientation filter it stores $(t, x, P)$. +When a delayed scalar measurement arrives with timestamp $t_{meas}$: + +1. **Retrieve**: fetch the closest: + $(x_{old}, P_{old}, a^{uav}_{old})$ before $t_{meas}$. + + $$ + t_{old} ≤ t_{meas} + $$ + +2. **Predict**: use the KF model to predict the state $(x_{meas}, P_{meas})$ using $\Delta t = t_{meas} - t_{old}$ (for the orientation filter the control-input term is omitted). + + $$ + \begin{aligned} + x_{meas} &= \Phi(\Delta t)\,x_{old} + G\,a^{uav}_{old} \\ + P_{meas} &= \Phi(\Delta t)\,P_{old}\,\Phi^T(\Delta t) + Q_d(\Delta t) + \end{aligned} + $$ + +3. **Innovate**: compute the innovation $y$ and innovation variance $S$: + + $$ + \begin{aligned} + y &= z - H\,x_{meas} \\ + S &= H\,P_{meas}\,H^T + R + \end{aligned} + $$ + +4. **Correct**: compute the optimal correction vector: + + $$ + \begin{aligned} + \delta x_{meas} &= K\,y \\ + K &= P_{meas}\,H^T\,S^{-1} + \end{aligned} + $$ + +5. **Project**: project this correction forward with the state transition matrix $\Phi(\Delta t)$: + + $$ + \delta x(t) = \Phi(t - t_{meas})\thinspace \delta x_{meas} = \Phi(t - t_{meas})\thinspace Ky + $$ + +6. **Apply**: apply the projected correction to the current live state _and_ to every stored history sample $i$ that occurred after $t_{meas}$, i.e. $t_{i} > t_{meas}$. + The corrected posterior at $t_{meas}$ is also written back into the history (replacing or inserting a sample at that timestamp), so a second delayed measurement in the same interval replays from the already-corrected state instead of from the stale pre-measurement floor. + + $$ + \begin{aligned} + K_{i} &= \Phi(t_{i} - t_{meas})\,K \\ + x_{i} &= x_{i} + K_{i}\,y \\ + P_{i} &= P_{i} - K_{i}\,S\,K_{i}^T + \end{aligned} + $$ + +Updating the history buffer keeps it self-consistent for subsequent delayed measurements. +This gives the practical benefits of a lag-smoother while staying deterministic (fixed buffer, bounded runtime), without running a full backward smoother over the timeline. + +The state prediction includes the control input, $x_{k+1} = \Phi x_k + G u_k$. +When projecting the correction forward, the $Gu_{k}$ term does not need to be used explicitly because it cancels out: + +$$ +\begin{aligned} +(x'_{k+1} - x_{k+1}) &= (\Phi\,x'_k + G\,u_k) - (\Phi\,x_k + G\,u_k) \\ +\Delta x_{k+1} &= \Phi\,(x'_k - x_k) = \Phi\,\Delta x_k +\end{aligned} +$$ + +::: + +### OOSM Approximation Assumptions + +Two approximations make the algorithm above tractable on an autopilot. + +- First, the OOSM gain is treated as the standard Kalman gain at the measurement time, propagated forward by the state transition matrix. +- Second, the past-state estimate is taken from the stored snapshot rather than from a full backward smoother over all intermediate measurements. + +:::details +Click to view OOSM mathematical proofs + +The notation follows _Zhang et al., Optimal Update with Out-of-Sequence Measurements_. + +In Algorithm I of the paper, the optimal gain for an Out-of-Sequence Measurement depends on $U_{k,d}$, the cross-covariance between the current state $x_k$ and the past-state error $\tilde{x}_{d|k}$: + +$$ +\begin{aligned} +\hat{x}_{k|k,d} &= \hat{x}_{k|k} + K_d\,(z_d - H_d\,\hat{x}_{d|k}) \\ +K_d &= U_{k,d}\,H_d^T\,S_d^{-1} +\end{aligned} +$$ + +With the optimal recursion (Eq. 5): + +$$ +U_{n+1,d} = (I - K_{n+1} H_{n+1})\,F_{n+1,n}\,U_{n,d} +$$ + +$F_{n+1,n}$ propagates the correlation forward in time based on system dynamics. +$(I - K_{n+1}H_{n+1})$ reduces the correlation based on the information gained from intermediate measurements processed between $t_d$ and $t_k$. + +#### First approximation: projected gain + +To avoid the computational complexity and storage required to track every intermediate gain $K_n$ and measurement matrix $H_n$, the implementation approximates the cross-covariance term. +The reduction in correlation due to intermediate updates is assumed negligible for the purpose of the OOSM projection. +Mathematically: + +$$ +(I - K_{n}H_{n}) \approx I +$$ + +Under this assumption, the recursion in Eq. (5) simplifies to pure dynamic propagation: + +$$U_{n+1,d} \approx F_{n+1,n}\,U_{n,d}$$ + +Iterating this from the measurement time $d$ to the current time $k$, and recognising that the initial cross-covariance $U_{d,d}$ corresponds to the prediction covariance $P_{d|d-1}$ (or $P_{d|k-l}$ in the paper's notation, Eq. 6): + +$$U_{k,d} \approx F_{k,d}\,U_{d,d} \approx \Phi_{k,d}\,P_{d|d-1}$$ + +Substituting back into the gain formula: + +$$K_d \approx (\Phi_{k,d}\,P_{d|d-1})\,H_d^T\,S_d^{-1}$$ + +Since the standard Kalman gain at time $d$ is $K = P_{d|d-1}\,H_d^T\,S_d^{-1}$, the OOSM gain simplifies to: + +$$K_d \approx \Phi_{k,d}\,K$$ + +This justifies the "Project" step in the implementation: the correction vector is computed from the snapshot at $t_{meas}$ and propagated forward by the state transition matrix $\Phi(\Delta t)$ ($F_{k,d}$), ignoring the coupling from intermediate measurements that the optimal recursion accounts for. +The storage cost drops from $O(N)$ matrices to a fixed-size circular buffer of snapshots, and the correction stays consistent with the system's motion model. + +#### Second approximation: stored prediction instead of full smoothing + +The paper's globally optimal update uses the smoothed past-state estimate and covariance. + +- **Optimal innovation.** The innovation in Eq. (3) is + + $$\tilde{z}_{d|k} = z_d - H_d\,\hat{x}_{d|k}$$ + + where $\hat{x}_{d|k}$ is the estimate of the state at time $d$ conditioned on all measurements up to time $k$. + +- **Optimal covariance.** The innovation covariance $S_d$ in Eq. (4) uses $P_{d|k}$, the error covariance at time $d$ given all data up to $k$. + +The current implementation calculates the innovation using a snapshot retrieved from history ($x_{old}$) and predicted to the measurement time ($x_{meas}$). +Since this snapshot was saved before the subsequent measurements $z_{d+1}, \dots, z_k$ were processed, it only contains information available up to time $d$. + +- **State approximation.** The predicted state $\hat{x}_{d|d^-}$ (or filtered state $\hat{x}_{d|d}$) is substituted for the smoothed state: + + $$\hat{x}_{d|k} \approx \hat{x}_{d|d^-}$$ + +- **Covariance approximation.** Similarly, $S$ is calculated using $P_{meas}$ (which is $P_{d|d^-}$), substituting the prediction covariance for the smoothed covariance: + + $$P_{d|k} \approx P_{d|d^-}$$ + +Calculating the exact $\hat{x}_{d|k}$ and $P_{d|k}$ would require the backward-smoothing machinery described in Section 4.1 of the paper, which means storing every intermediate measurement and transition matrix. +The stored snapshot avoids that overhead. +The approximation assumes that the measurements received between $t_{meas}$ and $t_{now}$ would not have significantly altered the estimate at $t_{meas}$ had they been available. + +::: + ## Moving-target Mode (experimental) :::warning @@ -498,7 +621,7 @@ Two prebuilt targets are available: ### Target GNSS Velocity Fusion With moving-target builds, bit 4 of [`VTE_AID_MASK`](../advanced_features/vision_target_estimator.md#sensor-fusion-selection) enables fusion of the target GNSS velocity from the `target_gnss` topic with observation model $z = v^{t}$. -This is the only measurement that directly informs the target-velocity state. +This is the only measurement that directly informs the target-velocity state; see [Filter Observability](#filter-observability) for why this matters. ### Precision-Landing Projection @@ -515,30 +638,33 @@ The two bounds play different roles: This matters because the horizontal velocity at contact should match the target's, not drop to zero. Tuning rule of thumb. -For an expected maximum target speed $|v^t|$ and a chosen [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD), pick `PLD_MOVING_T_MAX` so the maximum lookahead offset stays inside the acceptance radius: +For an expected maximum target speed $|v^t|$ and an acceptance radius $r_{acc}$ ([PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD)), pick [PLD_MOVING_T_MAX](../advanced_config/parameter_reference.md#PLD_MOVING_T_MAX) so the maximum lookahead offset stays inside the acceptance radius: $$ -\text{PLD\_MOVING\_T\_MAX} \lesssim \frac{\text{PLD\_HACC\_RAD}}{|v^t|}. +t_{max} \lesssim \frac{r_{acc}}{|v^t|}. $$ Worked example. -With a target at 0.5 m/s and [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) at the 0.2 m default, the bound is $\text{T\_MAX} \lesssim 0.4$ s, which is short enough that the lookahead barely leads the target. -Raising [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) to 1 m allows $\text{T\_MAX} \lesssim 2$ s, which is a much more useful lead. -As a rule, moving-target setups need [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) and `PLD_MOVING_T_MAX` raised together. +With a target at 0.5 m/s and [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) at the 0.2 m default, the bound is $t_{max} \lesssim 0.4$ s, which is short enough that the lookahead barely leads the target. +Raising [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) to 1 m allows $t_{max} \lesssim 2$ s, which is a much more useful lead. +As a rule, moving-target setups need [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) and [PLD_MOVING_T_MAX](../advanced_config/parameter_reference.md#PLD_MOVING_T_MAX) raised together. -For `PLD_MOVING_T_MIN`, pick a value at least as large as the touchdown altitude window divided by the descent speed: +For [PLD_MOVING_T_MIN](../advanced_config/parameter_reference.md#PLD_MOVING_T_MIN), pick a value at least as large as the touchdown altitude window divided by the descent speed: $$ -\text{PLD\_MOVING\_T\_MIN} \gtrsim \frac{h_{touchdown}}{|v_{descent}|}. +t_{min} \gtrsim \frac{h_{touchdown}}{|v_{descent}|}. $$ -For a vehicle that descends at 0.5 m/s with the last 0.1 m being the touchdown window, $\text{T\_MIN} \gtrsim 0.2$ s. +For a vehicle that descends at 0.5 m/s with the last 0.1 m being the touchdown window, $t_{min} \gtrsim 0.2$ s. This keeps the lookahead positive at touchdown so the vehicle keeps tracking the moving pad through contact. ### Gazebo Simulation -The moving-target SITL setup reuses the same `land_pad.sdf` model as the static configuration. -Build with `CONFIG_VTEST_MOVING=y` so the estimator tracks the target velocity, then edit `Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/land_pad/land_pad.sdf` to enable pad motion through the `libgazebo_random_velocity_plugin.so` plugin: +The moving-target SITL setup reuses the same `land_pad.sdf` model as the static configuration, so the upstream pipeline (camera, marker plugin, GPS plugin, mavlink bridge) is identical: see [SITL Simulation Pipeline](#sitl-simulation-pipeline) for the static-target walkthrough. +Build with `CONFIG_VTEST_MOVING=y` so the estimator tracks the target velocity, then edit `Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/land_pad/land_pad.sdf` to enable pad motion through the `libgazebo_random_velocity_plugin.so` plugin. + +:::details +Click here for details on how to configure pad motion - `0.5 0 0` applies a constant velocity along the pad's X axis at simulation start. - `0.5` scales the magnitude of newly drawn random velocities. @@ -547,10 +673,13 @@ Build with `CONFIG_VTEST_MOVING=y` so the estimator tracks the target velocity, - ``, ``, ``, `` clamp the velocity range per axis. Keep `00` so the pad stays on the ground. +::: + Tips for a stable touchdown on a moving target in SITL: - **Enable target GNSS position and target GNSS velocity aiding** ([VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bits 0 and 4). - The target GNSS velocity is the only direct observation of $v^t$; without it the target-velocity state is poorly observed, the lookahead is noisy, and touchdown accuracy suffers. + The target GNSS velocity is the only direct observation of $v^t$. + Without it the target-velocity state is poorly observed, the lookahead is noisy, and touchdown accuracy suffers. - **Raise [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD)** (try 2 to 3 m to start). With the 0.2 m default, the lookahead-projected setpoint will sit outside the acceptance radius at altitude even for slow targets, blocking the transition to descent. - **Make the pad visually larger** so vision detects it from a higher altitude (raise the visual box in `land_pad.sdf` to `1.5 1.5 0.01`). @@ -558,11 +687,13 @@ Tips for a stable touchdown on a moving target in SITL: Confirm that the moving-mode filter is well behaved on a static target, then introduce motion. This separates filter problems from precision-landing-projection problems. -## Log Analysis and Expected Plots + -This section provides an overview of the topics and fields that matter during log review: the published [estimator outputs](#estimator-outputs) and the upstream [input feeds](#main-input-feeds). -Then log analysis guidance is provided in [What to look for in logs](#what-to-look-for-in-logs) and the [troubleshooting checklist](#troubleshooting-checklist). -The [plot examples](#plot-examples) at the end illustrate the expected convergence behaviour. +## Log Analysis & Troubleshooting + +This section covers the topics and fields that matter during log review: the published [estimator outputs](#estimator-outputs), the upstream [input feeds](#main-input-feeds), and what to look for in [What to look for in logs](#what-to-look-for-in-logs). +The [troubleshooting checklist](#troubleshooting-checklist) maps common symptoms to their typical causes. +For example plots of what a healthy and a degraded filter look like, see [Expected Plot Dashboards](#expected-plot-dashboards). ### Estimator Outputs @@ -580,7 +711,10 @@ The [plot examples](#plot-examples) at the end illustrate the expected convergen ### Aid-Source Diagnostics Every fusion attempt is logged on the corresponding `vte_aid_*` topic. -The `fusion_status` field records which fusion branch the filter took: +The `fusion_status` field records which fusion branch the filter. + +:::details +Click to view details on how to interpret the fusion status | Значення | Status | Значення | Typical action | | -------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -594,9 +728,12 @@ The `fusion_status` field records which fusion branch the filter took: | 7 | `STATUS_REJECT_STALE` | Filter history was reset because no prediction had run for longer than the buffer span. | Expected after long pauses; otherwise investigate scheduler stalls. | | 8 | `STATUS_REJECT_EMPTY` | History buffer not yet populated when the measurement arrived. | Expected on the first cycles after the estimator starts; persistent occurrences indicate a startup race. | +::: + Two additional fields make latency tractable without manual timestamp arithmetic: -- `time_since_meas_ms = (time_last_predict - timestamp_sample) * 1e-3`. Negative values mean the measurement is timestamped after the latest prediction (i.e. the filter has not caught up yet). +- `time_since_meas_ms = (time_last_predict - timestamp_sample) * 1e-3`. + Negative values mean the measurement is timestamped after the latest prediction (i.e. the filter has not caught up yet). - `history_steps` is non-zero only for `STATUS_FUSED_OOSM` and tells you how many 20 ms snapshots were replayed when projecting the correction forward. ### Main Input Feeds @@ -607,7 +744,12 @@ Two additional fields make latency tractable without manual timestamp arithmetic - Mission position: cached from `navigator_mission_item`, with `position_setpoint_triplet` as a fallback when a valid LAND setpoint is available there first - `vehicle_local_position` and `vehicle_attitude` (used for frame transforms and timeout checks) -### What to Look For in Logs +When analysing a log, the walkthrough below lists the seven cross-checks to run from estimator output back to inputs (observations, innovations, fusion status, time alignment, coordinate transforms, prediction inputs). + + + +:::details +Click to view the log analysis list 1. **Estimator output vs. observations**: In all axis directions, overlay the estimator outputs position `vte_position.rel_pos[0]`, `vte_orientation.yaw` with measurement observations `vte_aid_*.observation[0]` (e.g. `vte_aid_fiducial_marker.observation[0]` or the relevant GNSS observation). The traces should converge after a short transient. @@ -618,21 +760,23 @@ Two additional fields make latency tractable without manual timestamp arithmetic Large swings in the raw bias or a persistently large `delta_norm` point to unstable early vision data or GNSS/vision time-alignment problems. If vision is active first, you should normally see immediate bias activation instead of an averaging phase. 3. **Innovation behaviour**: `vte_aid_*.innovation` (e.g. `vte_aid_fiducial_marker.innovation`) should be centred at zero and resemble white noise. - Recall that the innovation is defined as the difference between the state prediction and the measurement observation of the state. - It follows that the drifting innovations can come from: - - State prediction errors: - - check the estimators state outputs which correspond to the prediction of the state when no measurements are fused - - check `vte_input` (accelerations, attitude) - - check the frequency of the prediction `dt` - - State update errors: - - errors in the measurement implementation, compare the raw sensor input (e.g. `fiducial_marker_pos_report`) with the processed observation (e.g. `vte_aid_fiducial_marker`) - - time delays between the attitude of the drone and the observation (causing biases in the frame transform from sensor to NED) - - Incorrect noise assumptions + The innovation is the gap between the measurement and the value the filter predicted for it, so a drifting innovation points to one of two failure modes: + - **State prediction errors.** Check that: + - the estimator's state outputs follow the expected trajectory when no measurements are fused + - `vte_input` (accelerations, attitude) matches the upstream feeds + - the prediction interval `dt` is consistent with the configured rate + - **State update errors.** Check that: + - the measurement handler is correct (compare the raw sensor input, e.g. `fiducial_marker_pos_report`, with the processed observation, e.g. `vte_aid_fiducial_marker`) + - there are no time delays between vehicle attitude and the observation (these cause biases in the frame transform from sensor to NED) + - the noise assumptions on the sensor are realistic 4. **Measurement acceptance**: Inspect `fusion_status` alongside `test_ratio`. - `STATUS_FUSED_CURRENT` and `STATUS_FUSED_OOSM` are healthy; the various `STATUS_REJECT_*` codes each point to a different root cause (NIS gate, covariance, latency, time sync, scheduler stall). + `STATUS_FUSED_CURRENT` and `STATUS_FUSED_OOSM` are healthy. + The various `STATUS_REJECT_*` codes each point to a different root cause (NIS gate, covariance, latency, time sync, scheduler stall). See [Aid-source diagnostics](#aid-source-diagnostics) for the action mapped to each code. - Remember that gaps longer than [VTE_TGT_TOUT](../advanced_config/parameter_reference.md#VTE_TGT_TOUT) clear the validity flags, and exceeding [VTE_BTOUT](../advanced_config/parameter_reference.md#VTE_BTOUT) resets the affected estimator; it restarts as soon as the task remains active and enabled fusion input is available. -5. **Time alignment**: Use `time_since_meas_ms` on the `vte_aid_*` topic; it encodes `time_last_predict - timestamp_sample` in milliseconds. + Remember that gaps longer than [VTE_TGT_TOUT](../advanced_config/parameter_reference.md#VTE_TGT_TOUT) clear the validity flags, and exceeding [VTE_BTOUT](../advanced_config/parameter_reference.md#VTE_BTOUT) resets the affected estimator. + It restarts as soon as the task remains active and enabled fusion input is available. +5. **Time alignment**: Use `time_since_meas_ms` on the `vte_aid_*` topic. + It encodes the latency between the latest filter prediction and the measurement timestamp, in milliseconds. For an immediately fused source it should stay within a few times the 20 ms estimator loop period. Larger steady-state offsets, or a growing `history_steps` on `STATUS_FUSED_OOSM`, indicate delayed delivery or a missing time synchronisation step. 6. **Coordinate transforms**: Plot the raw measurement (e.g. `fiducial_marker_pos_report.rel_pos[0]`) together with its processed observation `vte_aid_fiducial_marker.observation`. @@ -640,6 +784,8 @@ Two additional fields make latency tractable without manual timestamp arithmetic 7. **Prediction inputs**: Use `vte_input` to track the downsampled acceleration and quaternion. Compare them to `vehicle_attitude.q` and `vehicle_acceleration` to ensure the estimator sees the expected attitude, especially when diagnosing timestamp mismatches. +::: + ### Troubleshooting Checklist Start by confirming that the estimator is running (`vision_target_estimator status`) and that the relevant `vte_aid_*` topic is present in the log. @@ -651,19 +797,21 @@ When the debug bit is set the estimator always runs, making it ideal for bench t Enable **debug prints** (`PX4_DEBUG`). ::: -| Symptom | Likely cause | Remedy | -| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Vehicle misses the pad or ignores target yaw | Mission land waypoint not set to precision mode or yaw alignment disabled | In QGroundControl set the land waypoint `Precision landing` field (or `MAV_CMD_NAV_LAND` `param2`) to Opportunistic/Required as described in [Precision landing missions](../advanced_features/precland.md#mission), and enable [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN). In logs verify that `trajectory_setpoint.x/y` converge to `landing_target_pose.x_abs/y_abs` and that `trajectory_setpoint.yaw` follows `vte_orientation.yaw`. | -| Frequent innovation rejections | Incorrect noise floors, miscalibrated measurement variance, or timestamp skew | The NIS gate uses `test_ratio = innov^2 / S` with `S = H P H^T + R`, where `R` is the observation variance. If `R` is under-reported (measurement noise floor set too low), even small innovations exceed the gate and healthy data is rejected; if `R` is over-reported, even corrupted samples pass the gate and pollute the state. Read `fusion_status` to find which branch fires. `STATUS_REJECT_NIS` points at the noise floors and the [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) / [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE) thresholds: for vision raise [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) or [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE), for GNSS check [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) and [VTE_GPS_V_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_V_NOISE), and compare with the `observation_variance` field on the corresponding `vte_aid_*` topic. `STATUS_REJECT_TOO_OLD` / `STATUS_REJECT_TOO_NEW` point at latency or time-sync; `time_since_meas_ms` on the same `vte_aid_*` topic gives the latency directly. | -| Bias does not converge | No secondary position source, or the GNSS/vision agreement check is too strict for the available vision quality | Ensure vision fusion is enabled so the filter can observe GNSS bias. If GNSS is active before vision and the bias stays near zero, inspect the first GNSS/vision agreement window and tune [VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR) / [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT). If vision is active first, expect the bias to appear on the first overlapping GNSS+vision sample rather than after an averaging phase. | -| Orientation estimate drifts | Missing yaw measurements or low NIS gate | Enable [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) and ensure vision yaw data is present. Increase [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE) if legitimate data is being rejected. | -| `rel_pos_valid` toggles during descent | Position measurements arriving too slowly | Increase [VTE_TGT_TOUT](../advanced_config/parameter_reference.md#VTE_TGT_TOUT) or improve the measurement rate so updates remain inside [VTE_M_REC_TOUT](../advanced_config/parameter_reference.md#VTE_M_REC_TOUT). | -| No `vte_aid_*` topics in the log | Sensor not publishing or fusion mask disabled | Use `listener` on the raw sensor topic, confirm [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) includes the relevant bit, and rerun the test with the debug task active. | -| Estimator never starts | Task mask disabled or mission not requesting precision landing | Set [VTE_TASK_MASK](../advanced_config/parameter_reference.md#VTE_TASK_MASK)=1 (or 3 for continuous debugging) and verify that new measurements arrive with valid timestamps. | +| Symptom | Likely cause | Remedy | +| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Vehicle misses the pad or ignores target yaw | Mission land waypoint not set to precision mode or yaw alignment disabled | Configure the landing waypoint for [precision landing](../advanced_features/precland.md#mission) and enable [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN). In logs, verify that `trajectory_setpoint.x/y` converges to `landing_target_pose.x_abs/y_abs` and `trajectory_setpoint.yaw` follows `vte_orientation.yaw`. | +| Frequent innovation rejections | Incorrect noise floors, miscalibrated measurement variance, or timestamp skew | Read `fusion_status` to find which branch fires. `STATUS_REJECT_NIS` points at the noise floors and the NIS thresholds; see [Outlier Detection](#outlier-detection) for the recipe. `STATUS_REJECT_TOO_OLD` / `STATUS_REJECT_TOO_NEW` point at latency or time-sync. Read `time_since_meas_ms` on the same `vte_aid_*` topic to confirm. | +| Bias does not converge | No secondary position source, or the GNSS/vision agreement check is too strict for the available vision quality | Enable vision fusion so the filter can observe GNSS bias. In the GNSS-first case, tune [VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR) / [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT). See [Bias initialization design](#bias-initialization-design) for the full state machine. | +| Orientation estimate drifts | Missing yaw measurements or low NIS gate | Enable [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) and ensure vision yaw data is present. Increase [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE) if legitimate data is being rejected. | +| `rel_pos_valid` toggles during descent | Position measurements arriving too slowly | Increase [VTE_TGT_TOUT](../advanced_config/parameter_reference.md#VTE_TGT_TOUT) or improve the measurement rate so updates remain inside [VTE_M_REC_TOUT](../advanced_config/parameter_reference.md#VTE_M_REC_TOUT). | +| No `vte_aid_*` topics in the log | Sensor not publishing or fusion mask disabled | Use `listener` on the raw sensor topic, confirm [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) includes the relevant bit, and rerun the test with the debug task active. | +| Estimator never starts | Task mask disabled or mission not requesting precision landing | Set [VTE_TASK_MASK](../advanced_config/parameter_reference.md#VTE_TASK_MASK)=1 (or 3 for continuous debugging) and verify that new measurements arrive with valid timestamps. | -### Plot Examples + -The dashboards below provide hints on how to analyse the estimator: +## Expected Plot Dashboards + +The dashboards below show what a healthy filter looks like, and what to watch when things degrade: 1. **Nominal behaviour**: how the position filter behaves, how the bias is initialised, what the innovations should look like, and how the orientation filter behaves. 2. **Out-of-sequence measurements (OOSM)**: how the filter handles delayed samples. @@ -675,8 +823,11 @@ The dashboards below provide hints on how to analyse the estimator: PlotJuggler (or the PX4 DevTools log viewer) is the easiest way to inspect the estimator as it allows you to group related signals into subplots that share the time axis. ::: -:::tip -**Adding new plots**: the screenshots in this section use a fixed colour convention so the same family of signals is easy to recognise across dashboards. Re-use it when adding or updating plots: +:::details +Click to see colour convention to add new plots + +**Adding new plots**: the screenshots in this section use a fixed colour convention so the same family of signals is easy to recognise across dashboards. +Re-use it when adding or updating plots: - Blue (`#1f77b4`): vision aid source (`vte_aid_fiducial_marker.*`) - Red (`#d62728`): GNSS aid sources (`vte_aid_gps_pos_target.*`, `vte_aid_gps_pos_mission.*`, `vte_aid_gps_vel_uav.*`, `vte_aid_gps_vel_target.*`) @@ -686,19 +837,23 @@ PlotJuggler (or the PX4 DevTools log viewer) is the easiest way to inspect the e ::: -#### Nominal Behaviour + + +:::details +Click to view Nominal Behaviour Plots **Estimator output and observation consistency**: Quick health check that the fused sensors agree with the estimated state during a real precision-landing approach using vision and the mission landing waypoint as the absolute reference. -- **Top row (observations and state output)**: `vte_aid_fiducial_marker.observation[0]`, `vte_aid_gps_pos_mission.observation[0]`, `vte_position.rel_pos[0]`, and a custom trace `gps_pos_mission_bias_compensated = vte_aid_gps_pos_mission.observation[0] - vte_position.bias[0]`. - The bias itself is not plotted explicitly here, it is consumed to produce the compensated trace. +- **Top row (observations and state output)**: `vte_aid_fiducial_marker.observation[0]`, `vte_aid_gps_pos_mission.observation[0]`, `vte_position.rel_pos[0]`, and a derived trace `gps_pos_mission_bias_compensated = vte_aid_gps_pos_mission.observation[0] - vte_position.bias[0]`. The filter follows vision most of the time because vision is the most precise source. - **Second row (observation variances and posterior)**: `vte_aid_fiducial_marker.observation_variance[0]`, `vte_aid_gps_pos_mission.observation_variance[0]`, and `vte_position.cov_rel_pos[0]`. - At the vertical line, mission GNSS reports about $0.65\,m^2$, vision about $0.060\,m^2$, and the posterior `vte_position.cov_rel_pos` about $0.010\,m^2$, below either input. + At the vertical line, mission GNSS reports about 0.65 m², vision about 0.060 m², and the posterior `vte_position.cov_rel_pos` about 0.010 m², below either input. This is the Kalman filter doing its job: combining independent measurements produces a posterior variance smaller than any of its inputs. - **Third row (vehicle velocity)**: `vte_aid_gps_vel_uav.observation[0]` against the filter output `vte_position.vel_uav[0]`. The filter trace stays smooth instead of copying the per-sample GNSS jitter, which confirms the velocity prediction and the GNSS velocity floor ([VTE_GPS_V_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_V_NOISE)) are tuned consistently. +![VTEST all observations](../../assets/vision_target_estimator/vtest_all_observations.png) + What this plot tells you: 1. **Vision is the dominant source throughout the descent.** @@ -707,7 +862,8 @@ What this plot tells you: If your receiver is more precise, retune [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) so the floor does not throw away its confidence. 2. **Higher altitudes have noisier vision.** At the start of the descent vision is noisier and `vte_position.rel_pos[0]` deviates from individual vision samples. - The vertical red line marks the moment vision becomes very precise; from there the filter locks onto vision. + The vertical red line marks the moment vision becomes very precise. + From there the filter locks onto vision. 3. **A steady offset between the filter and the compensated GNSS is a tuning signal.** During the last phase of the landing, a roughly 15 cm gap between `vte_position.rel_pos[0]` and `gps_pos_mission_bias_compensated` remains. If a comparable gap is persistent in your logs, the bias state can be too tight to absorb the slow drift. @@ -717,13 +873,12 @@ What this plot tells you: Vision stops detecting the target at the end of the trace and `vte_position.cov_rel_pos` starts to climb. The corrected GNSS still points to the pad thanks to the latest bias value, so the vehicle keeps tracking it. -![VTEST all observations](../../assets/vision_target_estimator/vtest_all_observations.png) - **Initial bias averaging**: Shows the GNSS/vision bias low-pass filter while the estimator is in the GNSS-first averaging phase. The plot was generated with [VTE_BIA_AVG_TOUT](../advanced_config/parameter_reference.md#VTE_BIA_AVG_TOUT)=10s and [VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR)=0.01 so the convergence threshold is never met and the full 10 s averaging window is exercised. - **Top row (raw vs filtered bias)**: `vte_bias_init_status.raw_bias` (per-axis raw GNSS minus vision delta) overlaid with `vte_bias_init_status.filtered_bias`. - The filtered bias is the LPF output (`tau = 0.3 s`); it should track the average of the raw samples and settle to a steady value as more vision observations arrive. + The filtered bias is the LPF output (`tau = 0.3 s`). + It should track the average of the raw samples and settle to a steady value as more vision observations arrive. - **Second row (delta norm)**: `vte_bias_init_status.delta_norm` is the norm of consecutive raw-bias deltas which is the stability metric used by the convergence test. With [VTE_BIA_AVG_THR](../advanced_config/parameter_reference.md#VTE_BIA_AVG_THR)=0.01 the filter would exit as soon as five consecutive deltas stay below 0.01 m and at least `2 * tau` has passed. This threshold can be tuned based on the precision of the vision sensor. @@ -743,7 +898,8 @@ The dashboard intentionally pairs a healthy aid source (vision) with a less well The exact status code matters less than the fact that the sample is fused: `STATUS_FUSED_CURRENT` and `STATUS_FUSED_OOSM` are both healthy. - **Third row (mission GNSS innovations)**: `vte_aid_gps_pos_mission.innovation[0..2]`. The innovations are _not_ zero-mean white noise. - A persistent bias is visible (at the vertical red line, about $-0.18$ m in North, $+0.22$ m in East, and $+0.38$ m in Down), which means the bias state is too tight to absorb the slow drift between the GNSS frame and the vision frame, so the residual ends up in the innovation. + A persistent bias is visible at the vertical red line (about -0.18 m in North, +0.22 m in East, and +0.38 m in Down). + The bias state is too tight to absorb the slow drift between the GNSS frame and the vision frame, so the residual ends up in the innovation. Loosen [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) to let the bias track more of that drift, but only enough that the bias still stays stable when vision is lost (see [Vision occlusion during descent](#vision-occlusion-during-descent)). - **Bottom row (mission GNSS fusion status)**: `vte_aid_gps_pos_mission.fusion_status[0..2]` is mostly `STATUS_FUSED_OOSM`, so the GNSS variance is wide enough to absorb the biased innovation through the NIS gate. A short burst of `STATUS_REJECT_TOO_OLD` (status code 5) is also visible, meaning a GNSS sample arrived older than the OOSM buffer span (500 ms). @@ -752,7 +908,8 @@ The dashboard intentionally pairs a healthy aid source (vision) with a less well ![VTEST innovations](../../assets/vision_target_estimator/vtest_innovations.png) **Orientation filter**: Validates that yaw aiding stays smooth yet responsive without making the drone oscillate. -Generated from a real precision-landing flight; enable the orientation filter with [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) to log the same signals. +Generated from a real precision-landing flight. +Enable the orientation filter with [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) to log the same signals. - **Top row (yaw observation vs. state)**: `vte_aid_ev_yaw.observation` overlaid with `vte_orientation.yaw`. The state should track the slow trend of the observation without copying its high-frequency jitter. @@ -765,7 +922,17 @@ See [When the state follows per-sample jitter](#when-the-state-follows-per-sampl ![VTEST orientation](../../assets/vision_target_estimator/vtest_yaw.png) -#### Out-of-Sequence Measurements + + +**Case study: yaw oscillation.** The plot above was generated with [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE) at 4 deg (about 0.07 rad) and [VTE_YAW_ACC_UNC](../advanced_config/parameter_reference.md#VTE_YAW_ACC_UNC) at 0.004, both current defaults. +With more aggressive values (0.05 rad / 0.04) the filter jumped to follow every yaw observation, the controller chased the resulting setpoint changes, and the drone visibly oscillated. +The oscillation itself then degraded the next vision samples (motion blur and larger lever-arm effects make yaw harder to estimate), feeding the loop. +Trusting the process model more (smaller `VTE_YAW_ACC_UNC`) and the observations less (larger `VTE_EVA_NOISE`) breaks that loop: the state stays close to the underlying yaw trend, the drone holds steady, and the observations themselves become cleaner. + +::: + +:::details +Click to view Out-of-Sequence Measurements (OOSM) plots @@ -788,7 +955,10 @@ Under fast dynamics this kind of latency-induced error grows quickly and can rep ![VTEST OOSM](../../assets/vision_target_estimator/vtest_oosm.png) -#### Filter Robustness +::: + +:::details +Click to view filter robustness plots @@ -807,7 +977,7 @@ If the state in your own logs follows the jitter instead of the trend, see [When **Rejecting a corrupted measurement**: Demonstrates how the estimator rejects a faulty measurement. The plot was obtained by injecting during 6 seconds an additive bias uniformly sampled between -1 and 1 metre on the x-axis vision observation, while leaving the other axis untouched. -The healthy axes keep fusing as expected, while the corrupted axis repeatedly fails the NIS gate, which is what protects the state from following the outliers into the wrong solution. +The healthy axes keep fusing as expected, while the corrupted axis repeatedly fails the NIS gate, which keeps the state from chasing the outliers. - **Top row (x observation)**: `vte_position.rel_pos[0]` follows `vte_aid_fiducial_marker.observation[0]` until the measurements are altered, at which point it does not follow the biased measurements. - **Second row (x fusion status)**: `vte_aid_fiducial_marker.fusion_status[0]` flips to `STATUS_REJECT_NIS` whenever the observation disagrees with the filter prediction, confirming that the chi-squared gate is doing its job. @@ -818,11 +988,12 @@ What to do when you see this pattern in your own logs: 1. Confirm that the rejection actually corresponds to a corrupted measurement and not a healthy sample being thrown out by an overly tight gate. Compare the raw sensor topic (e.g. `fiducial_marker_pos_report`) with `vte_aid_fiducial_marker.observation` to be sure the input itself is bad rather than a frame transform or timestamp issue. -2. If the rejections are legitimate (the data really is corrupted), no parameter change is needed: the NIS gate is performing exactly the function it is there for. +2. If the rejections are legitimate (the data really is corrupted), no parameter change is needed: the NIS gate is doing its job. Investigate the upstream sensor instead (camera exposure, marker visibility, attitude alignment). 3. If healthy samples are being rejected, the observation variance is the first thing to revisit. As detailed in the [troubleshooting checklist](#troubleshooting-checklist) row on _Frequent innovation rejections_, an under-reported variance causes the NIS gate to fire on small innovations. Raise [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) (or [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) for GNSS) so the floor matches the actual sensor accuracy. -4. If both the upstream sensor and the variance look correct but legitimate outliers are still slipping through, loosen the gate slightly with [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) (defaults to $3.84$, i.e. a $5\%$ false-rejection rate; smaller values reject more aggressively, larger values are more permissive). +4. If both the upstream sensor and the variance look correct but legitimate outliers are still slipping through, loosen the gate slightly with [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) (defaults to 3.84, i.e. a 5% false-rejection rate). + Larger values are more permissive, smaller values reject more aggressively. ![VTEST measurement not fused](../../assets/vision_target_estimator/vtest_meas_not_fused.png) @@ -836,10 +1007,8 @@ The only difference between the two runs is whether [VTE_AID_MASK](../advanced_c To make the full dropout visible, [VTE_BTOUT](../advanced_config/parameter_reference.md#VTE_BTOUT) was raised to 10 s for these runs (default 3 s) so the filter keeps predicting the state instead of resetting early. On both plots the **vertical blue line** marks the moment vision is lost, and the **vertical red line** marks the estimator timeout 10 s later, when [VTE_BTOUT](../advanced_config/parameter_reference.md#VTE_BTOUT) expires and the filter is reset. -The reason this case deserves its own plot is structural rather than a tuning issue. -The per-axis state $[r, v^{uav}, b]$ exposes $v^{uav}$ only through the $dt$ cross-term in the position prediction ($r_{k+1} = r_k - dt\thinspace v^{uav}_k - \tfrac{1}{2}\thinspace dt^2\thinspace a^{uav}$). Vision measures $r$ directly but does not touch $v^{uav}$. -While vision keeps arriving, the cross-coupling is enough to keep $v^{uav}$ close to truth indirectly. -When vision drops out that indirect anchor disappears and any small residual in $v^{uav}$ integrates straight into `vte_position.rel_pos`. +This is a structural property of the filter, not a tuning issue. +See [Filter observability](#filter-observability) for the underlying reason: vision never touches the $v^{uav}$ state directly, so any residual in $v^{uav}$ integrates straight into `vte_position.rel_pos` once vision is gone. **Plot 1, vision only**: [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) = vision only (bit 2). @@ -872,7 +1041,8 @@ What to take away from this comparison: **Vision occlusion during descent (real flight)**: Demonstrates the central motivation behind multi-sensor fusion. Once the bias between the absolute frame (here the mission landing waypoint) and the vision frame is estimated, the corrected GNSS observation still points at the pad after vision drops out, so the vehicle still lands precisely. -Generated by removing the vision fusion 5 m above the target during a real precision-landing flight. The drone landed at the center of the target despite the vision loss. +Generated by removing the vision fusion 5 m above the target during a real precision-landing flight. +The drone landed at the center of the target despite the vision loss. The vertical blue line marks the moment vision is stopped, and the vertical red line marks touchdown. @@ -883,10 +1053,10 @@ The vertical blue line marks the moment vision is stopped, and the vertical red By touchdown, the bias settles at about $-0.46$ m on x (north) and $+1.18$ m on y (east). Without bias compensation the drone would have touched down 1.18 m east of the pad. - **Bottom row (relative position covariance)**: `vte_position.cov_rel_pos[0]`. - The variance climbs by about $0.053\,m^2$ once vision is lost, corresponding to a 1-sigma growth of $\sqrt{0.053} \approx 0.23\,m$. + The variance climbs by about 0.053 m² once vision is lost, corresponding to a 1-sigma growth of $\sqrt{0.053} \approx 0.23$ m. This is the filter reporting that the relative position is now less certain because no vision sample is constraining it. -Why this matters: this is exactly the case multi-sensor fusion is meant to handle. +This is the case multi-sensor fusion was designed for. The mission landing waypoint reports the pad position with a metre-scale offset (the bias) that vision corrects. Once the bias is observed, the corrected GNSS effectively becomes a second relative-position sensor for the remaining descent, including any segment where the marker temporarily disappears (motion blur, partial occlusion, or the marker leaving the camera field of view because it is too large at low altitude). This is particularly important for large targets where the marker is expected to leave the camera frame in the final metres of descent. @@ -897,17 +1067,22 @@ What to watch in your own logs: If your dropout test shows the bias still moving when vision is lost, lower [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC). - The post-dropout bias drift gives a direct read on how aggressively the bias is tuned. The deltas above (a few centimetres over 8 seconds) match a well-tuned filter. - Larger drift means [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) is too loose; the filter overfit the bias to recent vision and now lets it walk away when vision is gone. + Larger drift means [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) is too loose. + The filter overfit the bias to recent vision and now lets it walk away when vision is gone. ![VTEST occlusion with GNSS mission](../../assets/vision_target_estimator/vtest_dropout_vision_and_gps_pos_mission.png) -#### Precision Landing on a Static Target +::: + +:::details +Click to view Precision Landing on a static target plot **Precision landing alignment**: Compares the precision-landing target with the vehicle position to confirm that the vehicle is actually navigating toward the target. Generated from a real precision-landing flight. `landing_target_pose.x_abs` and `landing_target_pose.y_abs` are expressed in the local NED frame, which is fixed relative to the EKF2 origin. -For a static target both values should stay roughly constant for the duration of the approach: the estimator can refine the target position as new observations arrive, but big jumps or steady drift in this signal indicate noisy observations or an estimator that is following them too aggressively. +For a static target both values should stay roughly constant for the duration of the approach. +The estimator can refine the target position as new observations arrive, but big jumps or steady drift in this signal indicate noisy observations or an estimator that is following them too aggressively. If you see this, [When the state follows per-sample jitter](#when-the-state-follows-per-sample-jitter) lists the right knobs. The plot is also useful for catching misconfigurations, for example [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN) disabled when yaw alignment is expected. @@ -922,10 +1097,16 @@ If the controller struggles to follow even when the target signal is clean, revi ![VTEST precision landing](../../assets/vision_target_estimator/vtest_precland.png) -#### Moving Target +::: + + + +:::details +Click to view Moving Target plot **Moving target precision landing**: Shows how the precision-landing controller projects the setpoint ahead of a moving target, how the lead converges onto the target as altitude drops, and how the moving-target states behave during the descent. -Generated from a real flight with a camera publishing target estimates at 10 Hz at $640 \times 480$ resolution; the firmware was built with `CONFIG_VTEST_MOVING=y`. +Generated from a real flight with a camera publishing target estimates at 10 Hz at 640×480 resolution. +The firmware was built with `CONFIG_VTEST_MOVING=y`. - **Top row (axis along which the target moves)**: `vehicle_local_position.x`, `landing_target_pose.x_abs`, and `trajectory_setpoint.position[0]`. The trajectory setpoint sits ahead of the estimated target position for most of the descent: that is the [PLD_MOVING_T_MAX](../advanced_config/parameter_reference.md#PLD_MOVING_T_MAX) lookahead leading the vehicle toward where the target will be at touchdown. @@ -943,23 +1124,30 @@ What to take away: Adding a target GNSS receiver gives the filter an absolute reference even before vision detects the marker: the filter converges faster, the vehicle can fly to a moving target before it is in view, and the risk of missing the target is reduced. Any offset between the receiver and the marker is estimated by the bias state. - **Add a direct target-velocity observation when you can.** - Target GNSS velocity ([VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 4) is the only measurement that constrains $v^t$ directly. - Without it, target velocity is only weakly observable and the precision-landing lookahead becomes noisier. - This is the moving-target analogue of the static-target [Vision dropout behaviour](#vision-dropout-behaviour), where fusing vehicle GNSS velocity directly anchored the vehicle velocity state and removed the relative-position drift. + Target GNSS velocity ([VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 4) is the only measurement that constrains $v^{t}$ directly, and without it the precision-landing lookahead becomes noisier. + See [Filter observability](#filter-observability) for why a direct velocity observation matters. - **Publish target estimates at a high rate.** With a 10 Hz camera the prediction has up to 100 ms of unconstrained motion between samples. Raising the rate shrinks the predicted variance growth between fusions, makes the precision-landing setpoint smoother, and keeps `vte_aid_fiducial_marker.innovation` closer to zero through the descent. ![VTEST moving target landing](../../assets/vision_target_estimator/vtest_moving_target.png) +::: + ## Development and Debugging Tips +A few tips to make iteration on real hardware and SITL easier. + - To print `PX4_DEBUG` statements from the module, launch SITL with `PX4_LOG_LEVEL=debug` (for example, `PX4_LOG_LEVEL=debug make px4_sitl_visionTargetEst`). On hardware builds, compile with the debug configuration or enable the console log level before running tests so the additional diagnostics appear on the shell. -- Keep the estimator alive on the bench by setting [VTE_TASK_MASK](../advanced_config/parameter_reference.md#VTE_TASK_MASK)=3; the debug bit enables the continuous update of the position and orientation estimators (if enabled via [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) and [VTE_POS_EN](../advanced_config/parameter_reference.md#VTE_POS_EN)). +- Keep the estimator alive on the bench by setting [VTE_TASK_MASK](../advanced_config/parameter_reference.md#VTE_TASK_MASK)=3. + The debug bit enables the continuous update of the position and orientation estimators (if enabled via [VTE_YAW_EN](../advanced_config/parameter_reference.md#VTE_YAW_EN) and [VTE_POS_EN](../advanced_config/parameter_reference.md#VTE_POS_EN)). - Use shell helpers while iterating: `listener landing_target_pose`, `listener vte_bias_init_status`, `listener vte_aid_fiducial_marker` (or the relevant `vte_aid_*`) to inspect bias averaging and innovations, `listener vte_input 5` for prediction inputs, and `vision_target_estimator status` to ensure both filters are running. -### SITL Simulation Pipeline + + +:::details +Click to view the guide on SITL Simulation Pipeline The Gazebo Classic SITL setup produces both VTE inputs (`fiducial_marker_pos_report` and `target_gnss`) end-to-end, so the filter can be tested without real hardware. This is also where you should inject extra noise or latency to stress-test the filter. @@ -967,9 +1155,11 @@ This is also where you should inject extra noise or latency to stress-test the f The pipeline has four stages: 1. **Aruco marker detection**: `arucoMarkerPlugin` (`Tools/simulation/gazebo-classic/sitl_gazebo-classic/src/gazebo_aruco_plugin.cpp`) runs on the simulated camera, detects the marker, and publishes a `TargetRelative` Gazebo message. - The reported standard deviations are hard-coded in `OnNewFrame()` (`set_std_x`, `set_std_y`, `set_std_z`, `set_yaw_std`); change them there to make the vision report more or less noise. + The reported standard deviations are hard-coded in `OnNewFrame()` (`set_std_x`, `set_std_y`, `set_std_z`, `set_yaw_std`). + Change them there to make the simulated vision report noisier or cleaner. Marker visibility is controlled by `Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/land_pad/land_pad.sdf`: the `` element sets the rendered Aruco square (the `` size is independent and just controls the physical pad). - The `` element on the `` block places the pad in the world; its last value is the pad yaw in radians (for example `0.0 0.0 0.06 0 0 0.7` rotates the pad by 0.7 rad, about 40 deg), which is the easiest way to exercise the orientation filter in SITL. + The `` element on the `` block places the pad in the world. + Its last value is the pad yaw in radians (for example `0.0 0.0 0.06 0 0 0.7` rotates the pad by 0.7 rad, about 40 deg), which is the easiest way to exercise the orientation filter in SITL. 2. **Target GPS**: the `gps_target` model included from `land_pad.sdf` runs the standard Gazebo GPS plugin. Tune the noise floors directly in `Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/gps/gps.sdf` (the `` blocks for horizontal/vertical position and velocity). 3. **Mavlink bridge**: `gazebo_mavlink_interface.cpp` connects the two plugins to the autopilot. @@ -977,7 +1167,11 @@ The pipeline has four stages: 4. **PX4 side**: `SimulatorMavlink::handle_message_target_relative()` and `handle_message_target_absolute()` decode the mavlink messages back into `fiducial_marker_pos_report` and `target_gnss` (or directly into `landing_target_pose` when `VTE_EN=0`). From there the filter sees exactly the same topics it would on real hardware, so anything you tune at the sensor level reproduces faithfully end to end. -### Adding New Measurement Sources +::: + + + +::::details Click to view the guide on adding new measurement sources To integrate a new sensor: @@ -1000,10 +1194,14 @@ Reject samples older than [VTE_M_REC_TOUT](../advanced_config/parameter_referenc If observations are stored in cache, invalidate it inside `checkMeasurementInputs` when older than [VTE_M_UPD_TOUT](../advanced_config/parameter_reference.md#VTE_M_UPD_TOUT) (`isMeasUpdated(hrt_abstime ts)`). ::: -### Adding New Tasks +:::: -Add a new `VteTask` when the estimator should only run during a particular mission phase or flight-mode behavior, or when that behavior needs its own subscriptions, cached state, or completion logic. -Do not put that state back into `VisionTargetEst`; the whole point of the task layer is to keep the scheduler generic. +:::details +Click to view the guide on adding new tasks + +Add a new `VteTask` when the estimator should only run during a particular mission phase or flight-mode behaviour, or when that behaviour needs its own subscriptions, cached state, or completion logic. +Do not put that state back into `VisionTargetEst`. +The whole point of the task layer is to keep the scheduler generic. Use this checklist: @@ -1023,7 +1221,12 @@ Use this checklist: 6. **Test lifecycle and cache behaviour**: extend `TEST_VTE_VisionTargetEst.cpp` with coverage for task activation completion, repeated starts, and any cached mission/context data that must survive estimator restarts within the same task. 7. **Document the operational meaning**: update the overview page, this deep dive, and any feature-specific docs so users understand when the new task is active and which `VTE_TASK_MASK` bit selects it. -### SymForce-Generated Derivations +::: + + + +:::details +Click to view the guide on SymForce-generated derivations The Kalman-filter math is not written by hand. The symbolic state, prediction model, and covariance update are defined in Python and expanded into C++ by [SymForce](https://symforce.org/), so the C++ that runs on the autopilot always matches the model defined in `derivation.py`. @@ -1040,7 +1243,7 @@ The symbolic state, prediction model, and covariance update are defined in Pytho | Положення | `state.h`, `predictState.h`, `predictCov.h`, `computeInnovCov.h`, `getTransitionMatrix.h`, `applyCorrection.h` | | Орієнтація | `predictState.h`, `predictCov.h`, `getTransitionMatrix.h` (innovation computation and correction stay hand-written in `Orientation/KF_orientation.cpp` so yaw angles can be wrapped to $[-\pi, \pi]$) | -**Build-time behavior:** +**Build-time behaviour:** - By default, CMake copies the committed pre-generated headers from `Position/vtest_derivation/generated/` into the build tree under `build//src/modules/vision_target_estimator/vtest_derivation/generated/`, and likewise for orientation. No SymForce install is required for the static build. - `CONFIG_VTEST_MOVING=y` automatically sets `VTEST_SYMFORCE_GEN=ON` and requires SymForce in the Python environment so the 5-state moving-target headers are produced. @@ -1059,8 +1262,16 @@ To change the model, edit `derivation.py` and regenerate. If the build fails during regeneration, inspect the CMake output for the SymForce invocation and rerun it manually inside `Position/vtest_derivation/` to catch Python errors. After regenerating, rebuild the module to ensure the Jacobians and code stay in sync. +::: + ## Runtime Performance on Hardware +Even with ~500 ms induced latency on every measurement the estimator stays inside its 20 ms loop budget on a Pixhawk 6c. +Expand below for the full per-counter breakdown (baseline vs. delayed runs). + +:::details +Click to view Pixhawk 6c performance expectations + The estimator publishes per-section perf counters that can be read at any time on the shell: ```sh @@ -1092,7 +1303,7 @@ VTE cycle yaw: 18563 events, 125422us elapsed, 6.76us avg, min 4us max 60u VTE cycle pos: 18569 events, 803841us elapsed, 43.29us avg, min 22us max 253us 38.464us rms ``` -**With `PX4_SIM_TARGET_MEASUREMENT_DELAY_MAX_MS=500` (≈ 480–500 ms latency, ~20 OOSM steps on average):** +**With bounded delay (≈ 480–500 ms latency, ~20 OOSM steps on average):** ```text VTE fusion: 31932 events, 1860362us elapsed, 58.26us avg, min 63us max 135us 23.520us rms @@ -1105,8 +1316,8 @@ VTE cycle pos: 32861 events, 2703185us elapsed, 82.26us avg, min 10us max 479u How to read these: -- **`VTE prediction` is essentially constant** (~5.7 us). - Predictions do a fixed amount of math regardless of measurement latency, which is what we expect. +- **`VTE prediction` stays constant** (~5.7 us). + Predictions do a fixed amount of math regardless of measurement latency. - **`VTE fusion` jumps from ~14 us to ~58 us** (≈ 4× increase). This is the OOSM cost: the projection step touches every history sample after `t_meas`, so the runtime grows roughly linearly in `history_steps`. With ~20 history steps the per-fusion cost is still well under 100 us on average. @@ -1122,16 +1333,18 @@ A few things to keep in mind when interpreting your own numbers: - `history_steps` saturates at the buffer depth (`kOosmHistorySize = 25`). If you see it pinned at 25 in the logs, the measurement is older than 500 ms and is being rejected as `STATUS_REJECT_TOO_OLD` rather than fused. -Even with ~500 ms induced latency on every measurement the estimator stays inside its 20 ms loop budget on a Pixhawk 6c. +::: ## Unit Test Suites +The module contains unit tests that cover the Kalman math, the per-filter module logic, and the OOSM history buffer. + - `TEST_VTE_KF_position`: Kalman filter math for the position state (prediction, NIS gating, bias-aware H, OOSM gold standard). Static model (state size 3) by default, moving-target tests (state size 5) build only when `CONFIG_VTEST_MOVING` is enabled. - `TEST_VTE_KF_orientation`: Kalman filter math for yaw/yaw-rate (wrap logic, process noise, dt edge cases, covariance symmetry). - `TEST_VTE_VTEPosition`: Module logic for vision/GNSS fusion, offsets, interpolation, ordering, and uORB innovation topics (static + moving gated by `CONFIG_VTEST_MOVING`). - `TEST_VTE_VTEOrientation`: Module logic for yaw fusion, noise models, resets, and OOSM handling. -- `TEST_VTE_VTEOosm`: Generic OOSM manager behavior. +- `TEST_VTE_VTEOosm`: Generic OOSM manager behaviour. Run locally: diff --git a/docs/uk/complete_vehicles_rover/hiwonder_ackermann.md b/docs/uk/complete_vehicles_rover/hiwonder_ackermann.md index 2adeb65b30..4e20c460e8 100644 --- a/docs/uk/complete_vehicles_rover/hiwonder_ackermann.md +++ b/docs/uk/complete_vehicles_rover/hiwonder_ackermann.md @@ -17,7 +17,7 @@ Make sure all parts are compatible with your flight controller's ports, and adju Alternatives are listed in: - [Flight Controllers](../flight_controller/index.md) -- [PX4-Compatible Receivers](../getting_started/rc_transmitter_receiver.md#px4-compatible-receivers-compatible_receivers) +- [PX4-Compatible Receivers](../getting_started/rc_transmitter_receiver.md#compatible_receivers) - [Data Links](../data_links/index.md) - [Global Navigation Satellite Systems (GNSS)](../gps_compass/index.md#supported-gnss) or [RTK GNSS](../gps_compass/rtk_gps.md) @@ -86,7 +86,7 @@ For a longer term solution we highly recommend 3d printing mounts that you attac This frame works with the usual Rover firmware variants on most flight controllers. You can use either prebuilt versions or build the firmware yourself (see [Flashing the Rover Build](../config_rover/index.md#flashing-the-rover-build) and [Building Rover](../config_rover/index.md#building-rover) in _Rover Configuration/Tuning_). -A few boards may omit the [`hiwonder_emm` driver](../modules/modules_driver.md#hiwonder_emm) for the [Hiwonder 4-Channel Encoder Motor Module](../peripherals/hiwonder_emm.md) used by this vehicle. +A few boards may omit the [`hiwonder_emm` driver](../modules/modules_driver.md#hiwonder-emm) for the [Hiwonder 4-Channel Encoder Motor Module](../peripherals/hiwonder_emm.md) used by this vehicle. If your board does not ship with it you will need a custom build — see [Hiwonder 4-Channel Encoder Motor Module > Building the Firmware](../peripherals/hiwonder_emm.md#building-the-firmware) for instructions. ## Конфігурація PX4 diff --git a/docs/uk/complete_vehicles_rover/hiwonder_mecanum.md b/docs/uk/complete_vehicles_rover/hiwonder_mecanum.md index d60957bba9..c73bbcfd2a 100644 --- a/docs/uk/complete_vehicles_rover/hiwonder_mecanum.md +++ b/docs/uk/complete_vehicles_rover/hiwonder_mecanum.md @@ -17,7 +17,7 @@ Make sure all parts are compatible with your flight controller's ports, and adju Alternatives are listed in: - [Flight Controllers](../flight_controller/index.md) -- [PX4-Compatible Receivers](../getting_started/rc_transmitter_receiver.md#px4-compatible-receivers-compatible_receivers) +- [PX4-Compatible Receivers](../getting_started/rc_transmitter_receiver.md#compatible_receivers) - [Data Links](../data_links/index.md) - [Global Navigation Satellite Systems (GNSS)](../gps_compass/index.md#supported-gnss) or [RTK GNSS](../gps_compass/rtk_gps.md) @@ -76,7 +76,7 @@ For a longer term solution we highly recommend 3d printing mounts that you attac This frame works with the usual Rover firmware variants on most flight controllers. You can use either prebuilt versions or build the firmware yourself (see [Flashing the Rover Build](../config_rover/index.md#flashing-the-rover-build) and [Building Rover](../config_rover/index.md#building-rover) in _Rover Configuration/Tuning_). -A few boards may omit the [`hiwonder_emm` driver](../modules/modules_driver.md#hiwonder_emm) for the [Hiwonder 4-Channel Encoder Motor Module](../peripherals/hiwonder_emm.md) used by this vehicle. +A few boards may omit the [`hiwonder_emm` driver](../modules/modules_driver.md#hiwonder-emm) for the [Hiwonder 4-Channel Encoder Motor Module](../peripherals/hiwonder_emm.md) used by this vehicle. If your board does not ship with it you will need a custom build — see [Hiwonder 4-Channel Encoder Motor Module > Building the Firmware](../peripherals/hiwonder_emm.md#building-the-firmware) for instructions. ## Конфігурація PX4 diff --git a/docs/uk/complete_vehicles_rover/hiwonder_tracked.md b/docs/uk/complete_vehicles_rover/hiwonder_tracked.md index ab1550bbeb..a1d42379b3 100644 --- a/docs/uk/complete_vehicles_rover/hiwonder_tracked.md +++ b/docs/uk/complete_vehicles_rover/hiwonder_tracked.md @@ -17,7 +17,7 @@ Make sure all parts are compatible with your flight controller's ports, and adju Alternatives are listed in: - [Flight Controllers](../flight_controller/index.md) -- [PX4-Compatible Receivers](../getting_started/rc_transmitter_receiver.md#px4-compatible-receivers-compatible_receivers) +- [PX4-Compatible Receivers](../getting_started/rc_transmitter_receiver.md#compatible_receivers) - [Data Links](../data_links/index.md) - [Global Navigation Satellite Systems (GNSS)](../gps_compass/index.md#supported-gnss) or [RTK GNSS](../gps_compass/rtk_gps.md) @@ -76,7 +76,7 @@ For a longer term solution we highly recommend 3d printing mounts that you attac This frame works with the usual Rover firmware variants on most flight controllers. You can use either prebuilt versions or build the firmware yourself (see [Flashing the Rover Build](../config_rover/index.md#flashing-the-rover-build) and [Building Rover](../config_rover/index.md#building-rover) in _Rover Configuration/Tuning_). -A few boards may omit the [`hiwonder_emm` driver](../modules/modules_driver.md#hiwonder_emm) for the [Hiwonder 4-Channel Encoder Motor Module](../peripherals/hiwonder_emm.md) used by this vehicle. +A few boards may omit the [`hiwonder_emm` driver](../modules/modules_driver.md#hiwonder-emm) for the [Hiwonder 4-Channel Encoder Motor Module](../peripherals/hiwonder_emm.md) used by this vehicle. If your board does not ship with it you will need a custom build — see [Hiwonder 4-Channel Encoder Motor Module > Building the Firmware](../peripherals/hiwonder_emm.md#building-the-firmware) for instructions. ## Конфігурація PX4 diff --git a/docs/uk/concept/flight_tasks.md b/docs/uk/concept/flight_tasks.md index 1a225c4b1b..8e1089e5a4 100644 --- a/docs/uk/concept/flight_tasks.md +++ b/docs/uk/concept/flight_tasks.md @@ -142,7 +142,6 @@ _Польотні завдання_ використовуються у [Реж ```c ... * @value 0 Direct velocity - * @value 3 Smoothed velocity * @value 4 Acceleration based * @value 5 My task * @group Multicopter Position Control diff --git a/docs/uk/config_mc/mc_jerk_limited_type_trajectory.md b/docs/uk/config_mc/mc_jerk_limited_type_trajectory.md index 77e55009b6..dfe0bb4e38 100644 --- a/docs/uk/config_mc/mc_jerk_limited_type_trajectory.md +++ b/docs/uk/config_mc/mc_jerk_limited_type_trajectory.md @@ -1,15 +1,9 @@ # Траєкторія Jerk-limited типу для Мультикоперів -Тип траєкторії з обмеженим рухом джерка забезпечує плавний рух у відповідь на введення палиці користувача або зміни місії (наприклад: для зйомки, картографування, вантажу). +The Jerk-limited trajectory type provides smooth motion in autonomous flight e.g. for filming, mapping, cargo. Він генерує симетричні плавні S-криві, де обмеження різкості та прискорення завжди гарантовані. -This trajectory type is always enabled in [Mission mode](../flight_modes_mc/mission.md). -To enable it in [Position mode](../flight_modes_mc/position.md) set the parameter [MPC_POS_MODE](../advanced_config/parameter_reference.md#MPC_POS_MODE) to `Smoothed velocity`. - -:::info -The jerk-limited type is not used _by default_ in position mode. -Це може бути не підходить для транспортних засобів / випадків використання, які вимагають швидкої відповіді - наприклад, гонщицькі квадрокоптери. -::: +This trajectory type is always enabled in autonomous modes like [Mission mode](../flight_modes_mc/mission.md). ## Генератор траєкторії @@ -30,16 +24,11 @@ The constraints `jMax`, `aMax` are configurable by the user via parameters and c ## Ручний режим -In manual position mode, the sticks are mapped to velocity where a full XY-stick deflection corresponds to [MPC_VEL_MANUAL](../advanced_config/parameter_reference.md#MPC_VEL_MANUAL) and a full Z-stick deflection corresponds to [MPC_Z_VEL_MAX_UP](../advanced_config/parameter_reference.md#MPC_Z_VEL_MAX_UP) (upward motion) or [MPC_Z_VEL_MAX_DN](../advanced_config/parameter_reference.md#MPC_Z_VEL_MAX_DN) (downward motion). +In manual position and altitude mode, jerk limiting is applied only to the vertical axis. Full throttle stick deflection commands the maximum vertical velocity which is [MPC_Z_VEL_MAX_UP](../advanced_config/parameter_reference.md#MPC_Z_VEL_MAX_UP) upwards and [MPC_Z_VEL_MAX_DN](../advanced_config/parameter_reference.md#MPC_Z_VEL_MAX_DN) downwards. ### Обмеження -XY-plane: - -- `jMax`: [MPC_JERK_MAX](../advanced_config/parameter_reference.md#MPC_JERK_MAX) -- `aMax`: [MPC_ACC_HOR_MAX](../advanced_config/parameter_reference.md#MPC_ACC_HOR_MAX) - -Z-axis: +Z-axis - `jMax`: [MPC_JERK_MAX](../advanced_config/parameter_reference.md#MPC_JERK_MAX) - `aMax` (upward motion): [MPC_ACC_UP_MAX](../advanced_config/parameter_reference.md#MPC_ACC_UP_MAX) diff --git a/docs/uk/config_mc/mc_trajectory_tuning.md b/docs/uk/config_mc/mc_trajectory_tuning.md index b9c3003f01..d5d5e5a61e 100644 --- a/docs/uk/config_mc/mc_trajectory_tuning.md +++ b/docs/uk/config_mc/mc_trajectory_tuning.md @@ -54,11 +54,6 @@ The following list provides an _overview_ of the different implementations of ho - Неочікувані зміни нахилу при досягненні швидкості руху. - Вертикальний вхід палиці відображений з обмеженим ривком траєкторії. - Set in position mode using `MPC_POS_MODE=Acceleration based`. -- [Jerk-limited](../config_mc/mc_jerk_limited_type_trajectory.md) - - Використовується, коли потрібен плавний рух (наприклад: зйомка, картографування, вантаж). - - Генерує симетричні плавні S-криві, де обмеження різкості та прискорення завжди гарантовані. - - Можливо, не підходить для транспортних засобів / випадків використання, які вимагають швидкої відповіді - наприклад, гонщицькі квадрокоптери. - - Set in position mode using `MPC_POS_MODE=Smoothed velocity`. - **Simple position control** - Палиці безпосередньо відображаються на встановлені точки швидкості без згладжування. - Корисно для налаштування контролю швидкості. diff --git a/docs/uk/dev_log/logging.md b/docs/uk/dev_log/logging.md index e61894e343..dc5f4c962d 100644 --- a/docs/uk/dev_log/logging.md +++ b/docs/uk/dev_log/logging.md @@ -52,21 +52,28 @@ _Developers_ can further configure what information is logged via the [logger](. ### Конфігурація SD-карти -Окремо, список зареєстрованих тем також може бути налаштований за допомогою файлу на картці SD. -Create a file `etc/logging/logger_topics.txt` on the card with a list of topics (For SITL, it's `build/px4_sitl_default/rootfs/fs/microsd/etc/logging/logger_topics.txt`): +The list of logged topics can also be customized with a file on the SD card: `etc/logging/logger_topics.txt` (for SITL, it's `build/px4_sitl_default/rootfs/fs/microsd/etc/logging/logger_topics.txt`). + +Each topic to be logged is listed on a separate line, with the following format: ```plain ``` -The `` is optional, and if specified, defines the minimum interval in ms between two logged messages of this topic. -Якщо не вказано, тема реєструється з повною швидкістю. +Де: -The `` is optional, and if specified, defines the instance to log. -Якщо не вказано, всі екземпляри теми реєструються. -To specify ``, `` must be specified. Може бути встановлено на 0 для реєстрації з повною швидкістю +- `` (optional). + Defines the minimum interval in ms between two logged messages of this topic. + If not specified or `0`, the topic is logged at full rate. +- `` (optional). + Defines the instance to log. + NOte that `` must be specified in order to set `instance` -Теми в цьому файлі замінюють всі теми за замовчуванням, які були зареєстровані. + Якщо не вказано, всі екземпляри теми реєструються. + +The topics in this file will be added on top of the already selected topics. +To just log the topics defined in this file, set [SDLOG_PROFILE=0](../advanced_config/parameter_reference.md#SDLOG_PROFILE). +If a topic is already included, it will update it's rate. Приклади : @@ -77,7 +84,7 @@ sensor_gyro 200 sensor_mag 200 1 ``` -Ця конфігурація буде реєструвати sensor_accel 0 з повною швидкістю, sensor_accel 1 з частотою 10 Гц, всі екземпляри sensor_gyro з частотою 5 Гц та sensor_mag 1 з частотою 5 Гц. +This configuration will log sensor_accel 0 at full rate, sensor_accel 1 at 10Hz, all `sensor_gyro` instances at 5Hz and `sensor_mag` 1 at 5Hz. ## Скрипти diff --git a/docs/uk/flight_controller/corvon_743v1.md b/docs/uk/flight_controller/corvon_743v1.md index 455589c0c2..8e0ff6e956 100644 --- a/docs/uk/flight_controller/corvon_743v1.md +++ b/docs/uk/flight_controller/corvon_743v1.md @@ -11,7 +11,7 @@ It features a powerful STM32H743 processor, dual high-performance IMUs (BMI088/B With its highly integrated 36x36mm footprint and 9g weight, and specialized interfaces like a direct plug-and-play DJI O3 Air Unit connector, this flight controller is optimized for space-constrained FPV builds and agile multirotors that require top-tier processing power and sensor redundancy. -The board uses [Pixhawk Autopilot Standard Connections](https://docs.px4.io/main/en/flight_controller/autopilot_pixhawk_standard.html). +The board uses [Pixhawk Autopilot Standard Connections](../flight_controller/autopilot_pixhawk_standard.md). diff --git a/docs/uk/flight_modes_fw/guided_course.md b/docs/uk/flight_modes_fw/guided_course.md index 8ff5e7fa04..1dcdf1dc31 100644 --- a/docs/uk/flight_modes_fw/guided_course.md +++ b/docs/uk/flight_modes_fw/guided_course.md @@ -3,7 +3,7 @@ _Guided Course mode_ maintains a constant ground track (course), altitude, and airspeed without any manual stick input. -The operator controls the vehicle entirely via [GCS commands](#in-flight-commands), making it the guided equivalent of [Position mode](../flight_modes_fw/position.md). +The operator controls the vehicle entirely using [GCS commands](#supported-commands), making it the guided equivalent of [Position mode](../flight_modes_fw/position.md). :::tip This mode is suited to situations where an operator wants to guide a fixed-wing vehicle from a GCS without manual control. diff --git a/docs/uk/mavlink/security_hardening.md b/docs/uk/mavlink/security_hardening.md index 306eaef9b8..d351d14e02 100644 --- a/docs/uk/mavlink/security_hardening.md +++ b/docs/uk/mavlink/security_hardening.md @@ -92,7 +92,7 @@ If your threat model includes physical access, secure the SD card slot and debug PX4 is open-source flight controller firmware used by manufacturers and system integrators to build commercial and custom drone platforms. Securing the communication links for a specific deployment is the responsibility of the system integrator. -Це включає: +This includes: - Choosing appropriate radio hardware and link security - Enabling and managing MAVLink message signing diff --git a/docs/uk/middleware/dds_topics.md b/docs/uk/middleware/dds_topics.md index 3f0a019a66..3750165480 100644 --- a/docs/uk/middleware/dds_topics.md +++ b/docs/uk/middleware/dds_topics.md @@ -96,220 +96,220 @@ They are not build into the module, and hence are neither published or subscribe :::details See messages -- [FiducialMarkerPosReport](../msg_docs/FiducialMarkerPosReport.md) -- [VteOrientation](../msg_docs/VteOrientation.md) -- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md) -- [NeuralControl](../msg_docs/NeuralControl.md) -- [TaskStackInfo](../msg_docs/TaskStackInfo.md) -- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md) -- [SystemPower](../msg_docs/SystemPower.md) -- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md) -- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md) -- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md) -- [MavlinkLog](../msg_docs/MavlinkLog.md) -- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md) -- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md) -- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md) -- [VehicleRoi](../msg_docs/VehicleRoi.md) -- [SensorMag](../msg_docs/SensorMag.md) -- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md) -- [EstimatorStatus](../msg_docs/EstimatorStatus.md) -- [OrbTest](../msg_docs/OrbTest.md) -- [RaptorInput](../msg_docs/RaptorInput.md) -- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md) -- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md) -- [PowerMonitor](../msg_docs/PowerMonitor.md) -- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md) -- [MountOrientation](../msg_docs/MountOrientation.md) -- [VehicleStatusV2](../msg_docs/VehicleStatusV2.md) -- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md) -- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md) -- [EstimatorStates](../msg_docs/EstimatorStates.md) -- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md) -- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md) -- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md) -- [LandingGearWheel](../msg_docs/LandingGearWheel.md) -- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md) -- [ActuatorTest](../msg_docs/ActuatorTest.md) -- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md) -- [HeaterStatus](../msg_docs/HeaterStatus.md) -- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md) -- [CellularStatus](../msg_docs/CellularStatus.md) -- [SensorCorrection](../msg_docs/SensorCorrection.md) -- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md) -- [VteBiasInitStatus](../msg_docs/VteBiasInitStatus.md) -- [HealthReport](../msg_docs/HealthReport.md) -- [OrbTestLarge](../msg_docs/OrbTestLarge.md) -- [TecsStatus](../msg_docs/TecsStatus.md) -- [TakeoffStatus](../msg_docs/TakeoffStatus.md) -- [SensorGyro](../msg_docs/SensorGyro.md) -- [EscEepromWrite](../msg_docs/EscEepromWrite.md) -- [DeviceInformation](../msg_docs/DeviceInformation.md) -- [PrecLandStatus](../msg_docs/PrecLandStatus.md) -- [AdcReport](../msg_docs/AdcReport.md) -- [RcChannels](../msg_docs/RcChannels.md) -- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md) -- [CameraCapture](../msg_docs/CameraCapture.md) -- [ButtonEvent](../msg_docs/ButtonEvent.md) -- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md) -- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md) -- [FigureEightStatus](../msg_docs/FigureEightStatus.md) -- [FollowTarget](../msg_docs/FollowTarget.md) -- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md) -- [LedControl](../msg_docs/LedControl.md) -- [VelocityLimits](../msg_docs/VelocityLimits.md) -- [QshellReq](../msg_docs/QshellReq.md) -- [VehicleStatusV1](../msg_docs/VehicleStatusV1.md) -- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md) -- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md) -- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md) -- [MissionResult](../msg_docs/MissionResult.md) -- [GpioConfig](../msg_docs/GpioConfig.md) -- [ActionRequest](../msg_docs/ActionRequest.md) -- [FuelTankStatus](../msg_docs/FuelTankStatus.md) -- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md) -- [GpsDump](../msg_docs/GpsDump.md) -- [RtlStatus](../msg_docs/RtlStatus.md) -- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md) -- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md) -- [GainCompression](../msg_docs/GainCompression.md) -- [EstimatorBias](../msg_docs/EstimatorBias.md) -- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md) -- [LogMessage](../msg_docs/LogMessage.md) -- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md) -- [Rpm](../msg_docs/Rpm.md) - [CameraStatus](../msg_docs/CameraStatus.md) -- [NavigatorStatus](../msg_docs/NavigatorStatus.md) -- [GeneratorStatus](../msg_docs/GeneratorStatus.md) -- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md) -- [DebugKeyValue](../msg_docs/DebugKeyValue.md) -- [DebugValue](../msg_docs/DebugValue.md) -- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md) -- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md) -- [SensorUwb](../msg_docs/SensorUwb.md) -- [RangingBeacon](../msg_docs/RangingBeacon.md) -- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md) -- [DatamanRequest](../msg_docs/DatamanRequest.md) -- [IrlockReport](../msg_docs/IrlockReport.md) -- [ActuatorArmed](../msg_docs/ActuatorArmed.md) -- [Px4ioStatus](../msg_docs/Px4ioStatus.md) -- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md) -- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md) -- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md) -- [GeofenceStatus](../msg_docs/GeofenceStatus.md) -- [Airspeed](../msg_docs/Airspeed.md) -- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md) -- [VteAidSource1d](../msg_docs/VteAidSource1d.md) -- [DebugArray](../msg_docs/DebugArray.md) -- [VehicleConstraints](../msg_docs/VehicleConstraints.md) -- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md) -- [VehicleImu](../msg_docs/VehicleImu.md) -- [QshellRetval](../msg_docs/QshellRetval.md) -- [RegisterExtComponentRequestV1](../msg_docs/RegisterExtComponentRequestV1.md) -- [UlogStream](../msg_docs/UlogStream.md) -- [PpsCapture](../msg_docs/PpsCapture.md) -- [OrbitStatus](../msg_docs/OrbitStatus.md) -- [PowerButtonState](../msg_docs/PowerButtonState.md) -- [EscStatus](../msg_docs/EscStatus.md) -- [EstimatorFusionControl](../msg_docs/EstimatorFusionControl.md) -- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md) -- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md) -- [SensorBaro](../msg_docs/SensorBaro.md) -- [SensorAirflow](../msg_docs/SensorAirflow.md) -- [SensorTemp](../msg_docs/SensorTemp.md) -- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md) -- [OrbTestMedium](../msg_docs/OrbTestMedium.md) -- [Gripper](../msg_docs/Gripper.md) -- [SensorGyroFft](../msg_docs/SensorGyroFft.md) -- [SensorsStatus](../msg_docs/SensorsStatus.md) -- [TuneControl](../msg_docs/TuneControl.md) -- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md) -- [Vtx](../msg_docs/Vtx.md) +- [PowerMonitor](../msg_docs/PowerMonitor.md) - [EventV0](../msg_docs/EventV0.md) -- [GpioOut](../msg_docs/GpioOut.md) +- [PowerButtonState](../msg_docs/PowerButtonState.md) +- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md) +- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md) - [SatelliteInfo](../msg_docs/SatelliteInfo.md) -- [AirspeedWind](../msg_docs/AirspeedWind.md) -- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md) -- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md) -- [Ping](../msg_docs/Ping.md) -- [LoggerStatus](../msg_docs/LoggerStatus.md) -- [VteInput](../msg_docs/VteInput.md) -- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md) -- [VteAidSource3d](../msg_docs/VteAidSource3d.md) -- [CameraTrigger](../msg_docs/CameraTrigger.md) -- [GeofenceResult](../msg_docs/GeofenceResult.md) -- [TargetGnss](../msg_docs/TargetGnss.md) -- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md) -- [HomePositionV0](../msg_docs/HomePositionV0.md) -- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md) -- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md) -- [VehicleCommandAckV0](../msg_docs/VehicleCommandAckV0.md) -- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md) -- [EscReport](../msg_docs/EscReport.md) -- [GimbalControls](../msg_docs/GimbalControls.md) -- [GpioIn](../msg_docs/GpioIn.md) -- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md) -- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md) -- [BatteryInfo](../msg_docs/BatteryInfo.md) -- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md) -- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md) -- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md) -- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md) -- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md) -- [ParameterUpdate](../msg_docs/ParameterUpdate.md) -- [FiducialMarkerYawReport](../msg_docs/FiducialMarkerYawReport.md) -- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md) -- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md) -- [VtePosition](../msg_docs/VtePosition.md) -- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md) -- [VehicleStatusV3](../msg_docs/VehicleStatusV3.md) -- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md) -- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md) -- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md) -- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md) -- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md) -- [VehicleGlobalPositionV0](../msg_docs/VehicleGlobalPositionV0.md) -- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md) -- [VehicleAirData](../msg_docs/VehicleAirData.md) -- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md) +- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md) +- [HealthReport](../msg_docs/HealthReport.md) +- [VteAidSource1d](../msg_docs/VteAidSource1d.md) +- [EscEepromWrite](../msg_docs/EscEepromWrite.md) +- [GainCompression](../msg_docs/GainCompression.md) +- [NavigatorStatus](../msg_docs/NavigatorStatus.md) - [Cpuload](../msg_docs/Cpuload.md) - [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md) -- [Mission](../msg_docs/Mission.md) -- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md) -- [UlogStreamAck](../msg_docs/UlogStreamAck.md) -- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md) -- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md) -- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md) -- [PwmInput](../msg_docs/PwmInput.md) -- [InputRc](../msg_docs/InputRc.md) -- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md) -- [WheelEncoders](../msg_docs/WheelEncoders.md) -- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md) -- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md) -- [RadioStatus](../msg_docs/RadioStatus.md) -- [DebugVect](../msg_docs/DebugVect.md) -- [LandingTargetPose](../msg_docs/LandingTargetPose.md) -- [DifferentialPressure](../msg_docs/DifferentialPressure.md) -- [RoverRateStatus](../msg_docs/RoverRateStatus.md) -- [SensorHygrometer](../msg_docs/SensorHygrometer.md) -- [PositionSetpoint](../msg_docs/PositionSetpoint.md) -- [RaptorStatus](../msg_docs/RaptorStatus.md) -- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md) -- [DatamanResponse](../msg_docs/DatamanResponse.md) -- [RcParameterMap](../msg_docs/RcParameterMap.md) -- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md) -- [SensorSelection](../msg_docs/SensorSelection.md) -- [SensorAccel](../msg_docs/SensorAccel.md) +- [DeviceInformation](../msg_docs/DeviceInformation.md) +- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md) +- [BatteryInfo](../msg_docs/BatteryInfo.md) +- [MavlinkLog](../msg_docs/MavlinkLog.md) - [GpioRequest](../msg_docs/GpioRequest.md) -- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md) -- [MagWorkerData](../msg_docs/MagWorkerData.md) -- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md) -- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md) -- [Event](../msg_docs/Event.md) +- [IrlockReport](../msg_docs/IrlockReport.md) +- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md) +- [VtePosition](../msg_docs/VtePosition.md) +- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md) +- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md) +- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md) - [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md) -- [EscEepromRead](../msg_docs/EscEepromRead.md) -- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md) -- [GpsInjectData](../msg_docs/GpsInjectData.md) +- [DebugValue](../msg_docs/DebugValue.md) +- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md) +- [AdcReport](../msg_docs/AdcReport.md) +- [Px4ioStatus](../msg_docs/Px4ioStatus.md) +- [FigureEightStatus](../msg_docs/FigureEightStatus.md) +- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md) +- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md) +- [VteBiasInitStatus](../msg_docs/VteBiasInitStatus.md) +- [DatamanRequest](../msg_docs/DatamanRequest.md) +- [DifferentialPressure](../msg_docs/DifferentialPressure.md) +- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md) +- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md) +- [VehicleImu](../msg_docs/VehicleImu.md) +- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md) +- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md) +- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md) +- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md) +- [SensorsStatus](../msg_docs/SensorsStatus.md) +- [ActionRequest](../msg_docs/ActionRequest.md) +- [ActuatorArmed](../msg_docs/ActuatorArmed.md) +- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md) +- [WheelEncoders](../msg_docs/WheelEncoders.md) +- [SensorAirflow](../msg_docs/SensorAirflow.md) +- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md) +- [UlogStream](../msg_docs/UlogStream.md) +- [ButtonEvent](../msg_docs/ButtonEvent.md) +- [RadioStatus](../msg_docs/RadioStatus.md) +- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md) +- [GpioConfig](../msg_docs/GpioConfig.md) +- [PositionSetpoint](../msg_docs/PositionSetpoint.md) +- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md) +- [SensorCorrection](../msg_docs/SensorCorrection.md) +- [FiducialMarkerYawReport](../msg_docs/FiducialMarkerYawReport.md) +- [DebugArray](../msg_docs/DebugArray.md) +- [HeaterStatus](../msg_docs/HeaterStatus.md) +- [LoggerStatus](../msg_docs/LoggerStatus.md) +- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md) +- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md) +- [Mission](../msg_docs/Mission.md) +- [OrbitStatus](../msg_docs/OrbitStatus.md) +- [Event](../msg_docs/Event.md) +- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md) +- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md) +- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md) +- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md) +- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md) +- [GpsDump](../msg_docs/GpsDump.md) +- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md) +- [SystemPower](../msg_docs/SystemPower.md) +- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md) +- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md) +- [QshellRetval](../msg_docs/QshellRetval.md) +- [SensorGyro](../msg_docs/SensorGyro.md) - [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md) +- [HomePositionV0](../msg_docs/HomePositionV0.md) +- [EscReport](../msg_docs/EscReport.md) +- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md) +- [OrbTest](../msg_docs/OrbTest.md) +- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md) +- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md) +- [TuneControl](../msg_docs/TuneControl.md) +- [VehicleCommandAckV0](../msg_docs/VehicleCommandAckV0.md) +- [EstimatorStatus](../msg_docs/EstimatorStatus.md) +- [SensorBaro](../msg_docs/SensorBaro.md) +- [VehicleStatusV2](../msg_docs/VehicleStatusV2.md) +- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md) +- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md) +- [FiducialMarkerPosReport](../msg_docs/FiducialMarkerPosReport.md) +- [GeneratorStatus](../msg_docs/GeneratorStatus.md) +- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md) +- [VteAidSource3d](../msg_docs/VteAidSource3d.md) +- [VelocityLimits](../msg_docs/VelocityLimits.md) +- [GeofenceStatus](../msg_docs/GeofenceStatus.md) +- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md) +- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md) +- [NeuralControl](../msg_docs/NeuralControl.md) +- [RcParameterMap](../msg_docs/RcParameterMap.md) +- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md) +- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md) +- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md) +- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md) +- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md) +- [MissionResult](../msg_docs/MissionResult.md) +- [TargetGnss](../msg_docs/TargetGnss.md) +- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md) +- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md) +- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md) +- [VehicleStatusV1](../msg_docs/VehicleStatusV1.md) +- [LandingTargetPose](../msg_docs/LandingTargetPose.md) +- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md) +- [TakeoffStatus](../msg_docs/TakeoffStatus.md) +- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md) +- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md) +- [GpsInjectData](../msg_docs/GpsInjectData.md) +- [VteInput](../msg_docs/VteInput.md) +- [VehicleRoi](../msg_docs/VehicleRoi.md) +- [SensorTemp](../msg_docs/SensorTemp.md) +- [VehicleAirData](../msg_docs/VehicleAirData.md) +- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md) +- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md) +- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md) +- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md) +- [PrecLandStatus](../msg_docs/PrecLandStatus.md) +- [EstimatorFusionControl](../msg_docs/EstimatorFusionControl.md) +- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md) +- [DebugKeyValue](../msg_docs/DebugKeyValue.md) +- [FuelTankStatus](../msg_docs/FuelTankStatus.md) +- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md) +- [CameraTrigger](../msg_docs/CameraTrigger.md) +- [TaskStackInfo](../msg_docs/TaskStackInfo.md) +- [GeofenceResult](../msg_docs/GeofenceResult.md) +- [AirspeedWind](../msg_docs/AirspeedWind.md) +- [CameraCapture](../msg_docs/CameraCapture.md) +- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md) +- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md) +- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md) +- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md) +- [QshellReq](../msg_docs/QshellReq.md) +- [VteOrientation](../msg_docs/VteOrientation.md) +- [GpioOut](../msg_docs/GpioOut.md) +- [FollowTarget](../msg_docs/FollowTarget.md) +- [CellularStatus](../msg_docs/CellularStatus.md) +- [SensorAccel](../msg_docs/SensorAccel.md) +- [OrbTestLarge](../msg_docs/OrbTestLarge.md) +- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md) +- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md) +- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md) +- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md) +- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md) +- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md) +- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md) +- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md) +- [LandingGearWheel](../msg_docs/LandingGearWheel.md) +- [UlogStreamAck](../msg_docs/UlogStreamAck.md) +- [VehicleStatusV3](../msg_docs/VehicleStatusV3.md) +- [SensorSelection](../msg_docs/SensorSelection.md) +- [LogMessage](../msg_docs/LogMessage.md) +- [RaptorInput](../msg_docs/RaptorInput.md) +- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md) +- [EstimatorBias](../msg_docs/EstimatorBias.md) +- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md) +- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md) +- [Vtx](../msg_docs/Vtx.md) +- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md) +- [Airspeed](../msg_docs/Airspeed.md) +- [PwmInput](../msg_docs/PwmInput.md) +- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md) +- [RangingBeacon](../msg_docs/RangingBeacon.md) +- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md) +- [EscStatus](../msg_docs/EscStatus.md) +- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md) +- [SensorHygrometer](../msg_docs/SensorHygrometer.md) +- [GimbalControls](../msg_docs/GimbalControls.md) +- [RegisterExtComponentRequestV1](../msg_docs/RegisterExtComponentRequestV1.md) +- [RaptorStatus](../msg_docs/RaptorStatus.md) +- [DatamanResponse](../msg_docs/DatamanResponse.md) +- [LedControl](../msg_docs/LedControl.md) +- [RoverRateStatus](../msg_docs/RoverRateStatus.md) +- [EstimatorStates](../msg_docs/EstimatorStates.md) +- [TecsStatus](../msg_docs/TecsStatus.md) +- [DebugVect](../msg_docs/DebugVect.md) +- [PpsCapture](../msg_docs/PpsCapture.md) +- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md) +- [RtlStatus](../msg_docs/RtlStatus.md) +- [GpioIn](../msg_docs/GpioIn.md) +- [SensorGyroFft](../msg_docs/SensorGyroFft.md) +- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md) +- [RcChannels](../msg_docs/RcChannels.md) +- [EscEepromRead](../msg_docs/EscEepromRead.md) +- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md) +- [ParameterUpdate](../msg_docs/ParameterUpdate.md) +- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md) +- [Rpm](../msg_docs/Rpm.md) +- [ActuatorTest](../msg_docs/ActuatorTest.md) +- [VehicleConstraints](../msg_docs/VehicleConstraints.md) +- [SensorMag](../msg_docs/SensorMag.md) +- [OrbTestMedium](../msg_docs/OrbTestMedium.md) +- [Gripper](../msg_docs/Gripper.md) +- [InputRc](../msg_docs/InputRc.md) +- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md) +- [MountOrientation](../msg_docs/MountOrientation.md) +- [Ping](../msg_docs/Ping.md) +- [VehicleGlobalPositionV0](../msg_docs/VehicleGlobalPositionV0.md) +- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md) +- [MagWorkerData](../msg_docs/MagWorkerData.md) +- [SensorUwb](../msg_docs/SensorUwb.md) +- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md) +- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md) ::: diff --git a/docs/uk/msg_docs/versioned_old_messages.md b/docs/uk/msg_docs/versioned_old_messages.md new file mode 100644 index 0000000000..a1315ebd3c --- /dev/null +++ b/docs/uk/msg_docs/versioned_old_messages.md @@ -0,0 +1,3 @@ +# Historic (Old) Versioned Messages (uORB Message Reference) + +See [list here](../msg_docs/index.md#historic-versions). diff --git a/docs/uk/releases/1.12.md b/docs/uk/releases/1.12.md index 30b877eb98..18b63e9836 100644 --- a/docs/uk/releases/1.12.md +++ b/docs/uk/releases/1.12.md @@ -1,5 +1,17 @@ # Реліз 1.12 + + +
+
+

This page is on a release branch, and hence probably out of date. See the latest version.

+
+ +
+ - [Release 1.12](#release-1-12) - [Pre Releases](#pre-releases) - [Changes](#changes) diff --git a/docs/uk/releases/1.13.md b/docs/uk/releases/1.13.md index 0a0600cc78..22078da3db 100644 --- a/docs/uk/releases/1.13.md +++ b/docs/uk/releases/1.13.md @@ -1,5 +1,17 @@ # Реліз 1.13 + + +
+
+

This page is on a release branch, and hence probably out of date. See the latest version.

+
+ +
+ - [Release 1.13](#release-1-13) - [Pre Releases](#pre-releases) - [Changes](#changes) diff --git a/docs/uk/releases/1.14.md b/docs/uk/releases/1.14.md index 6fedc0cdce..e3666a1a1b 100644 --- a/docs/uk/releases/1.14.md +++ b/docs/uk/releases/1.14.md @@ -1,5 +1,17 @@ # PX4-Autopilot v1.14 Нотатки щодо релізу + + +
+
+

This page is on a release branch, and hence probably out of date. See the latest version.

+
+ +
+ ## Прочитайте перед оновленням The v1.14 release includes a few breaking changes for users upgrading from previous versions, in particular we are moving away from using mixer files to define the vehicle geometry, motor mappings and actuators. diff --git a/docs/uk/releases/1.15.md b/docs/uk/releases/1.15.md index ac6a8dddcc..a0e71fb039 100644 --- a/docs/uk/releases/1.15.md +++ b/docs/uk/releases/1.15.md @@ -1,5 +1,17 @@ # PX4-Autopilot v1.15 Release Notes + + +
+
+

This page is on a release branch, and hence probably out of date. See the latest version.

+
+ +
+ The v1.15 release brings lots of new upgrades and fixes, thanks in part to the tremendous community response to the 1.14 release. In particular, PX4 v1.15 brings significant improvements for developers and integrators using PX4 as a target through [ROS 2](../ros2/index.md) and the [uXRCE-DDS middleware](../middleware/uxrce_dds.md). In addition to networking and middleware updates, the new [PX4 ROS 2 Interface Library](../ros2/px4_ros2_interface_lib.md) allows flight modes written as ROS 2 applications to be peers of PX4 flight modes. diff --git a/docs/uk/releases/1.16.md b/docs/uk/releases/1.16.md index c0b9b84434..37523759d2 100644 --- a/docs/uk/releases/1.16.md +++ b/docs/uk/releases/1.16.md @@ -1,6 +1,16 @@ # PX4-Autopilot v1.16.0 Release Notes - + + +
+
+

This page is on a release branch, and hence probably out of date. See the latest version.

+
+ +
PX4 v1.16 builds on the momentum of v1.15 with significant new features and expanded hardware support thanks to our community contributions. This release introduces bidirectional DShot support sponsored by ARK, a full rover rework with dedicated firmware builds and modular control modes for Ackermann, differential and mecanum rovers, and a switch to Gazebo Harmonic LTS for more reliable simulation. diff --git a/docs/uk/releases/1.17.md b/docs/uk/releases/1.17.md index f9a71b5eb1..2bd40ac11d 100644 --- a/docs/uk/releases/1.17.md +++ b/docs/uk/releases/1.17.md @@ -1,6 +1,6 @@ # PX4-Autopilot v1.17.0 Release Notes - + + +
+
+

This page is on a release branch, and hence possibly out of date. See the latest version.

+
+ +
+ +PX4 v1.18 builds on [PX4 v1.17](../releases/1.17.md) + +:::warning +PX4 v1.18 is in alpha testing. +Update these notes with features that are going to be in `v1.18`. +For new features that aren't going into v1.18, update [`main`](../releases/main.md). +::: + +## Прочитайте перед оновленням + +- Log rotation is now enabled by default. Previously, a single log file grew for the entire flight and old logs were only deleted at boot once free space fell below a fixed 300 MB floor. The logger now caps each log file at [SDLOG_MAX_SIZE](../advanced_config/parameter_reference.md#SDLOG_MAX_SIZE) (new parameter, default `1024` MB) and keeps a configurable percentage of the disk free via [SDLOG_ROTATE](../advanced_config/parameter_reference.md#SDLOG_ROTATE) (new parameter, default `90`, so at least 10% free). Cleanup runs at log start rather than boot, so logs can still be downloaded via FTP before they are deleted. See [Log Cleanup](../dev_log/logging.md#log-cleanup) for details. +- `SDLOG_DIRS_MAX` behaviour changed: it is now an orthogonal directory-count cap that runs on top of the new space-based cleanup, and the default is `0` (disabled). Previously it enforced a fixed ~300 MB free-space floor even when set to `0`. If you relied on that implicit floor, set [SDLOG_ROTATE](../advanced_config/parameter_reference.md#SDLOG_ROTATE) instead. + +Please continue reading for [upgrade instructions](#upgrade-guide). + +## Основні зміни + +- Уточнюється + +## Інструкції для оновлення + +## Інші зміни + +### Підтримка обладнання + +- Уточнюється + +### Загальні + +- [Remote ID (Open Drone ID) in-flight failsafe](../peripherals/remote_id.md): extended [COM_ARM_ODID](../advanced_config/parameter_reference.md#COM_ARM_ODID) to also trigger a configurable failsafe action (Return, Land, or Terminate) if the Remote ID heartbeat is lost while airborne. Users previously on `COM_ARM_ODID=2` retain the same arming behaviour; set to `3` or higher to enable the in-flight action. ([PX4-Autopilot#27029](https://github.com/PX4/PX4-Autopilot/pull/27029)) +- [QGroundControl Bootloader Update](../advanced_config/bootloader_update.md#qgc-bootloader-update-sys-bl-update) via the [SYS_BL_UPDATE](../advanced_config/parameter_reference.md#SYS_BL_UPDATE) parameter has been re-enabled after being broken for a number of releases. ([PX4-Autopilot#25032: build: romf: fix generation of rc.board_bootloader_upgrade](https://github.com/PX4/PX4-Autopilot/pull/25032)). +- [Feature: Allow prioritization of manual control inputs based on their instance number in ascending or descending order](../config/manual_control.md#px4-configuration). ([PX4-Autopilot#25602: Ascending and descending manual control input priorities](https://github.com/PX4/PX4-Autopilot/pull/25602)). + +### Управління + +- Added new flight mode(s): [Altitude Cruise (MC)](../flight_modes_mc/altitude_cruise.md), Altitude Cruise (FW). + For fixed-wing the mode behaves the same as Altitude mode but you can disable the manual control loss failsafe. ([PX4-Autopilot#25435: Add new flight mode: Altitude Cruise](https://github.com/PX4/PX4-Autopilot/pull/25435)). + +### Безпека + +- Rotary-wing vehicles now support uncommanded altitude loss detection: if the vehicle descends more than [FD_ALT_LOSS](../advanced_config/parameter_reference.md#FD_ALT_LOSS) meters below its setpoint in altitude-controlled flight, flight termination (and parachute deployment) is triggered. See [Altitude Loss Trigger](../config/safety.md#altitude-loss-trigger). ([PX4-Autopilot#26837](https://github.com/PX4/PX4-Autopilot/pull/26837)) +- [Parachute health failsafe](../peripherals/parachute.md): extended [COM_PARACHUTE](../advanced_config/parameter_reference.md#COM_PARACHUTE) from a boolean into a configurable in-flight failsafe action (Return or Land) parameter. The previously enabled value `COM_PARACHUTE=1` causes a warning like before. ([PX4-Autopilot#26918](https://github.com/PX4/PX4-Autopilot/pull/26918)) +- [GNSS check failsafe](../config/safety.md#gnss-check-failsafe): new failsafe that monitors the number of usable GNSS receivers with a 3D fix and their position consistency. The required number of receivers is set via [SYS_HAS_NUM_GNSS](../advanced_config/parameter_reference.md#SYS_HAS_NUM_GNSS) and the failsafe action via [COM_GNSSLOSS_ACT](../advanced_config/parameter_reference.md#COM_GNSSLOSS_ACT). ([PX4-Autopilot#26863](https://github.com/PX4/PX4-Autopilot/pull/26863)) + +### Оцінки + +- Added [EKF2_POS_LOCK](../advanced_config/parameter_reference.md#EKF2_POS_LOCK) to force constant position fusion while landed, useful for vehicles relying on dead-reckoning sensors (airspeed, optical flow) that provide no aiding on the ground. + +### Датчики + +- Add [sbgECom INS driver](../sensor/sbgecom.md) ([PX4-Autopilot#24137](https://github.com/PX4/PX4-Autopilot/pull/24137)) +- Quick magnetometer calibration now supports specifying an arbitrary initial heading ([PX4-Autopilot#24637](https://github.com/PX4/PX4-Autopilot/pull/24637)) + +### Симуляція + +- SIH: Add option to set wind velocity ([PX4-Autopilot#26467](https://github.com/PX4-Autopilot/pull/26467)) + + + +### Debug & Logging + +- [Asset Tracking](../debug/asset_tracking.md): Automatic tracking and logging of external device information including vendor name, firmware and hardware version, serial numbers. Currently supports DroneCAN devices. ([PX4-Autopilot#25617](https://github.com/PX4/PX4-Autopilot/pull/25617)) +- Logger: support for small flash storage (e.g. 128 MB W25N NAND on kakuteh7mini, kakuteh7v2, airbrainh743). Logs can now be written directly to an internal littlefs volume instead of requiring an SD card. +- Logger: reworked log rotation and cleanup. Log rotation is now on by default, and cleanup runs at log start rather than boot so logs can be downloaded via FTP before being deleted. + - New [SDLOG_MAX_SIZE](../advanced_config/parameter_reference.md#SDLOG_MAX_SIZE) (default `1024` MB) caps the size of a single log file; once reached, the logger closes the current file and starts a new one. + - New [SDLOG_ROTATE](../advanced_config/parameter_reference.md#SDLOG_ROTATE) (default `90`) sets the maximum disk usage percentage. Cleanup guarantees `(100 - SDLOG_ROTATE)%` of the disk stays free at all times, even while writing a new log file. Set `0` to disable space-based cleanup, `100` to allow filling the disk completely. + - `SDLOG_DIRS_MAX` is now an orthogonal cap on the number of log directories (default `0` = disabled), on top of the space-based cleanup driven by `SDLOG_ROTATE` and `SDLOG_MAX_SIZE`. SITL defaults to `7`. +- New `mklittlefs` systemcmd for reformatting a littlefs volume from the NSH console, analogous to `mkfatfs` for FAT filesystems. + +### Ethernet + +- Уточнюється + +### uXRCE-DDS / Zenoh / ROS2 + +- Уточнюється + + + +### MAVLink + +- Removed support for deprecated request commands `MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES`, `MAV_CMD_REQUEST_PROTOCOL_VERSION`, `MAV_CMD_GET_HOME_POSITION`, `MAV_CMD_REQUEST_FLIGHT_INFORMATION`, `MAV_CMD_REQUEST_STORAGE_INFORMATION` (Replaced by `MAV_CMD_REQUEST_MESSAGE`). + ([PX4-Autopilot#27251: fix(mavlink): Remove deprecated MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES](https://github.com/PX4/PX4-Autopilot/pull/27251), [PX4-Autopilot#27252: fix(mavlink): Remove legacy mavlink message requestors#27252](https://github.com/PX4/PX4-Autopilot/pull/27252)) + +### RC + +- Parse ELRS Status and Link Statistics TX messages in the CRSF parser. + +### Мульти-Ротор + +- 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)). +- Renamed `MPC_HOLD_DZ` to `MAN_DEADZONE` to have it globally available in modes that allow for a dead zone. ([PX4-Autopilot#25435: Add new flight mode: Altitude Cruise](https://github.com/PX4/PX4-Autopilot/pull/25435)). + +### VTOL + +- Уточнюється + +### Літак з фіксованим крилом + +- Уточнюється + + + +### Ровер + +- Уточнюється + + + +### ROS 2 + +- Уточнюється diff --git a/docs/uk/releases/index.md b/docs/uk/releases/index.md index 7326bf48b2..aab9fa7654 100644 --- a/docs/uk/releases/index.md +++ b/docs/uk/releases/index.md @@ -1,9 +1,22 @@ # Релізи + + +
+
+

This page is on a release branch, and hence probably out of date. See the latest version.

+
+ +
+ Перелік PX4 реліз, вони містять список змін, що відбулися в кожному релізі, пояснення включених функцій, виправлень, застарілих та оновлень. -- [main](../releases/main.md) (changes planned for v1.18 or later) -- [v1.17](../releases/1.17.md) (changes in v1.17, since v1.16) +- [main](../releases/main.md) (changes planned for v1.19 or later) +- [v1.18](../releases/1.18.md) (changes in v1.18, since v1.17) +- [v1.17](../releases/1.17.md) - [v1.16](../releases/1.16.md) - [v1.15](../releases/1.15.md) - [v1.14](../releases/1.14.md) diff --git a/docs/uk/releases/main.md b/docs/uk/releases/main.md index 33f7530502..bf06addd68 100644 --- a/docs/uk/releases/main.md +++ b/docs/uk/releases/main.md @@ -13,17 +13,16 @@ const { site } = useData(); -This contains changes to PX4 `main` branch since the last major release ([PX v1.16](../releases/1.16.md)). +This contains changes to PX4 `main` branch after the next major release ([PX v1.18](../releases/1.16.md)). :::warning -PX4 v1.17 is in alpha/beta testing. -Update these notes with features that are going to be in `main` (PX4 v1.18 or later) but not the PX4 v1.17 release. +PX4 v1.18 is in alpha/beta testing. +Update these notes with features that are going to be in `main` (PX4 v1.18 or later) but not the PX4 v1.18 release. ::: ## Прочитайте перед оновленням -- Log rotation is now enabled by default. Previously, a single log file grew for the entire flight and old logs were only deleted at boot once free space fell below a fixed 300 MB floor. The logger now caps each log file at [SDLOG_MAX_SIZE](../advanced_config/parameter_reference.md#SDLOG_MAX_SIZE) (new parameter, default `1024` MB) and keeps a configurable percentage of the disk free via [SDLOG_ROTATE](../advanced_config/parameter_reference.md#SDLOG_ROTATE) (new parameter, default `90`, so at least 10% free). Cleanup runs at log start rather than boot, so logs can still be downloaded via FTP before they are deleted. See [Log Cleanup](../dev_log/logging.md#log-cleanup) for details. -- `SDLOG_DIRS_MAX` behaviour changed: it is now an orthogonal directory-count cap that runs on top of the new space-based cleanup, and the default is `0` (disabled). Previously it enforced a fixed ~300 MB free-space floor even when set to `0`. If you relied on that implicit floor, set [SDLOG_ROTATE](../advanced_config/parameter_reference.md#SDLOG_ROTATE) instead. +- Уточнюється Please continue reading for [upgrade instructions](#upgrade-guide). @@ -41,52 +40,31 @@ Please continue reading for [upgrade instructions](#upgrade-guide). ### Загальні -- [Remote ID (Open Drone ID) in-flight failsafe](../peripherals/remote_id.md): extended [COM_ARM_ODID](../advanced_config/parameter_reference.md#COM_ARM_ODID) to also trigger a configurable failsafe action (Return, Land, or Terminate) if the Remote ID heartbeat is lost while airborne. Users previously on `COM_ARM_ODID=2` retain the same arming behaviour; set to `3` or higher to enable the in-flight action. ([PX4-Autopilot#27029](https://github.com/PX4/PX4-Autopilot/pull/27029)) -- [QGroundControl Bootloader Update](../advanced_config/bootloader_update.md#qgc-bootloader-update-sys-bl-update) via the [SYS_BL_UPDATE](../advanced_config/parameter_reference.md#SYS_BL_UPDATE) parameter has been re-enabled after being broken for a number of releases. ([PX4-Autopilot#25032: build: romf: fix generation of rc.board_bootloader_upgrade](https://github.com/PX4/PX4-Autopilot/pull/25032)). -- [Feature: Allow prioritization of manual control inputs based on their instance number in ascending or descending order](../config/manual_control.md#px4-configuration). ([PX4-Autopilot#25602: Ascending and descending manual control input priorities](https://github.com/PX4/PX4-Autopilot/pull/25602)). +- Уточнюється ### Управління -- Added new flight mode(s): [Altitude Cruise (MC)](../flight_modes_mc/altitude_cruise.md), Altitude Cruise (FW). - For fixed-wing the mode behaves the same as Altitude mode but you can disable the manual control loss failsafe. ([PX4-Autopilot#25435: Add new flight mode: Altitude Cruise](https://github.com/PX4/PX4-Autopilot/pull/25435)). +- Уточнюється ### Безпека -- Rotary-wing vehicles now support uncommanded altitude loss detection: if the vehicle descends more than [FD_ALT_LOSS](../advanced_config/parameter_reference.md#FD_ALT_LOSS) meters below its setpoint in altitude-controlled flight, flight termination (and parachute deployment) is triggered. See [Altitude Loss Trigger](../config/safety.md#altitude-loss-trigger). ([PX4-Autopilot#26837](https://github.com/PX4/PX4-Autopilot/pull/26837)) -- [Parachute health failsafe](../peripherals/parachute.md): extended [COM_PARACHUTE](../advanced_config/parameter_reference.md#COM_PARACHUTE) from a boolean into a configurable in-flight failsafe action (Return or Land) parameter. The previously enabled value `COM_PARACHUTE=1` causes a warning like before. ([PX4-Autopilot#26918](https://github.com/PX4/PX4-Autopilot/pull/26918)) -- [GNSS check failsafe](../config/safety.md#gnss-check-failsafe): new failsafe that monitors the number of usable GNSS receivers with a 3D fix and their position consistency. The required number of receivers is set via [SYS_HAS_NUM_GNSS](../advanced_config/parameter_reference.md#SYS_HAS_NUM_GNSS) and the failsafe action via [COM_GNSSLOSS_ACT](../advanced_config/parameter_reference.md#COM_GNSSLOSS_ACT). ([PX4-Autopilot#26863](https://github.com/PX4/PX4-Autopilot/pull/26863)) +- Уточнюється ### Оцінки -- Added [EKF2_POS_LOCK](../advanced_config/parameter_reference.md#EKF2_POS_LOCK) to force constant position fusion while landed, useful for vehicles relying on dead-reckoning sensors (airspeed, optical flow) that provide no aiding on the ground. +- Уточнюється ### Датчики -- Add [sbgECom INS driver](../sensor/sbgecom.md) ([PX4-Autopilot#24137](https://github.com/PX4/PX4-Autopilot/pull/24137)) -- Quick magnetometer calibration now supports specifying an arbitrary initial heading ([PX4-Autopilot#24637](https://github.com/PX4/PX4-Autopilot/pull/24637)) +- Уточнюється ### Симуляція -- SIH: Add option to set wind velocity ([PX4-Autopilot#26467](https://github.com/PX4-Autopilot/pull/26467)) - - +- Уточнюється ### Debug & Logging -- [Asset Tracking](../debug/asset_tracking.md): Automatic tracking and logging of external device information including vendor name, firmware and hardware version, serial numbers. Currently supports DroneCAN devices. ([PX4-Autopilot#25617](https://github.com/PX4/PX4-Autopilot/pull/25617)) -- Logger: support for small flash storage (e.g. 128 MB W25N NAND on kakuteh7mini, kakuteh7v2, airbrainh743). Logs can now be written directly to an internal littlefs volume instead of requiring an SD card. -- Logger: reworked log rotation and cleanup. Log rotation is now on by default, and cleanup runs at log start rather than boot so logs can be downloaded via FTP before being deleted. - - New [SDLOG_MAX_SIZE](../advanced_config/parameter_reference.md#SDLOG_MAX_SIZE) (default `1024` MB) caps the size of a single log file; once reached, the logger closes the current file and starts a new one. - - New [SDLOG_ROTATE](../advanced_config/parameter_reference.md#SDLOG_ROTATE) (default `90`) sets the maximum disk usage percentage. Cleanup guarantees `(100 - SDLOG_ROTATE)%` of the disk stays free at all times, even while writing a new log file. Set `0` to disable space-based cleanup, `100` to allow filling the disk completely. - - `SDLOG_DIRS_MAX` is now an orthogonal cap on the number of log directories (default `0` = disabled), on top of the space-based cleanup driven by `SDLOG_ROTATE` and `SDLOG_MAX_SIZE`. SITL defaults to `7`. -- New `mklittlefs` systemcmd for reformatting a littlefs volume from the NSH console, analogous to `mkfatfs` for FAT filesystems. +- Уточнюється ### Ethernet @@ -96,25 +74,17 @@ Please continue reading for [upgrade instructions](#upgrade-guide). - Уточнюється - - ### MAVLink -- Removed support for deprecated request commands `MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES`, `MAV_CMD_REQUEST_PROTOCOL_VERSION`, `MAV_CMD_GET_HOME_POSITION`, `MAV_CMD_REQUEST_FLIGHT_INFORMATION`, `MAV_CMD_REQUEST_STORAGE_INFORMATION` (Replaced by `MAV_CMD_REQUEST_MESSAGE`). - ([PX4-Autopilot#27251: fix(mavlink): Remove deprecated MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES](https://github.com/PX4/PX4-Autopilot/pull/27251), [PX4-Autopilot#27252: fix(mavlink): Remove legacy mavlink message requestors#27252](https://github.com/PX4/PX4-Autopilot/pull/27252)) +- Уточнюється ### RC -- Parse ELRS Status and Link Statistics TX messages in the CRSF parser. +- Уточнюється ### Мульти-Ротор -- 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)). -- Renamed `MPC_HOLD_DZ` to `MAN_DEADZONE` to have it globally available in modes that allow for a dead zone. ([PX4-Autopilot#25435: Add new flight mode: Altitude Cruise](https://github.com/PX4/PX4-Autopilot/pull/25435)). +- Уточнюється ### VTOL @@ -124,24 +94,10 @@ Please continue reading for [upgrade instructions](#upgrade-guide). - Уточнюється - - ### Ровер - Уточнюється - - ### ROS 2 - Уточнюється diff --git a/docs/uk/releases/release_process.md b/docs/uk/releases/release_process.md index 72c912808f..c61ed7aa72 100644 --- a/docs/uk/releases/release_process.md +++ b/docs/uk/releases/release_process.md @@ -1,5 +1,17 @@ # Процес випуску + + +
+
+

This page is on a release branch, and hence probably out of date. See the latest version.

+
+ +
+ This page documents the PX4 release process for maintainers. It covers the steps from preparing a release candidate through to the final announcement. ## Загальний огляд