From dd604072c49252455f362f76b6e7a49be65d8329 Mon Sep 17 00:00:00 2001 From: Jonas Perolini <74473718+JonasPerolini@users.noreply.github.com> Date: Mon, 25 May 2026 23:27:49 +0200 Subject: [PATCH] feat(new_module): Static and moving vision-based target esitmator (Kalman Filter) (#23726) Co-authored-by: jonas --- .github/workflows/checks.yml | 4 +- Makefile | 10 +- .../airframes/1011_gazebo-classic_iris_irlock | 5 +- ROMFS/px4fmu_common/init.d/rc.mc_apps | 9 + ROMFS/px4fmu_common/init.d/rc.vtol_apps | 9 + .../fmu-v6c/visionTargetEstMoving.px4board | 96 + .../fmu-v6c/visionTargetEstStatic.px4board | 95 + boards/px4/sitl/default.px4board | 4 +- boards/px4/sitl/vtest-moving.px4board | 89 + .../vtest_all_observations.png | Bin 0 -> 113061 bytes .../vtest_bias_averaging.png | Bin 0 -> 78842 bytes .../vtest_dropout_vision_and_gnss_vel.png | Bin 0 -> 109050 bytes ...est_dropout_vision_and_gps_pos_mission.png | Bin 0 -> 102063 bytes .../vtest_dropout_vision_only.png | Bin 0 -> 98338 bytes .../vtest_innovations.png | Bin 0 -> 145352 bytes .../vtest_meas_not_fused.png | Bin 0 -> 96638 bytes .../vtest_moving_target.png | Bin 0 -> 113815 bytes .../vtest_noisy_measurements.png | Bin 0 -> 126921 bytes .../vision_target_estimator/vtest_oosm.png | Bin 0 -> 132049 bytes .../vtest_precland.png | Bin 0 -> 96838 bytes .../vision_target_estimator/vtest_yaw.png | Bin 0 -> 92793 bytes docs/en/SUMMARY.md | 2 + docs/en/advanced_features/index.md | 2 + docs/en/advanced_features/precland.md | 37 +- .../vision_target_estimator.md | 390 ++++ .../vision_target_estimator_advanced.md | 1139 ++++++++++ msg/CMakeLists.txt | 14 + msg/FiducialMarkerPosReport.msg | 14 + msg/FiducialMarkerYawReport.msg | 10 + msg/LandingTargetPose.msg | 39 +- msg/PrecLandStatus.msg | 20 + msg/TargetGnss.msg | 26 + msg/VteAidSource1d.msg | 34 + msg/VteAidSource3d.msg | 35 + msg/VteBiasInitStatus.msg | 10 + msg/VteInput.msg | 11 + msg/VteOrientation.msg | 14 + msg/VtePosition.msg | 23 + .../px4_work_queue/WorkQueueManager.hpp | 2 + platforms/common/px4_work_queue/Kconfig | 14 + src/lib/ringbuffer/CMakeLists.txt | 3 +- src/lib/ringbuffer/TimestampedRingBuffer.hpp | 154 +- ...p => TimestampedRingBufferDynamicTest.cpp} | 42 +- .../TimestampedRingBufferStaticTest.cpp | 157 ++ src/modules/ekf2/EKF2.cpp | 8 +- src/modules/ekf2/EKF2.hpp | 2 + src/modules/ekf2/params_aux_velocity.yaml | 9 + .../tasks/Auto/FlightTaskAuto.cpp | 25 +- .../tasks/Auto/FlightTaskAuto.hpp | 11 +- .../LandingTargetEstimator.cpp | 1 + .../BlockLocalPositionEstimator.hpp | 7 - .../sensors/landing_target.cpp | 6 +- src/modules/logger/logged_topics.cpp | 17 + src/modules/mavlink/mavlink_receiver.cpp | 255 +++ src/modules/mavlink/mavlink_receiver.h | 30 + src/modules/navigator/precland.cpp | 188 +- src/modules/navigator/precland.h | 48 + src/modules/navigator/precland_params.yaml | 32 + .../simulator_mavlink/SimulatorMavlink.cpp | 247 +++ .../simulator_mavlink/SimulatorMavlink.hpp | 28 + .../vision_target_estimator/CMakeLists.txt | 307 +++ src/modules/vision_target_estimator/Kconfig | 24 + .../Orientation/KF_orientation.cpp | 145 ++ .../Orientation/KF_orientation.h | 133 ++ .../Orientation/VTEOrientation.cpp | 304 +++ .../Orientation/VTEOrientation.h | 182 ++ .../vtest_derivation/derivation.py | 174 ++ .../generated/getTransitionMatrix.h | 47 + .../vtest_derivation/generated/predictCov.h | 56 + .../vtest_derivation/generated/predictState.h | 46 + .../Position/KF_position.cpp | 129 ++ .../Position/KF_position.h | 137 ++ .../Position/VTEPosition.cpp | 1690 +++++++++++++++ .../Position/VTEPosition.h | 466 +++++ .../Position/vtest_derivation/derivation.py | 220 ++ .../generated/applyCorrection.h | 76 + .../generated/computeInnovCov.h | 55 + .../generated/getTransitionMatrix.h | 48 + .../vtest_derivation/generated/predictCov.h | 67 + .../vtest_derivation/generated/predictState.h | 49 + .../vtest_derivation/generated/state.h | 49 + .../generated_moving/applyCorrection.h | 110 + .../generated_moving/computeInnovCov.h | 67 + .../generated_moving/getTransitionMatrix.h | 53 + .../generated_moving/predictCov.h | 103 + .../generated_moving/predictState.h | 52 + .../vtest_derivation/generated_moving/state.h | 55 + .../vtest_derivation/utils/__init__.py | 0 .../utils/derivation_utils.py | 180 ++ src/modules/vision_target_estimator/VTEOosm.h | 490 +++++ .../VisionTargetEst.cpp | 780 +++++++ .../vision_target_estimator/VisionTargetEst.h | 237 +++ src/modules/vision_target_estimator/common.h | 174 ++ .../tasks/PrecLandTask.cpp | 183 ++ .../tasks/PrecLandTask.h | 97 + .../vision_target_estimator/tasks/VteTask.h | 102 + .../test/CMakeLists.txt | 94 + .../test/TEST_VTEOosm.cpp | 1115 ++++++++++ .../test/TEST_VTEOrientation.cpp | 435 ++++ .../test/TEST_VTEPosition.cpp | 1840 +++++++++++++++++ .../test/TEST_VTE_KF_orientation.cpp | 373 ++++ .../test/TEST_VTE_KF_position.cpp | 633 ++++++ .../test/TEST_VTE_VisionTargetEst.cpp | 1040 ++++++++++ .../test/VTETestHelper.hpp | 308 +++ .../vision_target_estimator_params.yaml | 348 ++++ 105 files changed, 16614 insertions(+), 86 deletions(-) create mode 100644 boards/px4/fmu-v6c/visionTargetEstMoving.px4board create mode 100644 boards/px4/fmu-v6c/visionTargetEstStatic.px4board create mode 100644 boards/px4/sitl/vtest-moving.px4board create mode 100644 docs/assets/vision_target_estimator/vtest_all_observations.png create mode 100644 docs/assets/vision_target_estimator/vtest_bias_averaging.png create mode 100644 docs/assets/vision_target_estimator/vtest_dropout_vision_and_gnss_vel.png create mode 100644 docs/assets/vision_target_estimator/vtest_dropout_vision_and_gps_pos_mission.png create mode 100644 docs/assets/vision_target_estimator/vtest_dropout_vision_only.png create mode 100644 docs/assets/vision_target_estimator/vtest_innovations.png create mode 100644 docs/assets/vision_target_estimator/vtest_meas_not_fused.png create mode 100644 docs/assets/vision_target_estimator/vtest_moving_target.png create mode 100644 docs/assets/vision_target_estimator/vtest_noisy_measurements.png create mode 100644 docs/assets/vision_target_estimator/vtest_oosm.png create mode 100644 docs/assets/vision_target_estimator/vtest_precland.png create mode 100644 docs/assets/vision_target_estimator/vtest_yaw.png create mode 100644 docs/en/advanced_features/vision_target_estimator.md create mode 100644 docs/en/advanced_features/vision_target_estimator_advanced.md create mode 100644 msg/FiducialMarkerPosReport.msg create mode 100644 msg/FiducialMarkerYawReport.msg create mode 100644 msg/PrecLandStatus.msg create mode 100644 msg/TargetGnss.msg create mode 100644 msg/VteAidSource1d.msg create mode 100644 msg/VteAidSource3d.msg create mode 100644 msg/VteBiasInitStatus.msg create mode 100644 msg/VteInput.msg create mode 100644 msg/VteOrientation.msg create mode 100644 msg/VtePosition.msg rename src/lib/ringbuffer/{TimestampedRingBufferTest.cpp => TimestampedRingBufferDynamicTest.cpp} (78%) create mode 100644 src/lib/ringbuffer/TimestampedRingBufferStaticTest.cpp create mode 100644 src/modules/vision_target_estimator/CMakeLists.txt create mode 100644 src/modules/vision_target_estimator/Kconfig create mode 100644 src/modules/vision_target_estimator/Orientation/KF_orientation.cpp create mode 100644 src/modules/vision_target_estimator/Orientation/KF_orientation.h create mode 100644 src/modules/vision_target_estimator/Orientation/VTEOrientation.cpp create mode 100644 src/modules/vision_target_estimator/Orientation/VTEOrientation.h create mode 100644 src/modules/vision_target_estimator/Orientation/vtest_derivation/derivation.py create mode 100644 src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/getTransitionMatrix.h create mode 100644 src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/predictCov.h create mode 100644 src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/predictState.h create mode 100644 src/modules/vision_target_estimator/Position/KF_position.cpp create mode 100644 src/modules/vision_target_estimator/Position/KF_position.h create mode 100644 src/modules/vision_target_estimator/Position/VTEPosition.cpp create mode 100644 src/modules/vision_target_estimator/Position/VTEPosition.h create mode 100755 src/modules/vision_target_estimator/Position/vtest_derivation/derivation.py create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated/applyCorrection.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated/computeInnovCov.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated/getTransitionMatrix.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated/predictCov.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated/predictState.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated/state.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/applyCorrection.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/computeInnovCov.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/getTransitionMatrix.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/predictCov.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/predictState.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/state.h create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/utils/__init__.py create mode 100644 src/modules/vision_target_estimator/Position/vtest_derivation/utils/derivation_utils.py create mode 100644 src/modules/vision_target_estimator/VTEOosm.h create mode 100644 src/modules/vision_target_estimator/VisionTargetEst.cpp create mode 100644 src/modules/vision_target_estimator/VisionTargetEst.h create mode 100644 src/modules/vision_target_estimator/common.h create mode 100644 src/modules/vision_target_estimator/tasks/PrecLandTask.cpp create mode 100644 src/modules/vision_target_estimator/tasks/PrecLandTask.h create mode 100644 src/modules/vision_target_estimator/tasks/VteTask.h create mode 100644 src/modules/vision_target_estimator/test/CMakeLists.txt create mode 100644 src/modules/vision_target_estimator/test/TEST_VTEOosm.cpp create mode 100644 src/modules/vision_target_estimator/test/TEST_VTEOrientation.cpp create mode 100644 src/modules/vision_target_estimator/test/TEST_VTEPosition.cpp create mode 100644 src/modules/vision_target_estimator/test/TEST_VTE_KF_orientation.cpp create mode 100644 src/modules/vision_target_estimator/test/TEST_VTE_KF_position.cpp create mode 100644 src/modules/vision_target_estimator/test/TEST_VTE_VisionTargetEst.cpp create mode 100644 src/modules/vision_target_estimator/test/VTETestHelper.hpp create mode 100644 src/modules/vision_target_estimator/vision_target_estimator_params.yaml diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 9013ab11f76..e96ffc02926 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -75,7 +75,9 @@ jobs: - name: Build and run unit tests env: PX4_SBOM_DISABLE: 1 - run: make tests + run: | + make tests + make tests_vtest_moving - uses: ./.github/actions/save-ccache if: always() diff --git a/Makefile b/Makefile index 2c92d9e2ff4..f880ec91294 100644 --- a/Makefile +++ b/Makefile @@ -441,7 +441,7 @@ check_newlines: # Testing # -------------------------------------------------------------------- -.PHONY: tests tests_coverage tests_mission tests_mission_coverage tests_offboard +.PHONY: tests tests_vtest_moving tests_coverage tests_mission tests_mission_coverage tests_offboard .PHONY: rostest python_coverage tests: @@ -451,6 +451,14 @@ tests: $(eval UBSAN_OPTIONS += color=always) $(call cmake-build,px4_sitl_test) +tests_vtest_moving: + $(eval override CMAKE_ARGS += -DTESTFILTER=$(if $(TESTFILTER),$(TESTFILTER),VTE)) + $(eval override CMAKE_ARGS += -DCMAKE_TESTING=ON) + $(eval ARGS += test_results) + $(eval ASAN_OPTIONS += color=always:check_initialization_order=1:detect_stack_use_after_return=1) + $(eval UBSAN_OPTIONS += color=always) + $(call cmake-build,px4_sitl_vtest-moving) + # work around lcov bug #316; remove once lcov is fixed (see https://github.com/linux-test-project/lcov/issues/316) LCOBUG = --ignore-errors mismatch,negative tests_coverage: diff --git a/ROMFS/px4fmu_common/init.d-posix/airframes/1011_gazebo-classic_iris_irlock b/ROMFS/px4fmu_common/init.d-posix/airframes/1011_gazebo-classic_iris_irlock index 2f064e2c5ff..29776d8f9d3 100644 --- a/ROMFS/px4fmu_common/init.d-posix/airframes/1011_gazebo-classic_iris_irlock +++ b/ROMFS/px4fmu_common/init.d-posix/airframes/1011_gazebo-classic_iris_irlock @@ -35,4 +35,7 @@ param set-default PLD_HACC_RAD 0.1 param set-default RTL_PLD_MD 2 # Start up Landing Target Estimator module -landing_target_estimator start +if param compare VTE_EN 0 +then + landing_target_estimator start +fi diff --git a/ROMFS/px4fmu_common/init.d/rc.mc_apps b/ROMFS/px4fmu_common/init.d/rc.mc_apps index 24a3f81ed70..e826cacf791 100644 --- a/ROMFS/px4fmu_common/init.d/rc.mc_apps +++ b/ROMFS/px4fmu_common/init.d/rc.mc_apps @@ -25,6 +25,15 @@ then mc_autotune_attitude_control start fi +# +# Start Vision Target Estimator. +# + +if param greater -s VTE_EN 0 +then + vision_target_estimator start +fi + # # Start Multicopter Position Controller. # diff --git a/ROMFS/px4fmu_common/init.d/rc.vtol_apps b/ROMFS/px4fmu_common/init.d/rc.vtol_apps index 16fb6ee5d66..2efa29709d9 100644 --- a/ROMFS/px4fmu_common/init.d/rc.vtol_apps +++ b/ROMFS/px4fmu_common/init.d/rc.vtol_apps @@ -25,6 +25,15 @@ then mc_autotune_attitude_control start fi +# +# Start Vision Target Estimator. +# + +if param greater -s VTE_EN 0 +then + vision_target_estimator start +fi + fw_rate_control start vtol fw_att_control start vtol fw_mode_manager start diff --git a/boards/px4/fmu-v6c/visionTargetEstMoving.px4board b/boards/px4/fmu-v6c/visionTargetEstMoving.px4board new file mode 100644 index 00000000000..e87c6ee8eb6 --- /dev/null +++ b/boards/px4/fmu-v6c/visionTargetEstMoving.px4board @@ -0,0 +1,96 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0" +CONFIG_BOARD_SERIAL_GPS2="/dev/ttyS6" +CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS5" +CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS3" +CONFIG_BOARD_SERIAL_TEL3="/dev/ttyS1" +CONFIG_DRIVERS_ADC_BOARD_ADC=y +CONFIG_DRIVERS_BAROMETER_MS5611=y +CONFIG_DRIVERS_BATT_SMBUS=y +CONFIG_DRIVERS_CAMERA_CAPTURE=y +CONFIG_DRIVERS_CAMERA_TRIGGER=y +CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y +CONFIG_COMMON_DISTANCE_SENSOR=y +CONFIG_DRIVERS_DSHOT=y +CONFIG_DRIVERS_GPS=y +CONFIG_DRIVERS_HEATER=y +CONFIG_COMMON_INS=n +CONFIG_COMMON_LIGHT=y +CONFIG_COMMON_MAGNETOMETER=y +CONFIG_COMMON_OPTICAL_FLOW=y +CONFIG_DRIVERS_POWER_MONITOR_INA226=y +CONFIG_DRIVERS_POWER_MONITOR_INA228=y +CONFIG_DRIVERS_POWER_MONITOR_INA238=y +CONFIG_DRIVERS_PWM_OUT=y +CONFIG_DRIVERS_PX4IO=y +CONFIG_COMMON_TELEMETRY=y +CONFIG_DRIVERS_TONE_ALARM=y +CONFIG_DRIVERS_UAVCAN=y +CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE=2 +CONFIG_MODULES_AIRSPEED_SELECTOR=y +CONFIG_MODULES_BATTERY_STATUS=y +CONFIG_MODULES_COMMANDER=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_EKF2=y +CONFIG_MODULES_ESC_BATTERY=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_FLIGHT_MODE_MANAGER=y +CONFIG_MODULES_FW_ATT_CONTROL=y +CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_FW_POS_CONTROL=y +CONFIG_MODULES_FW_RATE_CONTROL=y +CONFIG_MODULES_GYRO_CALIBRATION=y +CONFIG_MODULES_GYRO_FFT=y +CONFIG_MODULES_LAND_DETECTOR=y +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y +CONFIG_MODULES_MANUAL_CONTROL=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MODULES_MC_ATT_CONTROL=y +CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y +CONFIG_MODULES_MC_POS_CONTROL=y +CONFIG_MODULES_MC_RATE_CONTROL=y +CONFIG_MODULES_NAVIGATOR=y +CONFIG_MODULES_RC_UPDATE=y +CONFIG_MODULES_SENSORS=y +CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=y +CONFIG_MODULES_TEMPERATURE_COMPENSATION=y +CONFIG_MODULES_VTOL_ATT_CONTROL=y +CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y +CONFIG_SYSTEMCMDS_BSONDUMP=y +CONFIG_SYSTEMCMDS_DMESG=y +CONFIG_SYSTEMCMDS_HARDFAULT_LOG=y +CONFIG_SYSTEMCMDS_I2CDETECT=y +CONFIG_SYSTEMCMDS_LED_CONTROL=y +CONFIG_SYSTEMCMDS_MFT=y +CONFIG_SYSTEMCMDS_MTD=y +CONFIG_SYSTEMCMDS_NSHTERM=y +CONFIG_SYSTEMCMDS_PARAM=y +CONFIG_SYSTEMCMDS_PERF=y +CONFIG_SYSTEMCMDS_REBOOT=y +CONFIG_SYSTEMCMDS_SD_BENCH=y +CONFIG_SYSTEMCMDS_SYSTEM_TIME=y +CONFIG_SYSTEMCMDS_TOP=y +CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y +CONFIG_SYSTEMCMDS_TUNE_CONTROL=y +CONFIG_SYSTEMCMDS_UORB=y +CONFIG_SYSTEMCMDS_VER=y +CONFIG_SYSTEMCMDS_WORK_QUEUE=y + +CONFIG_MAVLINK_DIALECT="development" +CONFIG_MODULES_VISION_TARGET_ESTIMATOR=y +CONFIG_VTEST_MOVING=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=n +CONFIG_MODULES_ROVER_POS_CONTROL=n +CONFIG_MODULES_CAMERA_FEEDBACK=n +CONFIG_MODULES_GIMBAL=n +CONFIG_MODULES_UXRCE_DDS_CLIENT=n +CONFIG_UXRCE_DDS_CLIENT_SERIAL=n +CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=n +CONFIG_DRIVERS_GNSS_SEPTENTRIO=n +CONFIG_DRIVERS_IMU_BOSCH_BMI055=n +CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y diff --git a/boards/px4/fmu-v6c/visionTargetEstStatic.px4board b/boards/px4/fmu-v6c/visionTargetEstStatic.px4board new file mode 100644 index 00000000000..244d8b4ec5b --- /dev/null +++ b/boards/px4/fmu-v6c/visionTargetEstStatic.px4board @@ -0,0 +1,95 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0" +CONFIG_BOARD_SERIAL_GPS2="/dev/ttyS6" +CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS5" +CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS3" +CONFIG_BOARD_SERIAL_TEL3="/dev/ttyS1" +CONFIG_DRIVERS_ADC_BOARD_ADC=y +CONFIG_DRIVERS_BAROMETER_MS5611=y +CONFIG_DRIVERS_BATT_SMBUS=y +CONFIG_DRIVERS_CAMERA_CAPTURE=y +CONFIG_DRIVERS_CAMERA_TRIGGER=y +CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y +CONFIG_COMMON_DISTANCE_SENSOR=y +CONFIG_DRIVERS_DSHOT=y +CONFIG_DRIVERS_GPS=y +CONFIG_DRIVERS_HEATER=y +CONFIG_COMMON_INS=n +CONFIG_COMMON_LIGHT=y +CONFIG_COMMON_MAGNETOMETER=y +CONFIG_COMMON_OPTICAL_FLOW=y +CONFIG_DRIVERS_POWER_MONITOR_INA226=y +CONFIG_DRIVERS_POWER_MONITOR_INA228=y +CONFIG_DRIVERS_POWER_MONITOR_INA238=y +CONFIG_DRIVERS_PWM_OUT=y +CONFIG_DRIVERS_PX4IO=y +CONFIG_COMMON_TELEMETRY=y +CONFIG_DRIVERS_TONE_ALARM=y +CONFIG_DRIVERS_UAVCAN=y +CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE=2 +CONFIG_MODULES_AIRSPEED_SELECTOR=y +CONFIG_MODULES_BATTERY_STATUS=y +CONFIG_MODULES_COMMANDER=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_EKF2=y +CONFIG_MODULES_ESC_BATTERY=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_FLIGHT_MODE_MANAGER=y +CONFIG_MODULES_FW_ATT_CONTROL=y +CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_FW_POS_CONTROL=y +CONFIG_MODULES_FW_RATE_CONTROL=y +CONFIG_MODULES_GYRO_CALIBRATION=y +CONFIG_MODULES_GYRO_FFT=y +CONFIG_MODULES_LAND_DETECTOR=y +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y +CONFIG_MODULES_MANUAL_CONTROL=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MODULES_MC_ATT_CONTROL=y +CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y +CONFIG_MODULES_MC_POS_CONTROL=y +CONFIG_MODULES_MC_RATE_CONTROL=y +CONFIG_MODULES_NAVIGATOR=y +CONFIG_MODULES_RC_UPDATE=y +CONFIG_MODULES_SENSORS=y +CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=y +CONFIG_MODULES_TEMPERATURE_COMPENSATION=y +CONFIG_MODULES_VTOL_ATT_CONTROL=y +CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y +CONFIG_SYSTEMCMDS_BSONDUMP=y +CONFIG_SYSTEMCMDS_DMESG=y +CONFIG_SYSTEMCMDS_HARDFAULT_LOG=y +CONFIG_SYSTEMCMDS_I2CDETECT=y +CONFIG_SYSTEMCMDS_LED_CONTROL=y +CONFIG_SYSTEMCMDS_MFT=y +CONFIG_SYSTEMCMDS_MTD=y +CONFIG_SYSTEMCMDS_NSHTERM=y +CONFIG_SYSTEMCMDS_PARAM=y +CONFIG_SYSTEMCMDS_PERF=y +CONFIG_SYSTEMCMDS_REBOOT=y +CONFIG_SYSTEMCMDS_SD_BENCH=y +CONFIG_SYSTEMCMDS_SYSTEM_TIME=y +CONFIG_SYSTEMCMDS_TOP=y +CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y +CONFIG_SYSTEMCMDS_TUNE_CONTROL=y +CONFIG_SYSTEMCMDS_UORB=y +CONFIG_SYSTEMCMDS_VER=y +CONFIG_SYSTEMCMDS_WORK_QUEUE=y + +CONFIG_MAVLINK_DIALECT="development" +CONFIG_MODULES_VISION_TARGET_ESTIMATOR=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=n +CONFIG_MODULES_ROVER_POS_CONTROL=n +CONFIG_MODULES_CAMERA_FEEDBACK=n +CONFIG_MODULES_GIMBAL=n +CONFIG_MODULES_UXRCE_DDS_CLIENT=n +CONFIG_UXRCE_DDS_CLIENT_SERIAL=n +CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=n +CONFIG_DRIVERS_GNSS_SEPTENTRIO=n +CONFIG_DRIVERS_IMU_BOSCH_BMI055=n +CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y diff --git a/boards/px4/sitl/default.px4board b/boards/px4/sitl/default.px4board index e2a3996ca36..3e2edf7ea26 100644 --- a/boards/px4/sitl/default.px4board +++ b/boards/px4/sitl/default.px4board @@ -28,7 +28,7 @@ CONFIG_MODULES_GIMBAL=y CONFIG_MODULES_GYRO_CALIBRATION=y CONFIG_MODULES_GYRO_FFT=y CONFIG_MODULES_LAND_DETECTOR=y -CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=n CONFIG_MODULES_LOAD_MON=y CONFIG_MODULES_LOCAL_POSITION_ESTIMATOR=y CONFIG_MODULES_LOGGER=y @@ -59,6 +59,7 @@ CONFIG_MODULES_TEMPERATURE_COMPENSATION=y CONFIG_MODULES_UUV_ATT_CONTROL=y CONFIG_MODULES_UUV_POS_CONTROL=y CONFIG_MODULES_UXRCE_DDS_CLIENT=y +CONFIG_MODULES_VISION_TARGET_ESTIMATOR=y CONFIG_MODULES_VTOL_ATT_CONTROL=y CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y CONFIG_SYSTEMCMDS_BSONDUMP=y @@ -84,3 +85,4 @@ CONFIG_EXAMPLES_PX4_MAVLINK_DEBUG=y CONFIG_EXAMPLES_PX4_SIMPLE_APP=y CONFIG_EXAMPLES_WORK_ITEM=y CONFIG_MODULES_SPACECRAFT=n +CONFIG_MAVLINK_DIALECT="development" diff --git a/boards/px4/sitl/vtest-moving.px4board b/boards/px4/sitl/vtest-moving.px4board new file mode 100644 index 00000000000..cf43b2efeb7 --- /dev/null +++ b/boards/px4/sitl/vtest-moving.px4board @@ -0,0 +1,89 @@ +CONFIG_PLATFORM_POSIX=y +CONFIG_BOARD_TESTING=y +CONFIG_BOARD_ETHERNET=y +CONFIG_BOARD_ROOT_PATH="." +CONFIG_DRIVERS_CAMERA_TRIGGER=y +CONFIG_DRIVERS_GPS=y +CONFIG_DRIVERS_GNSS_SEPTENTRIO=y +CONFIG_DRIVERS_OSD_MSP_OSD=y +CONFIG_DRIVERS_TONE_ALARM=y +CONFIG_MODULES_AIRSHIP_ATT_CONTROL=y +CONFIG_MODULES_AIRSPEED_SELECTOR=y +CONFIG_MODULES_ATTITUDE_ESTIMATOR_Q=y +CONFIG_MODULES_CAMERA_FEEDBACK=y +CONFIG_MODULES_COMMANDER=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_EKF2=y +CONFIG_EKF2_VERBOSE_STATUS=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_FLIGHT_MODE_MANAGER=y +CONFIG_MODULES_FW_ATT_CONTROL=y +CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_FW_MODE_MANAGER=y +CONFIG_MODULES_FW_LATERAL_LONGITUDINAL_CONTROL=y +CONFIG_FIGURE_OF_EIGHT=y +CONFIG_MODULES_FW_RATE_CONTROL=y +CONFIG_MODULES_GIMBAL=y +CONFIG_MODULES_GYRO_CALIBRATION=y +CONFIG_MODULES_GYRO_FFT=y +CONFIG_MODULES_LAND_DETECTOR=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=n +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOCAL_POSITION_ESTIMATOR=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y +CONFIG_MODULES_MANUAL_CONTROL=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MODULES_MC_ATT_CONTROL=y +CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y +CONFIG_MODULES_MC_POS_CONTROL=y +CONFIG_MODULES_MC_RATE_CONTROL=y +CONFIG_MODULES_NAVIGATOR=y +CONFIG_MODE_NAVIGATOR_VTOL_TAKEOFF=y +CONFIG_NUM_MISSION_ITMES_SUPPORTED=10000 +CONFIG_MODULES_PAYLOAD_DELIVERER=y +CONFIG_MODULES_RC_UPDATE=y +CONFIG_MODULES_REPLAY=y +CONFIG_MODULES_ROVER_ACKERMANN=y +CONFIG_MODULES_ROVER_DIFFERENTIAL=y +CONFIG_MODULES_ROVER_MECANUM=y +CONFIG_MODULES_SENSORS=y +CONFIG_COMMON_SIMULATION=y +CONFIG_MODULES_SIMULATION_GZ_MSGS=y +CONFIG_MODULES_SIMULATION_GZ_BRIDGE=y +CONFIG_MODULES_SIMULATION_GZ_PLUGINS=y +CONFIG_MODULES_SIMULATION_SENSOR_AGP_SIM=y +CONFIG_MODULES_TEMPERATURE_COMPENSATION=y +CONFIG_MODULES_UUV_ATT_CONTROL=y +CONFIG_MODULES_UUV_POS_CONTROL=y +CONFIG_MODULES_UXRCE_DDS_CLIENT=y +CONFIG_MODULES_VISION_TARGET_ESTIMATOR=y +CONFIG_MODULES_VTOL_ATT_CONTROL=y +CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y +CONFIG_SYSTEMCMDS_BSONDUMP=y +CONFIG_SYSTEMCMDS_DYN=y +CONFIG_SYSTEMCMDS_FAILURE=y +CONFIG_SYSTEMCMDS_LED_CONTROL=y +CONFIG_SYSTEMCMDS_PARAM=y +CONFIG_SYSTEMCMDS_PERF=y +CONFIG_SYSTEMCMDS_SD_BENCH=y +CONFIG_SYSTEMCMDS_SHUTDOWN=y +CONFIG_SYSTEMCMDS_SYSTEM_TIME=y +CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y +CONFIG_SYSTEMCMDS_TUNE_CONTROL=y +CONFIG_SYSTEMCMDS_UORB=y +CONFIG_SYSTEMCMDS_VER=y +CONFIG_SYSTEMCMDS_WORK_QUEUE=y +CONFIG_EXAMPLES_DYN_HELLO=y +CONFIG_EXAMPLES_FAKE_GPS=y +CONFIG_EXAMPLES_FAKE_IMU=y +CONFIG_EXAMPLES_FAKE_MAGNETOMETER=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_PX4_MAVLINK_DEBUG=y +CONFIG_EXAMPLES_PX4_SIMPLE_APP=y +CONFIG_EXAMPLES_WORK_ITEM=y +CONFIG_MODULES_SPACECRAFT=n +CONFIG_MAVLINK_DIALECT="development" +CONFIG_VTEST_MOVING=y diff --git a/docs/assets/vision_target_estimator/vtest_all_observations.png b/docs/assets/vision_target_estimator/vtest_all_observations.png new file mode 100644 index 0000000000000000000000000000000000000000..c1cee255774981ccb319d87943b1cf1003175238 GIT binary patch literal 113061 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 Zs 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 TvAr0Z00000NkvXXu0mjf(Y@dI literal 0 HcmV?d00001 diff --git a/docs/assets/vision_target_estimator/vtest_bias_averaging.png b/docs/assets/vision_target_estimator/vtest_bias_averaging.png new file mode 100644 index 0000000000000000000000000000000000000000..9c6899fe9454cb4f52ff33f6feab08ce7b9271c4 GIT binary patch literal 78842 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 literal 0 HcmV?d00001 diff --git a/docs/assets/vision_target_estimator/vtest_dropout_vision_and_gnss_vel.png b/docs/assets/vision_target_estimator/vtest_dropout_vision_and_gnss_vel.png new file mode 100644 index 0000000000000000000000000000000000000000..2eb5ced4c1ac859613f0370e2963a90f56722c9a GIT binary patch literal 109050 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 literal 0 HcmV?d00001 diff --git a/docs/assets/vision_target_estimator/vtest_dropout_vision_and_gps_pos_mission.png b/docs/assets/vision_target_estimator/vtest_dropout_vision_and_gps_pos_mission.png new file mode 100644 index 0000000000000000000000000000000000000000..6953a8dc719e41e6006c6f1295e7974f4744d78d GIT binary patch literal 102063 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 literal 0 HcmV?d00001 diff --git a/docs/assets/vision_target_estimator/vtest_moving_target.png b/docs/assets/vision_target_estimator/vtest_moving_target.png new file mode 100644 index 0000000000000000000000000000000000000000..408f5b26cf9c504eac70deb10ed1756e093a9c6a GIT binary patch literal 113815 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 literal 0 HcmV?d00001 diff --git a/docs/assets/vision_target_estimator/vtest_noisy_measurements.png b/docs/assets/vision_target_estimator/vtest_noisy_measurements.png new file mode 100644 index 0000000000000000000000000000000000000000..833d1030c3201e47bdfb5afd5d93bf1933a189e1 GIT binary patch literal 126921 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 z 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

Ib854PaTsKb6|p(%`9!LpYCRklAp+mR1SN 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[SENS_EN_IRLOCK](../advanced_config/parameter_reference.md#SENS_EN_IRLOCK) | IR-LOCK Sensor (external I2C). Disable: `0` (default): Enable: `1`). | -| [LTEST_MODE](../advanced_config/parameter_reference.md#LTEST_MODE) | Landing target is moving (`0`) or stationary (`1`). Default is moving. | -| [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) | Horizontal acceptance radius, within which the vehicle will start descending. Default is 0.2m. | -| [PLD_BTOUT](../advanced_config/parameter_reference.md#PLD_BTOUT) | Landing Target Timeout, after which the target is assumed lost. Default is 5 seconds. | -| [PLD_FAPPR_ALT](../advanced_config/parameter_reference.md#PLD_FAPPR_ALT) | Final approach altitude. Default is 0.1 metres. | -| [PLD_MAX_SRCH](../advanced_config/parameter_reference.md#PLD_MAX_SRCH) | Maximum number of search attempts in an required landing. | -| [RTL_PLD_MD](../advanced_config/parameter_reference.md#RTL_PLD_MD) | RTL precision land mode. `0`: disabled, `1`: [Opportunistic](#opportunistic-mode), `2`: [Required](#required-mode). | +| Parameter | Description | +| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| [SENS_EN_IRLOCK](../advanced_config/parameter_reference.md#SENS_EN_IRLOCK) | IR-LOCK Sensor (external I2C). Disable: `0` (default): Enable: `1`). | +| [LTEST_MODE](../advanced_config/parameter_reference.md#LTEST_MODE) | Landing target is moving (`0`) or stationary (`1`). Default is moving. | +| [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) | Horizontal acceptance radius, within which the vehicle will start descending. Default is 0.2m. | +| [PLD_MOVING_T_MIN](../advanced_config/parameter_reference.md#PLD_MOVING_T_MIN) | Minimum moving-target prediction time for the precision landing setpoint. | +| [PLD_MOVING_T_MAX](../advanced_config/parameter_reference.md#PLD_MOVING_T_MAX) | Maximum moving-target prediction time for the precision landing setpoint. | +| [PLD_BTOUT](../advanced_config/parameter_reference.md#PLD_BTOUT) | Landing Target Timeout, after which the target is assumed lost. Default is 5 seconds. | +| [PLD_FAPPR_ALT](../advanced_config/parameter_reference.md#PLD_FAPPR_ALT) | Final approach altitude. Default is 0.1 metres. | +| [PLD_MAX_SRCH](../advanced_config/parameter_reference.md#PLD_MAX_SRCH) | Maximum number of search attempts in a required landing. | +| [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN) | Enable yaw alignment during precision landing when target orientation is available. | +| [RTL_PLD_MD](../advanced_config/parameter_reference.md#RTL_PLD_MD) | RTL precision land mode. `0`: disabled, `1`: [Opportunistic](#opportunistic-mode), `2`: [Required](#required-mode). | ### IR Beacon Scaling diff --git a/docs/en/advanced_features/vision_target_estimator.md b/docs/en/advanced_features/vision_target_estimator.md new file mode 100644 index 00000000000..db3b1b8a615 --- /dev/null +++ b/docs/en/advanced_features/vision_target_estimator.md @@ -0,0 +1,390 @@ +# Vision Target Estimator (VTEST) + + + +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. +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. +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. +::: + +## Table of Contents + +[[toc]] + +## Building the Module + +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_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. + +Two prebuilt targets are available: + +- `make px4_fmu-v6c_visionTargetEstStatic`: static-target hardware build. +- `make px4_sitl_default`: SITL static-target build. + +For the experimental moving-target build, see [Moving-target mode](../advanced_features/vision_target_estimator_advanced.md#moving-target-mode-experimental). + +## Configuration + +### 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. + +### 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. + +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_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. + +### 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_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: + +- 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. + +### Task Selection + +[VTE_TASK_MASK](../advanced_config/parameter_reference.md#VTE_TASK_MASK) is a bitmask that selects the runtime tasks for which the estimators perform computations and estimate the state of the target. +Set the indicated bit to enable the corresponding task. + +| Bit | Task | +| --- | --------------------- | +| 0 | Precision landing | +| 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. +::: + +### Sensor Fusion Selection + +[VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) is a bitmask that defines which measurements can be fused: + +| Bit | Meaning | +| --- | ----------------------------------------------------------------------------------------------------------------------------------- | +| 0 | Target GNSS position | +| 1 | Vehicle GNSS velocity | +| 2 | Vision-relative position | +| 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. + +**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. + +**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). + +**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 + +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). + +- **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. +- **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. +- **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. + +### 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. + 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 + +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. +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: + +- `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 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 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_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 + +The estimator receives target information through two MAVLink messages emitted by an onboard companion (vision pipeline and/or external GNSS receiver): + +- [TARGET_RELATIVE](https://mavlink.io/en/messages/development.html#TARGET_RELATIVE) carries each vision-based observation of the target. +- [TARGET_ABSOLUTE](https://mavlink.io/en/messages/development.html#TARGET_ABSOLUTE) carries absolute target state from a GNSS receiver mounted on the target. + +::: info +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 + +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](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: + +- A coordinate frame selector (`TARGET_OBS_FRAME`) and a sensor quaternion (`q_sensor`) that, when provided, rotates the measurement into vehicle-carried NED. +- Target pose (`x`, `y`, `z`, `q_target`) and variances (`pos_std`, `yaw_std`), collected from onboard vision pipelines. + +`mavlink_receiver` validates the frame/type and handles the message differently depending on the Vision Target Estimator status: + +- When `VTE_EN=0`, the measurement is rotated (using `q_sensor` or the vehicle attitude for body-frame reports) and published straight to `landing_target_pose` so precision-landing can operate without the estimator. +- 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](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. +PX4 maps the available content into the `target_gnss` uORB topic: + +- Bit 0 (position) triggers publication of latitude/longitude/altitude along with the horizontal and vertical accuracy estimates (`position_std`). +- 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. + +## Gazebo Classic Simulation + +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). + +::: 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. +::: + +1. Launch the simulator with: + + ```sh + make px4_sitl gazebo-classic_iris_irlock + ``` + +2. If CMake cannot locate the expected OpenCV version, query the version present on your system (`opencv_version --short` or `pkg-config --modversion opencv4`) and update `Tools/simulation/gazebo-classic/sitl_gazebo-classic/CMakeLists.txt` accordingly, for example: + + ```cmake + find_package(OpenCV 4.2.0 REQUIRED EXACT) + ``` + + Re-run the build after adjusting the `find_package` line. + +::: tip + +- **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. +- **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. + +::: + +## Monitoring + +For detailed log-analysis guidance, see [Log analysis and expected plots](../advanced_features/vision_target_estimator_advanced.md#log-analysis-and-expected-plots) in the deep dive. + +On the autopilot shell, the first command to run is + +```sh +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. + +- `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. + +## 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. +- 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 topic | H structure | Notes | +| ---------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 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/en/advanced_features/vision_target_estimator_advanced.md b/docs/en/advanced_features/vision_target_estimator_advanced.md new file mode 100644 index 00000000000..a9e24519e47 --- /dev/null +++ b/docs/en/advanced_features/vision_target_estimator_advanced.md @@ -0,0 +1,1139 @@ +# Vision Target Estimator Deep Dive + + + +This guide expands on the [Vision Target Estimator module overview](../advanced_features/vision_target_estimator.md) and targets advanced users who want to tune, extend, and debug the estimator in detail. +It documents the system architecture of the Vision Target Estimator, and outlines workflows for log analysis and sensor integration. + +## Table of Contents + +[[toc]] + +## System Architecture + +The implementation is split across 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. +- `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. +- `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). + - 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]$. +- Shared utilities live in `common.h` and `VTEOosm.h` (templated OOSM manager, see [OOSM Implementation](#oosm-implementation)). + +```text +VisionTargetEst (work item, 50 Hz) +├── tasks/ priority-ordered registry, scheduler picks the first ready task +│ ├── VteTask task interface + VTE_TASK_MASK bits +│ └── PrecLandTask precision-landing activation/exit logic +├── VTEPosition per-axis filters, observation buffers, vte_* topic publication +│ ├── KF_position 1D Kalman math (SymForce-generated predict/correct) +│ └── bias init state machine reconciles GNSS-vs-vision bias before fusion +├── VTEOrientation yaw fusion +│ └── KF_orientation SymForce-generated predict, hand-written correct with yaw wrap +└── shared utilities common.h, VTEOosm.h (templated OOSM history buffer) +``` + +## Bias Initialization Design + +The bias state exists because the absolute target reference and the relative vision reference do not necessarily agree: + +- If [`VTE_AID_MASK`](../advanced_features/vision_target_estimator.md#sensor-fusion-selection) uses the mission landing point, that waypoint can be offset from the real pad. +- If [`VTE_AID_MASK`](../advanced_features/vision_target_estimator.md#sensor-fusion-selection) uses target GNSS, the target receiver can still be off by metres when it is not RTK-grade. +- Vision measures the target relative to the vehicle, so it can be locally accurate even when the absolute GNSS reference is biased. + +VTE therefore models GNSS-like position observations as `z = r + b` once the bias becomes observable. +This lets corrected GNSS continue to point to the target when vision drops out. + +Naive bias initialization is not robust: + +- **Zero bias** assumes GNSS and vision already agree. + If the real offset is large, the first vision updates can look like outliers and get rejected. +- **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: + +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. + +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. + +## Balancing Process and Observation Noise + +Two distinct noise tunings shape the filter's behaviour, and the right trade-off has to be found on both: + +- The **observation noise** of each sensor sets how much that sensor is trusted relative to others within a single fusion step. + Larger reported variance means a smaller Kalman gain and less influence on the state. +- The **process noise** of the prediction model sets how much the prediction is trusted between updates. + 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). + +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. + +Tune them together so the resulting gain produces the response speed and noise rejection you actually want. + +### 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 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: + +$$ +R_{\text{eff}} = \max\bigl(R_{\text{reported}},\ \text{VTE\_*\_NOISE}^2\bigr). +$$ + +| Parameter | Units | Default | Applies to | +| ------------------------------------------------------------------------------ | ----- | ------- | ---------------------------------- | +| [VTE_EVP_NOISE](../advanced_config/parameter_reference.md#VTE_EVP_NOISE) | m | 0.10 | Vision relative position | +| [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE) | rad | 0.07 | Vision yaw | +| [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. + +Two common mis-tunes: + +1. **Floor too tight** (for example `VTE_EVP_NOISE = 0.01` for a marker pipeline that is really 10 cm accurate): the filter is told to trust every sample to within 1 cm, so legitimate per-sample noise looks like outliers, the [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) gate fires often, and the few samples that pass cause state overshoots. +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. + +| Parameter | 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) | + +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 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. +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: + +$$ +\sigma(t) = \sqrt{\text{spectral density} \cdot t} +$$ + +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. + +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: + +| 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 + +The deterministic prediction uses the measured inputs to advance the mean state. +Process noise describes how wrong that prediction might be. +For the static-target position filter, the per-axis continuous-time model can be read as: + +$$ +\begin{aligned} +\dot r &= -v^{uav} \\ +\dot v^{uav} &= a^{uav}_{meas} + w_a \\ +\dot b &= w_b +\end{aligned} +$$ + +where: + +- `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**. +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: + +$$ +\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}, +$$ + +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 does not feed any other state in the prediction model, so [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) contributes only: + +$$ +\Delta\,\text{var}(b) = q_b\,dt. +$$ + +In moving-target builds, [VTE_ACC_T_UNC](../advanced_config/parameter_reference.md#VTE_ACC_T_UNC) is target jerk noise. +It drives the derivative of target acceleration: + +$$ +\dot a^t = w_j. +$$ + +The target acceleration noise then reaches target velocity after one integration and relative position after two integrations. + +The implementation integrates the full continuous-time noise response, including cross-covariances, and SymForce writes the closed-form result into `Position/vtest_derivation/generated/predictCov.h`. +The standard continuous-to-discrete expression is + +$$ +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. + +### 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. + For a moving target, target jerk is modelled as a white-noise driver, so target acceleration evolves as a Brownian-motion random walk. +- **Random-walk bias.** The GNSS-to-vision bias is modelled as a pure random walk. + The offset between the absolute GNSS frame and the relative vision frame drifts slowly and has no deterministic high-frequency dynamics. +- **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. + +## Moving-target Mode (experimental) + +::: warning +The moving-target mode is marked experimental. +Initial flight tests have been performed (see [Moving target precision landing](#moving-target) further down), but coverage is limited compared to the static mode. +Use it only for controlled experiments. +::: + +When the firmware is built with `CONFIG_VTEST_MOVING=y`, the position filter is extended with two additional states per axis to track target dynamics: $x = [r, v^{uav}, b, a^{t}, v^{t}]^T$, where $v^{t}$ and $a^{t}$ are the target velocity and acceleration along the axis. +The discrete prediction model becomes + +$$ +\begin{aligned} +r_{k+1} &= r_k - dt\thinspace (v^{uav}_k - v^{t}_k) - \tfrac{1}{2}\thinspace dt^2\thinspace (a^{uav} - a^{t}_k) \\ +v^{uav}_{k+1} &= v^{uav}_k + dt\thinspace a^{uav} \\ +v^{t}_{k+1} &= v^{t}_k + dt\thinspace a^{t}_k \\ +a^{t}_{k+1} &= a^{t}_k \\ +b_{k+1} &= b_k +\end{aligned} +$$ + +Target jerk is modelled as continuous-time white noise with PSD [VTE_ACC_T_UNC](../advanced_config/parameter_reference.md#VTE_ACC_T_UNC); see [Process noise computation](#process-noise-computation). +The initial target-acceleration variance is set by [VTE_ACC_UNC_IN](../advanced_config/parameter_reference.md#VTE_ACC_UNC_IN). + +### Build Setup + +The moving-target firmware is selected by `CONFIG_VTEST_MOVING=y` in the [KConfig board configuration](../hardware/porting_guide_config.md). +Two prebuilt targets are available: + +- `make px4_fmu-v6c_visionTargetEstMoving`: experimental moving-target hardware build. +- `make px4_sitl_vtest-moving`: SITL experimental moving-target build. + +### 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. + +### Precision-Landing Projection + +The estimator publishes the current target pose and velocity only. +The precision-landing controller applies a lookahead using [PLD_MOVING_T_MIN](../advanced_config/parameter_reference.md#PLD_MOVING_T_MIN) and [PLD_MOVING_T_MAX](../advanced_config/parameter_reference.md#PLD_MOVING_T_MAX). +It computes an intersection time $\Delta t$ by constraining $|z_{rel}| / |v_{descent}|$ between the two parameters, then shifts the horizontal landing setpoint by $\Delta t$ along the estimated target velocity. +The goal is to command the vehicle toward where the moving target will be at touchdown, not where it was at the last measurement. + +The two bounds play different roles: + +- **[PLD_MOVING_T_MAX](../advanced_config/parameter_reference.md#PLD_MOVING_T_MAX)** caps how far ahead the setpoint can lead the target. + Without a cap, at high altitude the projected setpoint can sit so far ahead that the camera no longer sees the target (target lost on vision), or so far that the horizontal error stays larger than [PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD) forever (vehicle never enters the descent phase). +- **[PLD_MOVING_T_MIN](../advanced_config/parameter_reference.md#PLD_MOVING_T_MIN)** sets a floor on the lookahead so the vehicle is still leading the target at touchdown. + 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: + +$$ +\text{PLD\_MOVING\_T\_MAX} \lesssim \frac{\text{PLD\_HACC\_RAD}}{|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. + +For `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}|}. +$$ + +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. +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: + +- `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. + Set to `0` for purely constant motion (matches the plot below). +- `500` is the period in seconds between new random velocities. +- ``, ``, ``, `` 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. +- **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`). +- **Validate on a static pad first**: build with `CONFIG_VTEST_MOVING=y` but keep `0 0 0` for the first runs. + 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. + +### Estimator Outputs + +- Full state estimations with variance and validity flags for position and orientation filters: + - `vte_position` + - `vte_orientation` +- `vte_bias_init_status`: raw GNSS/vision bias sample, low-pass filtered bias, and the norm of the consecutive raw-bias delta while the initial bias averaging phase is running. +- `landing_target_pose`: controller-facing pose plus `rel_pos_valid`, `rel_vel_valid`, and `rel_vel_ekf2_valid` booleans. +- `vte_input`: downsampled acceleration in NED and the quaternion fed to each prediction step. + Can be used to correlate estimator behaviour with vehicle attitude changes. +- `vte_aid_*`: one topic per fused source (`vte_aid_gps_pos_target`, `vte_aid_gps_pos_mission`, `vte_aid_gps_vel_uav`, `vte_aid_gps_vel_target`, `vte_aid_fiducial_marker`, `vte_aid_ev_yaw`). + Each publishes the observation, observation variance, innovation, innovation variance, chi-squared `test_ratio`, the `fusion_status` outcome code (per-axis on the 3D variant), and OOSM diagnostics (`time_since_meas_ms`, `history_steps`, `time_last_predict`). + See [Aid-source diagnostics](#aid-source-diagnostics) for the meaning of each `fusion_status` value. + +### 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: + +| Value | Status | Meaning | Typical action | +| ----- | ----------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| 0 | `STATUS_IDLE` | No fusion attempted on this axis (e.g. measurement not provided for that axis). | None. | +| 1 | `STATUS_FUSED_CURRENT` | Measurement fused immediately against the live state. | Healthy. | +| 2 | `STATUS_FUSED_OOSM` | Measurement was delayed and fused via the OOSM history buffer; check `history_steps`, and `time_since_meas_ms`. | Healthy as long as `history_steps` stays below the buffer depth `kOosmHistorySize = 25`. | +| 3 | `STATUS_REJECT_NIS` | Innovation failed the chi-squared gate. | Check sensor variance, frame rotations, time skew. Compare with `test_ratio` and the matching `vte_input` sample. | +| 4 | `STATUS_REJECT_COV` | Innovation covariance was non-finite or non-positive. | Numerical issue: check process-noise parameters and that the state has not diverged. | +| 5 | `STATUS_REJECT_TOO_OLD` | Sample older than the OOSM buffer (`kOosmMaxTimeUs = 500 ms`) or older than the oldest stored snapshot. | Reduce sensor latency, raise the publication rate, or check transport timestamps. | +| 6 | `STATUS_REJECT_TOO_NEW` | Sample timestamped in the future relative to the latest filter prediction. | Time-sync problem: verify `mavlink_timesync` or the sensor clock. | +| 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). +- `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 + +- Vision: `fiducial_marker_pos_report` / `fiducial_marker_yaw_report` +- GNSS on the target: `target_gnss` +- Vehicle GNSS: `sensor_gps` (used to convert absolute GNSS measurements to relative vehicle-carried NED measurements) +- 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 + +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. + Large steady offsets point to calibration errors or incorrect measurement-frame-to-NED transforms. +2. **Initial bias averaging**: When GNSS is active before vision, inspect `vte_bias_init_status.raw_bias`, `vte_bias_init_status.filtered_bias`, and `vte_bias_init_status.delta_norm`. + Here `delta_norm` is the norm between consecutive raw bias samples, so it directly reflects the stability criterion used by the low-pass filter exit. + The filtered bias should settle before `vte_position.bias` is initialized. + 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 +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). + 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. + 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`. + Ensure that there is no mistake in the rotation (`fiducial_marker_pos_report.q`), covariance handling, or offsets applied in the handler. +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. +If a topic is missing, verify that the upstream sensor message is publishing and that the fusion mask bit is enabled. + +::: tip +**Task activation**: Enable the debug bit in [VTE_TASK_MASK](../advanced_config/parameter_reference.md#VTE_TASK_MASK). +When the debug bit is set the estimator always runs, making it ideal for bench testing. +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. | + +### Plot Examples + +The dashboards below provide hints on how to analyse the estimator: + +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. +3. **Filter robustness**: what happens when vision drops out, when observations are noisy, and when an outlier slips through. +4. **Precision landing on a static target**: the controller actually lands on the pad. +5. **Moving target**: precision landing on a target in motion. + +::: tip +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: + +- 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.*`) +- Green (`#1ac938`): filter state output (`vte_position.*`) +- Purple (`#bd22a0`): controller-facing pose (`landing_target_pose.*`) +- Orange (`#ec8414`): EKF reference (`vehicle_local_position.*`) +::: + +#### Nominal Behaviour + +**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. + 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. + 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. + +What this plot tells you: + +1. **Vision is the dominant source throughout the descent.** + The two observation variances never cross: vision is more precise than the mission GNSS at every altitude in this flight. + This is intentional because the GPS module on the vehicle is not RTK-grade and the reported variance reflects that. + 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. +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. + Loosen [VTE_BIAS_UNC](../advanced_config/parameter_reference.md#VTE_BIAS_UNC) so the bias has more process noise, or lower [VTE_GPS_P_NOISE](../advanced_config/parameter_reference.md#VTE_GPS_P_NOISE) so GNSS pushes the bias harder. + Do not push either knob too far: a bias that moves too freely will drift when vision is lost, see [Vision occlusion during descent](#vision-occlusion-during-descent). +4. **End-of-flight vision loss.** + 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. +- **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. +- **Third row (state activation)**: `vte_position.bias` jumps from zero to the activated bias once averaging completes. + The reset uses `r = pos_rel_gnss(t_vision) - b_filtered`, `b = b_filtered`, so after activation `vte_position.rel_pos` aligns with the vision observation while `vte_position.bias` stores the GNSS offset. + +![VTEST bias averaging](../../assets/vision_target_estimator/vtest_bias_averaging.png) + +**Innovation consistency**: Confirms that every fused sensor produces zero-mean white-noise innovations. +Generated from the same real precision-landing flight as the dashboard above, with vision and the mission landing waypoint as the absolute reference. +The dashboard intentionally pairs a healthy aid source (vision) with a less well-tuned one (mission GNSS) so the two patterns can be compared side by side. + +- **Top row (vision innovations)**: `vte_aid_fiducial_marker.innovation[0..2]` on all three NED axes. + The innovations look like white noise centred on zero, which is the healthy signature. + They are slightly larger at higher altitudes where vision is noisier. +- **Second row (vision fusion status)**: `vte_aid_fiducial_marker.fusion_status[0..2]` stays at 2 (`STATUS_FUSED_OOSM`), so every sample is fused via the OOSM history replay. + 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. + 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). + To investigate, plot `vte_aid_gps_pos_mission.time_since_meas_ms` next (the [OOSM under measurement delay](#oosm-under-measurement-delay) dashboard is the right template). + +![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. + +- **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. +- **Second row (innovation, rad)**: `vte_aid_ev_yaw.innovation` should resemble white noise centred on zero. +- **Third row (innovation, deg)**: same signal converted to degrees, which is the unit most users intuitively reason about when setting [VTE_EVA_NOISE](../advanced_config/parameter_reference.md#VTE_EVA_NOISE). +- **Bottom row (test ratio)**: `vte_aid_ev_yaw.test_ratio` should stay below [VTE_YAW_NIS_THRE](../advanced_config/parameter_reference.md#VTE_YAW_NIS_THRE). + +If the yaw state follows the observation noise, the solution is the same as for position: raise the observation floor or stiffen the prediction. +See [When the state follows per-sample jitter](#when-the-state-follows-per-sample-jitter). + +![VTEST orientation](../../assets/vision_target_estimator/vtest_yaw.png) + +#### Out-of-Sequence Measurements + + + +**OOSM under measurement delay**: Shows that delayed measurements are still consumed correctly thanks to the OOSM history replay. +The plot was generated by delaying each simulated measurement by a uniform random value in [0, 500] ms before reaching the autopilot. + +- **Top two rows (measurement latency)**: `vte_aid_fiducial_marker.time_since_meas_ms` and `vte_position.history_steps`. + With a 0-500 ms delay we observe `time_since_meas_ms` ranging up to ~450 ms and `history_steps` proportional to it (`history_steps ≈ time_since_meas_ms / 20`, capped at the 25-sample buffer). +- **Third row (raw vs processed observation)**: `vte_position.rel_pos` overlaid with `vte_aid_fiducial_marker.observation`. + The processed observation lags the live state by roughly the measurement delay. + The OOSM allows fusing old data without forcing the live state to wait for it. +- **Fourth row (innovation)**: `vte_aid_fiducial_marker.innovation[0]` stays close to zero. + The innovation is computed against the predicted state at `t_meas`, not against the current live state, so the latency cancels out. + +A concrete sample from this run: at $t = 68.712$ s (vertical red line) the live state is `vte_position.rel_pos[0] = 0.026 m` and the measurement that just arrived is `vte_aid_fiducial_marker.observation[0] = 0.041 m`, with `time_since_meas_ms = 368 ms` and `history_steps = 21`. +Looking 368 ms back into the history at $t = 68.344$ s (blue vertical line), `vte_position.rel_pos[0] = 0.034 m`. +The OOSM innovation is computed against that historic prediction, giving $0.041 - 0.034 = 0.007$ m, which matches `vte_aid_fiducial_marker.innovation[0] = 0.007 m`. +Without OOSM the filter would compare the delayed measurement against the live state and produce $|0.026 - 0.041| = 0.015$ m instead which is roughly twice as large. +Under fast dynamics this kind of latency-induced error grows quickly and can repeatedly fail the chi-squared gate or pull the state in the wrong direction causing overshoots. + +![VTEST OOSM](../../assets/vision_target_estimator/vtest_oosm.png) + +#### Filter Robustness + + + +**Smoothing through bounded noise**: When the filter is well tuned, the state stays smooth even when individual observations are noisy. +The plot was generated by adding uniform random noise in the range $[-0.20, +0.20]$ m to both the vision (`vte_aid_fiducial_marker.observation`) and target-GNSS (`vte_aid_gps_pos_target.observation`) position observations on the x, y, z axes. +The injected noise stays within the NIS gate, so every sample is fused. + +- **Top row (x axis)**: `vte_aid_fiducial_marker.observation[0]` and `vte_aid_gps_pos_target.observation[0]` are visibly noisy, but `vte_position.rel_pos[0]` follows the underlying trend smoothly. +- **Bottom row (y axis)**: same behaviour on the lateral axis. + +The smoothness is the Kalman filter doing its job: each sample only contributes a fraction of its innovation to the state, weighted by the ratio of the predicted state variance to the observation variance. +As long as the noise stays inside the NIS gate, no rejection happens and the per-sample jitter averages out across many fusions. +If the state in your own logs follows the jitter instead of the trend, see [When the state follows per-sample jitter](#when-the-state-follows-per-sample-jitter) for the tuning recipe. + +![VTEST noisy measurements](../../assets/vision_target_estimator/vtest_noisy_measurements.png) + +**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. + +- **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. +- **Third row (x test ratio)**: `vte_aid_fiducial_marker.test_ratio[1]` spikes and breaches [VTE_POS_NIS_THRE](../advanced_config/parameter_reference.md#VTE_POS_NIS_THRE) for the biased measurements. +- **Bottom row (y, z fusion status)**: `vte_aid_fiducial_marker.fusion_status` stays at 1: `STATUS_FUSED_CURRENT` or 2: `STATUS_FUSED_OOSM` in the y and z direction. + +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. + 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). + +![VTEST measurement not fused](../../assets/vision_target_estimator/vtest_meas_not_fused.png) + + + +**Vision dropout behaviour**: Illustrates what happens when vision is the only relative-position source and the marker is temporarily lost, and why fusing the vehicle GNSS velocity matters in practice. + +Both plots come from the same SITL scenario with a static target: the filter is well converged on vision, vision drops out for several seconds, then comes back. +The only difference between the two runs is whether [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 1 (vehicle GNSS velocity) is enabled. + +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`. + +**Plot 1, vision only**: [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) = vision only (bit 2). + +- **Top row (relative position)**: `vte_position.rel_pos[0]` overlaid with `vte_aid_fiducial_marker.observation[0]`. + The state stays close to the last vision sample for roughly 3 seconds after the dropout (the time it takes the residual $v^{uav}$ to integrate to a visible offset), then drifts by about 60 cm over the next 7 seconds. + When vision returns, the state snaps back by ~60 cm in a single innovation, which is the accumulated drift. +- **Bottom row (UAV velocity)**: `vte_position.vel_uav[0]`, `vehicle_local_position.vx`, and `sensor_gps.vel_n_m_s`. + The three traces agree while vision is fused. + As soon as vision drops, the filter estimate diverges by about 0.1 m/s from the EKF2 and GNSS references. + That ~0.1 m/s gap over 7 seconds is the position drift observed in the top row. + +![VTEST dropout, vision only](../../assets/vision_target_estimator/vtest_dropout_vision_only.png) + +**Plot 2, vision and vehicle GNSS velocity**: Same scenario, with [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) bit 1 enabled. +Vehicle GNSS velocity is now fused as $z = v^{uav}$, which gives the velocity state a direct observation independent of vision. + +- **Top row (relative position)**: `vte_position.rel_pos[0]` properly follows the expected trend through the dropout. + The correction on vision recovery is small (in this run, from 0.26 m to 0.24 m, i.e. 2 cm), which is within the vision noise level rather than a real drift. +- **Bottom row (UAV velocity)**: `vte_position.vel_uav[0]` now tracks `vehicle_local_position.vx` and `sensor_gps.vel_n_m_s` for the full dropout, because GNSS velocity continues to constrain the state when no vision sample is available. + +![VTEST dropout, vision and GNSS velocity](../../assets/vision_target_estimator/vtest_dropout_vision_and_gnss_vel.png) + +What to take away from this comparison: + +1. With vision alone, the vehicle velocity state is only weakly observable, so the filter cannot estimate cleanly through gaps in vision. + Any additional source that touches the velocity state directly substantially extends how long the filter remains accurate without a vision sample. +2. The size of the relative-position jump on vision recovery is a useful diagnostic on its own: a large jump means the velocity state had drifted during the gap, not that the recovered vision sample is wrong. + + + +**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. + +The vertical blue line marks the moment vision is stopped, and the vertical red line marks touchdown. + +- **Top row (relative position and bias-compensated GNSS)**: `vte_aid_fiducial_marker.observation[0]`, `vte_aid_gps_pos_mission.observation[0]`, `vte_position.rel_pos[0]`, and the custom trace `gps_pos_mission_bias_compensated = vte_aid_gps_pos_mission.observation[0] - vte_position.bias[0]`. +- **Middle row (bias estimates)**: `vte_position.bias[0]` and `vte_position.bias[1]`. + The bias converges in roughly 6 seconds as the drone descends and vision becomes more precise. + Between the blue and red lines (8 seconds without vision), the deltas are about $-0.023$ m on x and $-0.008$ m on y, so the bias stays effectively stable. + 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$. + 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. +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. + +What to watch in your own logs: + +- The bias must already be settled before vision drops out. + 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. + +![VTEST occlusion with GNSS mission](../../assets/vision_target_estimator/vtest_dropout_vision_and_gps_pos_mission.png) + +#### Precision Landing on a Static Target + +**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. +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. +If the controller struggles to follow even when the target signal is clean, review the [multicopter position tuning guide](../config_mc/pid_tuning_guide_multicopter.md). + +- **Top row (north alignment)**: `landing_target_pose.x_abs` against `vehicle_local_position.x`. + The curves should overlay once precision landing is triggered. +- **Second row (east alignment)**: `landing_target_pose.y_abs` against `vehicle_local_position.y`, same as north. +- **Third row (yaw alignment)**: `vte_orientation.yaw` should remain steady while `trajectory_setpoint.yaw` tracks it when [PLD_YAW_EN](../advanced_config/parameter_reference.md#PLD_YAW_EN) is enabled. +- **Bottom row (descent context)**: `vehicle_local_position.dist_bottom` shows when the final approach begins and how high above the pad the precision-landing alignment converged. + A higher convergence altitude is better. + +![VTEST precision landing](../../assets/vision_target_estimator/vtest_precland.png) + +#### Moving Target + +**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`. + +- **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. + As altitude drops, the lookahead converges toward [PLD_MOVING_T_MIN](../advanced_config/parameter_reference.md#PLD_MOVING_T_MIN), the gap between setpoint and target closes, and the vehicle lands on the moving target rather than where it was at the start of the approach. +- **Second row (vision innovations)**: `vte_aid_fiducial_marker.innovation[0..2]` on all three NED axes. + They look like white noise centred on zero, which means the filter dynamics match the marker observations even as the target moves. +- **Third row (moving-target states)**: `vte_position.vel_target` and `vte_position.acc_target`. + These states only exist in the moving-target build and can be compared to the expected target velocity and acceleration. +- **Bottom row (descent context)**: `vehicle_local_position.dist_bottom` shows the distance to the ground and indicates the phase of the landing. + +What to take away: + +- **Add more sensors when you can.** + With vision only, the mission must end up somewhere the target is visible because the filter has no other observation of the target position. + 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. +- **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 + +- 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)). +- 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 + +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. + +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. + 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. +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. + `targetRelativeCallback()` packs the marker into a `TARGET_RELATIVE` mavlink message, and `TargetGpsCallback()` packs the GPS sample into `TARGET_ABSOLUTE`. +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 + +To integrate a new sensor: + +1. **Define a uORB message** that carries the measurement in either the vehicle body frame or NED, complete with variance estimates and timestamps. +2. **Extend the fusion mask**: add a bit to `SensorFusionMaskU` (`src/modules/vision_target_estimator/common.h`) and update the parameter definition for [VTE_AID_MASK](../advanced_config/parameter_reference.md#VTE_AID_MASK) (see also [sensor fusion selection](../advanced_features/vision_target_estimator.md#sensor-fusion-selection)) in `vision_target_estimator_params.yaml`. +3. **Augment observation enums**: append the new entry to the relevant `ObsType` enum (`VTEPosition.h` or `VTEOrientation.h`), update `ObsValidMaskU`, and update helper functions such as `hasNewNonGpsPositionSensorData()` and `selectInitialPosition()` if the measurement can provide a relative position. +4. **Subscribe and validate**: add a `uORB::Subscription` to the filter, check for finite values, and reject samples that are too old `isMeasUpdated` or timestamped in the future before marking the observation valid. +5. **Implement the handler** in `processObservations()`. + Convert the measurement into NED coordinates, populate `TargetObs::meas_xyz`, `meas_unc_xyz`, and the observation Jacobian (`meas_h_xyz` or `meas_h_theta`), and set the fusion-mask flag only after the data passes validation. +6. **Provide tunable noise**: declare a parameter (e.g. `VTE__NOISE`) and clamp it with `kMinObservationNoise` so the estimator never believes a measurement is perfect. +7. **Log the innovations**: add a publication member and ORB topic (see `vte_aid_fiducial_marker` for reference) so that logs include the innovation, variance, and `fusion_status` outcome for the new sensor. + Use the `FusionResult` returned by the filter to populate `fusion_status` so successes and rejections share the same status enum as the existing sources. +8. **Exercise SITL**: update the Gazebo (or other) simulation so that replay tests produce the new measurement. + This keeps CI coverage intact and provides a reference data set for tuning. +9. **Document the workflow**: update this deep dive and any setup how-tos so users know how to enable the new bit, calibrate the sensor, and interpret its logs. + +::: warning +**Timeout policy**: Every measurement must be time-aligned and checked so that stale data never reaches the update step. +Reject samples older than [VTE_M_REC_TOUT](../advanced_config/parameter_reference.md#VTE_M_REC_TOUT) (`isMeasRecent(hrt_abstime ts)`) and check `time_since_meas_ms` (and `fusion_status` for `STATUS_REJECT_TOO_OLD` / `STATUS_REJECT_TOO_NEW`) on the new `vte_aid_*` topic to confirm the sensor fits inside the estimator deadlines. +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. + +Use this checklist: + +1. **Reserve a task-mask bit**: add the bit in `task_bits` (`tasks/VteTask.h`). + Those constants are the code-level source of truth for `VTE_TASK_MASK`. + Then update `vision_target_estimator_params.yaml` and the `VTE_TASK_MASK` + documentation so users can enable the new task. +2. **Create a task class**: add a new file under `src/modules/vision_target_estimator/tasks/` and derive it from `VteTask`. + Put all task-specific subscriptions and status flags in that class. +3. **Implement the interface deliberately**: `maskBit()` and `name()` identify the task, `pollStatus()` refreshes external state, `isReady()` exposes level-triggered readiness, and `isComplete()` reports self-termination. + Use `onActivate()` for one-shot state resets on task entry, and `onPosEstStart()` only when the position filter needs task-specific seeding such as a cached mission waypoint. +4. **Keep side effects out of readiness checks**: `pollStatus()` and `isReady()` are called every scheduler cycle while the task bit is enabled. + They should be cheap. + Transition-only work belongs in `onActivate()`. +5. **Register the task by priority**: add the task instance to `VisionTargetEst` and place it in `_task_registry` in descending priority order. + If multiple bits are enabled at the same time, the first ready task wins. +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 + +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`. + +**Source files (Python):** + +- `src/modules/vision_target_estimator/Position/vtest_derivation/derivation.py` for the position filter. +- `src/modules/vision_target_estimator/Orientation/vtest_derivation/derivation.py` for the yaw filter. + +**Generated outputs (C++ headers) used at runtime:** + +| Filter | Generated headers | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Position | `state.h`, `predictState.h`, `predictCov.h`, `computeInnovCov.h`, `getTransitionMatrix.h`, `applyCorrection.h` | +| Orientation | `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:** + +- 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. +- Setting `-DVTEST_SYMFORCE_GEN=ON` manually regenerates both filters at configure time. + +The generated files are included from the build directory and must never be edited by hand. +To change the model, edit `derivation.py` and regenerate. + +#### Regenerating the symbolic model + +1. Configure CMake with `-DVTEST_SYMFORCE_GEN=ON` (automatic when `CONFIG_VTEST_MOVING=y`) and ensure SymForce is available in the Python environment. +2. Reconfigure with `cmake --fresh ...` so the custom command in `src/modules/vision_target_estimator/CMakeLists.txt` runs. + The outputs land in `build//src/modules/vision_target_estimator/vtest_derivation/generated/` (position) and `.../vte_orientation_derivation/generated/` (orientation). +3. To refresh the committed reference files, add `-DVTEST_UPDATE_COMMITTED_DERIVATION=ON` and commit the regenerated files in `Position/vtest_derivation/generated*/` once vetted. + +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 + +The estimator publishes per-section perf counters that can be read at any time on the shell: + +```sh +perf | grep "vision_target_estimator" +``` + +Each line reports event count, total elapsed time, average, min, max, and standard deviation in microseconds. +Six counters cover the vision target estimator: + +| Counter | What it covers | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `VTE cycle ` | One full work-queue of `VisionTargetEst::Run()`. Includes input subscription polls, task scheduling, and the dispatch into the position/orientation update steps. | +| `VTE cycle pos` | The position-filter part of the cycle (every prediction or measurement update for `VTEPosition`). | +| `VTE cycle yaw` | The orientation-filter part (same scope, for `VTEOrientation`). | +| `VTE prediction` | Just the Kalman prediction inside the position filter: `Predictstate` + `Predictcov` plus OOSM history. | +| `VTE update` | The full update step in the position filter, including measurement validation, frame transforms, fusion calls for every active aid source, and OOSM history maintenance. | +| `VTE fusion` | Just the per-axis fusion inside an update: innovation, gating, gain projection, and history correction. This is where OOSM scales with `history_steps`. | + +The numbers below come from a Pixhawk 6c running the static-target filter (`vte_aid_fiducial_marker` + `vte_aid_gps_pos_target` + `vte_aid_gps_vel_uav`) at the default 50 Hz cadence. + +**Baseline (no injected delay):** + +```text +VTE fusion: 20568 events, 297061us elapsed, 14.44us avg, min 1us max 88us 14.138us rms +VTE update: 6856 events, 318536us elapsed, 46.46us avg, min 3us max 163us 41.827us rms +VTE prediction: 18567 events, 105034us elapsed, 5.66us avg, min 5us max 52us 1.575us rms +VTE cycle : 92576 events, 1614647us elapsed, 17.44us avg, min 6us max 281us 27.204us rms +VTE cycle yaw: 18563 events, 125422us elapsed, 6.76us avg, min 4us max 60us 3.985us rms +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):** + +```text +VTE fusion: 31932 events, 1860362us elapsed, 58.26us avg, min 63us max 135us 23.520us rms +VTE update: 10644 events, 1894804us elapsed, 178.02us avg, min 4us max 301us 69.331us rms +VTE prediction: 29156 events, 166179us elapsed, 5.70us avg, min 5us max 52us 1.614us rms +VTE cycle : 163952 events, 4215369us elapsed, 25.71us avg, min 6us max 511us 57.621us rms +VTE cycle yaw: 32850 events, 274433us elapsed, 8.35us avg, min 1us max 86us 7.852us rms +VTE cycle pos: 32861 events, 2703185us elapsed, 82.26us avg, min 10us max 479us 96.704us rms +``` + +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 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. +- **`VTE update` follows the same trend** (~46 us → ~178 us) since it wraps multiple fusion calls. + The worst-case (~300 us) corresponds to a cycle where every aid source hits the OOSM path. +- **`VTE cycle pos` (~43 us → ~82 us)** confirms the same behaviour at the cycle level. + A full position cycle still completes in well under 0.5 ms even in the worst case, which is small relative to the 20 ms (50 Hz) loop budget. +- **`VTE cycle ` and `VTE cycle yaw` see only minor changes**: these counters are dominated by lightweight scheduling and yaw-only fusion that does not involve OOSM history projection. + +A few things to keep in mind when interpreting your own numbers: + +- The total `VTE cycle ` event count is roughly five times the `VTE cycle pos` count because `Run()` is woken on every input topic update, but the position estimator only ticks at 50 Hz. +- `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 + +- `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. + +Run locally: + +```sh +make tests TESTFILTER=TEST_VTE* +``` diff --git a/msg/CMakeLists.txt b/msg/CMakeLists.txt index 1d7dae1bd75..af55a8474fe 100644 --- a/msg/CMakeLists.txt +++ b/msg/CMakeLists.txt @@ -286,6 +286,20 @@ set(msg_files ) list(SORT msg_files) +if(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) + list(APPEND msg_files + TargetGnss.msg + VteInput.msg + VtePosition.msg + VteOrientation.msg + VteAidSource1d.msg + VteAidSource3d.msg + VteBiasInitStatus.msg + FiducialMarkerPosReport.msg + FiducialMarkerYawReport.msg + PrecLandStatus.msg) +endif() + px4_list_make_absolute(msg_files ${CMAKE_CURRENT_SOURCE_DIR} ${msg_files}) if(NOT EXTERNAL_MODULES_LOCATION STREQUAL "") diff --git a/msg/FiducialMarkerPosReport.msg b/msg/FiducialMarkerPosReport.msg new file mode 100644 index 00000000000..63c6faebc1f --- /dev/null +++ b/msg/FiducialMarkerPosReport.msg @@ -0,0 +1,14 @@ +# Relative position of a precision-landing target detected by a vision pipeline (e.g. an ArUco marker). +# +# Published by: vision pipelines (on-board or off-board over MAVLink TARGET_RELATIVE), decoded in mavlink_receiver. +# Subscribed by: vision_target_estimator (VTEPosition). +# +# The measurement is expressed in an arbitrary sensor frame; the quaternion q rotates it into the NED earth frame. + +uint64 timestamp # [us] Time since system start +uint64 timestamp_sample # [us] Timestamp of the raw observation + +float32[3] rel_pos # [m] Target position relative to vehicle, expressed in the frame defined by q +float32[3] cov_rel_pos # [m^2] Target position variance, expressed in the frame defined by q + +float32[4] q # [-] Quaternion rotation from the rel_pos frame to the NED earth frame diff --git a/msg/FiducialMarkerYawReport.msg b/msg/FiducialMarkerYawReport.msg new file mode 100644 index 00000000000..86213faf6b2 --- /dev/null +++ b/msg/FiducialMarkerYawReport.msg @@ -0,0 +1,10 @@ +# Yaw of a precision-landing target relative to the NED (North, East, Down) frame, reported by a vision pipeline. +# +# Published by: vision pipelines (on-board or off-board over MAVLink TARGET_RELATIVE), decoded in mavlink_receiver. +# Subscribed by: vision_target_estimator (VTEOrientation). + +uint64 timestamp # [us] Time since system start +uint64 timestamp_sample # [us] Timestamp of the raw observation + +float32 yaw_ned # [rad] [@frame NED] Orientation of the target relative to the NED frame [-Pi ; Pi] +float32 yaw_var_ned # [rad^2] Orientation uncertainty diff --git a/msg/LandingTargetPose.msg b/msg/LandingTargetPose.msg index 875920f183b..0fc86b92937 100644 --- a/msg/LandingTargetPose.msg +++ b/msg/LandingTargetPose.msg @@ -1,26 +1,31 @@ # Relative position of precision land target in navigation (body fixed, north aligned, NED) and inertial (world fixed, north aligned, NED) frames -uint64 timestamp # time since system start (microseconds) +uint64 timestamp # [us] Time since system start -bool is_static # Flag indicating whether the landing target is static or moving with respect to the ground +bool is_static # [-] Flag indicating whether the landing target is static or moving with respect to the ground -bool rel_pos_valid # Flag showing whether relative position is valid -bool rel_vel_valid # Flag showing whether relative velocity is valid +bool rel_pos_valid # [-] Flag showing whether relative position is valid +bool rel_vel_valid # [-] Flag showing whether relative velocity is valid +bool rel_vel_ekf2_valid # [-] Flag showing whether relative velocity is valid for EKF2 auxiliary velocity aiding -float32 x_rel # X/north position of target, relative to vehicle (navigation frame) [meters] -float32 y_rel # Y/east position of target, relative to vehicle (navigation frame) [meters] -float32 z_rel # Z/down position of target, relative to vehicle (navigation frame) [meters] +float32 x_rel # [m] X/north position of target, relative to vehicle (navigation frame) +float32 y_rel # [m] Y/east position of target, relative to vehicle (navigation frame) +float32 z_rel # [m] Z/down position of target, relative to vehicle (navigation frame) -float32 vx_rel # X/north velocity of target, relative to vehicle (navigation frame) [meters/second] -float32 vy_rel # Y/east velocity of target, relative to vehicle (navigation frame) [meters/second] +float32 vx_rel # [m/s] X/north velocity of target, relative to vehicle (navigation frame) +float32 vy_rel # [m/s] Y/east velocity of target, relative to vehicle (navigation frame) +float32 vz_rel # [m/s] Z/down velocity of target, relative to vehicle (navigation frame) -float32 cov_x_rel # X/north position variance [meters^2] -float32 cov_y_rel # Y/east position variance [meters^2] +float32 cov_x_rel # [m^2] X/north position variance +float32 cov_y_rel # [m^2] Y/east position variance +float32 cov_z_rel # [m^2] Z/down position variance -float32 cov_vx_rel # X/north velocity variance [(meters/second)^2] -float32 cov_vy_rel # Y/east velocity variance [(meters/second)^2] +float32 cov_vx_rel # [(m/s)^2] X/north velocity variance +float32 cov_vy_rel # [(m/s)^2] Y/east velocity variance +float32 cov_vz_rel # [(m/s)^2] Z/down velocity variance -bool abs_pos_valid # Flag showing whether absolute position is valid -float32 x_abs # X/north position of target, relative to origin (navigation frame) [meters] -float32 y_abs # Y/east position of target, relative to origin (navigation frame) [meters] -float32 z_abs # Z/down position of target, relative to origin (navigation frame) [meters] +bool abs_pos_valid # [-] Flag showing whether absolute position is valid + +float32 x_abs # [m] X/north position of target, relative to origin (navigation frame) +float32 y_abs # [m] Y/east position of target, relative to origin (navigation frame) +float32 z_abs # [m] Z/down position of target, relative to origin (navigation frame) diff --git a/msg/PrecLandStatus.msg b/msg/PrecLandStatus.msg new file mode 100644 index 00000000000..55fdc5d1d15 --- /dev/null +++ b/msg/PrecLandStatus.msg @@ -0,0 +1,20 @@ +# Precision-landing runtime status: a single state captures both whether precision landing is active and which phase it is in. +# +# Published by: navigator (precland.cpp). +# Subscribed by: vision_target_estimator, flight_mode_manager (FlightTaskAuto). +# +# STOPPED is published when the precision-landing task is not active (just inactivated, or never started). +# The phase values (START..FALLBACK) are only published while the task is running and not yet finished. +# DONE is published once on successful completion, then STOPPED on the subsequent inactivation. + +uint64 timestamp # [us] Time since system start + +uint8 state # [@enum PREC_LAND_STATE] Current precision-landing state +uint8 PREC_LAND_STATE_STOPPED = 0 # Task not active (inactivated or never started) +uint8 PREC_LAND_STATE_START = 1 # Task just activated, initial setup +uint8 PREC_LAND_STATE_HORIZONTAL = 2 # Positioning over landing target while maintaining altitude +uint8 PREC_LAND_STATE_DESCEND = 3 # Descending while staying over the target +uint8 PREC_LAND_STATE_FINAL = 4 # Final landing approach (continues even without target in sight) +uint8 PREC_LAND_STATE_SEARCH = 5 # Searching for the landing target +uint8 PREC_LAND_STATE_FALLBACK = 6 # Fallback landing method (no precision) +uint8 PREC_LAND_STATE_DONE = 7 # Precision landing finished diff --git a/msg/TargetGnss.msg b/msg/TargetGnss.msg new file mode 100644 index 00000000000..faf0d620485 --- /dev/null +++ b/msg/TargetGnss.msg @@ -0,0 +1,26 @@ +# Landing target GNSS position in WGS84 coordinates, and optional NED velocity, from a target-mounted receiver. +# +# Published by: mavlink_receiver (when decoding TARGET_ABSOLUTE with position/velocity capability bits set). +# Subscribed by: vision_target_estimator (VTEPosition). +# +# abs_pos_updated / vel_ned_updated tell the estimator which fields in this sample are fresh. + +uint64 timestamp # [us] Time since system start +uint64 timestamp_sample # [us] Timestamp of the raw observation + +float64 latitude_deg # [deg] Latitude, allows centimeter level RTK precision +float64 longitude_deg # [deg] Longitude, allows centimeter level RTK precision +float32 altitude_msl_m # [m] Altitude above MSL + +float32 eph # [m] GNSS horizontal position accuracy +float32 epv # [m] GNSS vertical position accuracy + +bool abs_pos_updated # True if WGS84 position is updated + +float32 vel_n_m_s # [m/s] GNSS North velocity +float32 vel_e_m_s # [m/s] GNSS East velocity +float32 vel_d_m_s # [m/s] GNSS Down velocity + +float32 s_acc_m_s # [m/s] GNSS speed accuracy estimate + +bool vel_ned_updated # True if NED velocity is updated diff --git a/msg/VteAidSource1d.msg b/msg/VteAidSource1d.msg new file mode 100644 index 00000000000..dd5880ef9d1 --- /dev/null +++ b/msg/VteAidSource1d.msg @@ -0,0 +1,34 @@ +# Vision Target Estimator 1D fusion aid-source diagnostics (e.g. yaw). +# +# Published by: vision_target_estimator (VTEOrientation) on every fusion attempt, including rejected ones. +# Subscribed by: logger only. Inspect observation, innovation, test_ratio, and fusion_status to debug why a measurement was or was not fused. + +uint64 timestamp # [us] Time since system start +uint64 timestamp_sample # [us] Timestamp of the raw observation +uint64 time_last_predict # [us] Timestamp of last filter prediction + +# Observation & Innovation +float32 observation # [-] Observation attempted to be fused +float32 observation_variance # [-] Variance of observation attempted to be fused + +float32 innovation # [-] Kalman Filter innovation (y = z - Hx) +float32 innovation_variance # [-] Kalman Filter variance of the innovation + +float32 test_ratio # [-] Normalized innovation squared (NIS) + +uint8 fusion_status # [@enum VTE_FUSION_STATUS] Fusion status code +uint8 STATUS_IDLE = 0 # No fusion attempted yet +uint8 STATUS_FUSED_CURRENT = 1 # Fused immediately (low latency) +uint8 STATUS_FUSED_OOSM = 2 # Fused via history buffer +uint8 STATUS_REJECT_NIS = 3 # Rejected by Normalized Innovation Squared check +uint8 STATUS_REJECT_COV = 4 # Rejected due to invalid/infinite covariance or numerical error +uint8 STATUS_REJECT_TOO_OLD = 5 # Rejected: older than buffer limit (kOosmMaxTimeUs) or oldest sample +uint8 STATUS_REJECT_TOO_NEW = 6 # Rejected: timestamp in the future (beyond tolerance) +uint8 STATUS_REJECT_STALE = 7 # Rejected: history was reset due to staleness/discontinuity +uint8 STATUS_REJECT_EMPTY = 8 # Rejected: history buffer not yet populated + +# OOSM Diagnostics +float32 time_since_meas_ms # [ms] (now - timestamp_sample) +uint8 history_steps # [-] Number of steps replayed in OOSM (0 if current or failed) + +# TOPICS vte_aid_ev_yaw diff --git a/msg/VteAidSource3d.msg b/msg/VteAidSource3d.msg new file mode 100644 index 00000000000..e5de854e375 --- /dev/null +++ b/msg/VteAidSource3d.msg @@ -0,0 +1,35 @@ +# Vision Target Estimator 3D fusion aid-source diagnostics, one fusion_status per NED axis. +# +# Published by: vision_target_estimator (VTEPosition) on every fusion attempt, including rejected ones. +# Subscribed by: logger only. Inspect observation, innovation, test_ratio, and per-axis fusion_status to debug why a measurement was or was not fused. + +uint64 timestamp # [us] Time since system start +uint64 timestamp_sample # [us] Timestamp of the raw observation +uint64 time_last_predict # [us] Timestamp of last filter prediction + +# Observation & Innovation +float32[3] observation # [-] [@frame NED] Sensor observation attempted to be fused +float32[3] observation_variance # [-] [@frame NED] Variance of the observation attempted to be fused + +float32[3] innovation # [-] [@frame NED] Kalman Filter innovation (y = z - Hx) +float32[3] innovation_variance # [-] [@frame NED] Kalman Filter variance of the innovation + +float32[3] test_ratio # [-] Normalized innovation squared (NIS) + +uint8[3] fusion_status # [@enum VTE_FUSION_STATUS] Fusion status code per axis +uint8 STATUS_IDLE = 0 # No fusion attempted yet +uint8 STATUS_FUSED_CURRENT = 1 # Fused immediately (low latency) +uint8 STATUS_FUSED_OOSM = 2 # Fused via history buffer +uint8 STATUS_REJECT_NIS = 3 # Rejected by Normalized Innovation Squared check +uint8 STATUS_REJECT_COV = 4 # Rejected due to invalid/infinite covariance or numerical error +uint8 STATUS_REJECT_TOO_OLD = 5 # Rejected: older than buffer limit (kOosmMaxTimeUs) or oldest sample +uint8 STATUS_REJECT_TOO_NEW = 6 # Rejected: timestamp in the future (beyond tolerance) +uint8 STATUS_REJECT_STALE = 7 # Rejected: history was reset due to staleness/discontinuity +uint8 STATUS_REJECT_EMPTY = 8 # Rejected: history buffer not yet populated + +# OOSM Diagnostics (Shared across axes) +float32 time_since_meas_ms # [ms] (now - timestamp_sample) +uint8 history_steps # [-] Number of steps replayed in OOSM (0 if current or failed) + +# TOPICS vte_aid_gps_pos_target vte_aid_gps_pos_mission vte_aid_gps_vel_target vte_aid_gps_vel_uav +# TOPICS vte_aid_fiducial_marker diff --git a/msg/VteBiasInitStatus.msg b/msg/VteBiasInitStatus.msg new file mode 100644 index 00000000000..edc4467fe83 --- /dev/null +++ b/msg/VteBiasInitStatus.msg @@ -0,0 +1,10 @@ +# Diagnostics for the initial GNSS/vision bias averaging phase in the Vision Target Estimator. +# +# Published by: vision_target_estimator (VTEPosition) while the bias low-pass filter is running. +# Subscribed by: logger only, to verify that the bias settles before the estimator starts fusing vision. + +uint64 timestamp # [us] Time since system start + +float32[3] raw_bias # [m] [@frame NED] Current GNSS-vision bias sample +float32[3] filtered_bias # [m] [@frame NED] Low-pass filtered bias sample +float32 delta_norm # [m] norm(raw_bias_k - raw_bias_k-1) diff --git a/msg/VteInput.msg b/msg/VteInput.msg new file mode 100644 index 00000000000..5a887703ae9 --- /dev/null +++ b/msg/VteInput.msg @@ -0,0 +1,11 @@ +# Vehicle inputs fed into the Vision Target Estimator position prediction step, logged for tuning. +# +# Published by: vision_target_estimator (VisionTargetEst work item). +# Subscribed by: logger only. + +uint64 timestamp # [us] Time since system start +uint64 timestamp_sample # [us] Timestamp of the raw input data + +float32[3] acc_xyz # [m/s^2] [@frame NED] Downsampled UAV bias-corrected acceleration (including gravity) +float32[4] q_att # [-] Downsampled UAV attitude quaternion (FRD body -> NED earth) +uint32 acc_sample_count # [-] Number of raw samples averaged into acc_xyz this cycle diff --git a/msg/VteOrientation.msg b/msg/VteOrientation.msg new file mode 100644 index 00000000000..54e6a5848b9 --- /dev/null +++ b/msg/VteOrientation.msg @@ -0,0 +1,14 @@ +# Vision Target Estimator orientation state, exposing the full yaw filter output with covariances for logging and tuning. +# +# Published by: vision_target_estimator (VTEOrientation). +# Subscribed by: logger only. The orientation-related fields consumed elsewhere (precision landing) are exposed on landing_target_pose. + +uint64 timestamp # [us] Time since system start + +bool orientation_valid # [-] Relative orientation estimate valid + +float32 yaw # [rad] [@frame NED] Target yaw angle +float32 cov_yaw # [rad^2] Variance of yaw + +float32 yaw_rate # [rad/s] [@frame NED] Target yaw rate +float32 cov_yaw_rate # [(rad/s)^2] Variance of yaw_rate diff --git a/msg/VtePosition.msg b/msg/VtePosition.msg new file mode 100644 index 00000000000..5eb87bc6d3d --- /dev/null +++ b/msg/VtePosition.msg @@ -0,0 +1,23 @@ +# Vision Target Estimator position state, exposing the full per-axis Kalman filter state with covariances for logging and tuning. +# +# Published by: vision_target_estimator (VTEPosition). +# Subscribed by: logger only. The position-related fields consumed elsewhere (precision landing, EKF2 aiding) are exposed on landing_target_pose. +# +# vel_target and acc_target are only populated when the firmware is built with CONFIG_VTEST_MOVING=y; otherwise they stay at zero. + +uint64 timestamp # [us] Time since system start + +bool rel_pos_valid # [-] Relative position estimate valid +bool rel_vel_valid # [-] Relative velocity estimate valid + +float32[3] rel_pos # [m] [@frame NED] Target position relative to vehicle +float32[3] vel_uav # [m/s] [@frame NED] Vehicle velocity +float32[3] vel_target # [m/s] [@frame NED] Target velocity +float32[3] bias # [m] [@frame NED] GNSS bias between vehicle and target receivers +float32[3] acc_target # [m/s^2] [@frame NED] Target acceleration + +float32[3] cov_rel_pos # [m^2] [@frame NED] Variance of rel_pos +float32[3] cov_vel_uav # [(m/s)^2] [@frame NED] Variance of vel_uav +float32[3] cov_bias # [m^2] [@frame NED] Variance of bias +float32[3] cov_vel_target # [(m/s)^2] [@frame NED] Variance of vel_target +float32[3] cov_acc_target # [(m/s^2)^2] [@frame NED] Variance of acc_target diff --git a/platforms/common/include/px4_platform_common/px4_work_queue/WorkQueueManager.hpp b/platforms/common/include/px4_platform_common/px4_work_queue/WorkQueueManager.hpp index 4ce4db1e743..dbee70a8ed9 100644 --- a/platforms/common/include/px4_platform_common/px4_work_queue/WorkQueueManager.hpp +++ b/platforms/common/include/px4_platform_common/px4_work_queue/WorkQueueManager.hpp @@ -70,6 +70,8 @@ static constexpr wq_config_t I2C4{"wq:I2C4", CONFIG_WQ_I2C_STACKSIZE, (int8_t)CO // PX4 att/pos controllers, highest priority after sensors. static constexpr wq_config_t nav_and_controllers{"wq:nav_and_controllers", CONFIG_WQ_NAV_AND_CONTROLLERS_STACKSIZE, (int8_t)CONFIG_WQ_NAV_AND_CONTROLLERS_PRIORITY}; +static constexpr wq_config_t vte{"wq:vte", CONFIG_WQ_VTE_STACKSIZE, (int8_t)CONFIG_WQ_VTE_PRIORITY}; + static constexpr wq_config_t INS0{"wq:INS0", CONFIG_WQ_INS_STACKSIZE, (int8_t)CONFIG_WQ_INS0_PRIORITY}; static constexpr wq_config_t INS1{"wq:INS1", CONFIG_WQ_INS_STACKSIZE, (int8_t)CONFIG_WQ_INS1_PRIORITY}; static constexpr wq_config_t INS2{"wq:INS2", CONFIG_WQ_INS_STACKSIZE, (int8_t)CONFIG_WQ_INS2_PRIORITY}; diff --git a/platforms/common/px4_work_queue/Kconfig b/platforms/common/px4_work_queue/Kconfig index bb320e9519c..0f2a2ac004c 100644 --- a/platforms/common/px4_work_queue/Kconfig +++ b/platforms/common/px4_work_queue/Kconfig @@ -138,6 +138,20 @@ config WQ_NAV_AND_CONTROLLERS_PRIORITY help Sets the relative priority for the nav_and_controllers work queue. +config WQ_VTE_STACKSIZE + int "Stack size for vte" + default 6000 + range 1000 10000 + help + Sets the stack size for the vte work queue. + +config WQ_VTE_PRIORITY + int "Relative priority for vte" + default -14 + range -255 0 + help + Sets the relative priority for the vte work queue. + menu "INS Work Queues" config WQ_INS_STACKSIZE diff --git a/src/lib/ringbuffer/CMakeLists.txt b/src/lib/ringbuffer/CMakeLists.txt index 538c1ae9071..af30832d62c 100644 --- a/src/lib/ringbuffer/CMakeLists.txt +++ b/src/lib/ringbuffer/CMakeLists.txt @@ -38,4 +38,5 @@ px4_add_library(ringbuffer target_include_directories(ringbuffer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) px4_add_unit_gtest(SRC RingbufferTest.cpp LINKLIBS ringbuffer) -px4_add_unit_gtest(SRC TimestampedRingBufferTest.cpp) +px4_add_unit_gtest(SRC TimestampedRingBufferDynamicTest.cpp) +px4_add_unit_gtest(SRC TimestampedRingBufferStaticTest.cpp) diff --git a/src/lib/ringbuffer/TimestampedRingBuffer.hpp b/src/lib/ringbuffer/TimestampedRingBuffer.hpp index a96f1c35a02..29ef526b7a2 100644 --- a/src/lib/ringbuffer/TimestampedRingBuffer.hpp +++ b/src/lib/ringbuffer/TimestampedRingBuffer.hpp @@ -32,21 +32,139 @@ ****************************************************************************/ /** - * @file TimestampedRingBuffer.h - * @author Roman Bapst - * @brief Template ring buffer for timestamped samples (requires data_type::time_us). - * Note: This is not the same as `Ringbuffer` (byte FIFO) in `src/lib/ringbuffer/Ringbuffer.hpp`. - */ +* @file TimestampedRingBuffer.hpp +* @author Roman Bapst +* @brief Template ring buffer for timestamped samples (requires data_type::time_us). +* +* Note: This is not the same as `Ringbuffer` (byte FIFO) in `src/lib/ringbuffer/Ringbuffer.hpp`. +*/ #pragma once +#include +#include #include -#include -#include -template +template +class TimestampedRingBuffer; + +/** + * Static-size ring buffer specialization (SIZE > 0). + */ +template class TimestampedRingBuffer { +public: + static_assert(SIZE > 0, "SIZE must be > 0"); + static_assert(SIZE <= UINT8_MAX, "SIZE must fit in uint8_t"); + static constexpr uint8_t kSize = static_cast(SIZE); + + TimestampedRingBuffer() = default; + ~TimestampedRingBuffer() = default; + + // no copy, assignment, move, move assignment + TimestampedRingBuffer(const TimestampedRingBuffer &) = delete; + TimestampedRingBuffer &operator=(const TimestampedRingBuffer &) = delete; + TimestampedRingBuffer(TimestampedRingBuffer &&) = delete; + TimestampedRingBuffer &operator=(TimestampedRingBuffer &&) = delete; + + bool allocate(size_t size) { return size == SIZE; } + + bool valid() const { return SIZE > 0; } + + void push(const data_type &sample) + { + _buffer[_head] = sample; + _head = next(_head); + + if (_entries < kSize) { + _entries++; + } + } + + uint8_t get_length() const { return kSize; } + + data_type &operator[](const uint8_t index) { return _buffer[index]; } + + const data_type &get_newest() const { return _buffer[get_newest_index()]; } + const data_type &get_oldest() const { return _buffer[get_oldest_index()]; } + + uint8_t get_newest_index() const { return (_entries > 0) ? prev(_head) : 0; } + uint8_t get_oldest_index() const + { + if (_entries == 0) { + return 0; + } + + const uint16_t idx = static_cast(_head) + static_cast(kSize) - static_cast(_entries); + return (idx >= kSize) ? static_cast(idx - kSize) : static_cast(idx); + } + + uint8_t next(uint8_t i) const { return (i + 1 >= kSize) ? 0 : i + 1; } + uint8_t prev(uint8_t i) const { return (i == 0) ? kSize - 1 : i - 1; } + + bool pop_first_older_than(const uint64_t ×tamp, data_type *sample) + { + // start looking from newest observation data + const uint8_t newest_idx = get_newest_index(); + const uint8_t oldest_idx = get_oldest_index(); + + for (uint8_t i = 0; i < _entries; i++) { + int index = (newest_idx - i); + index = index < 0 ? kSize + index : index; + + if (timestamp >= _buffer[index].time_us && timestamp < _buffer[index].time_us + (uint64_t)1e5) { + *sample = _buffer[index]; + + // Now we can set the tail to the item which + // comes after the one we removed since we don't + // want to have any older data in the buffer + const uint8_t index_u = static_cast(index); + const uint8_t distance = (index_u >= oldest_idx) ? (index_u - oldest_idx) : (index_u + kSize - oldest_idx); + const uint8_t discard_count = distance + 1; + _entries = (_entries > discard_count) ? (_entries - discard_count) : 0; + _buffer[index].time_us = 0; + + return true; + } + } + + return false; + } + + int get_total_size() const + { + static_assert(sizeof(TimestampedRingBuffer) <= static_cast(INT_MAX), + "static ring buffer size must fit in int"); + return static_cast(sizeof(TimestampedRingBuffer)); + } + + int entries() const { return _entries; } + bool empty() const { return _entries == 0; } + + void reset() + { + for (uint8_t i = 0; i < kSize; i++) { + _buffer[i].time_us = 0; + } + + _head = 0; + _entries = 0; + } + +private: + data_type _buffer[SIZE] {}; + + uint8_t _head{0}; + uint8_t _entries{0}; +}; + +/** + * Dynamic-size ring buffer specialization (SIZE == 0). + */ +template +class TimestampedRingBuffer +{ public: explicit TimestampedRingBuffer(size_t size) { allocate(size); } TimestampedRingBuffer() = delete; @@ -58,14 +176,14 @@ public: TimestampedRingBuffer(TimestampedRingBuffer &&) = delete; TimestampedRingBuffer &operator=(TimestampedRingBuffer &&) = delete; - bool allocate(uint8_t size) + bool allocate(size_t size) { if (valid() && (size == _size)) { // no change return true; } - if (size == 0) { + if (size == 0 || size > UINT8_MAX) { return false; } @@ -77,7 +195,7 @@ public: return false; } - _size = size; + _size = static_cast(size); reset(); @@ -91,7 +209,7 @@ public: uint8_t head_new = _head; if (!_first_write) { - head_new = (_head + 1) % _size; + head_new = next(_head); } _buffer[head_new] = sample; @@ -99,7 +217,7 @@ public: // move tail if we overwrite it if (_head == _tail && !_first_write) { - _tail = (_tail + 1) % _size; + _tail = next(_tail); } else { _first_write = false; @@ -113,8 +231,12 @@ public: const data_type &get_newest() const { return _buffer[_head]; } const data_type &get_oldest() const { return _buffer[_tail]; } + uint8_t get_newest_index() const { return _head; } uint8_t get_oldest_index() const { return _tail; } + uint8_t next(uint8_t i) const { return (_size > 0) ? ((i + 1 >= _size) ? 0 : i + 1) : 0; } + uint8_t prev(uint8_t i) const { return (_size > 0) ? ((i == 0) ? (_size - 1) : (i - 1)) : 0; } + bool pop_first_older_than(const uint64_t ×tamp, data_type *sample) { // start looking from newest observation data @@ -133,7 +255,7 @@ public: _first_write = true; } else { - _tail = (index + 1) % _size; + _tail = next(static_cast(index)); } _buffer[index].time_us = 0; @@ -167,11 +289,13 @@ public: return count; } + bool empty() const { return entries() == 0; } + void reset() { if (_buffer) { for (uint8_t i = 0; i < _size; i++) { - _buffer[i] = {}; + _buffer[i].time_us = 0; } _head = 0; diff --git a/src/lib/ringbuffer/TimestampedRingBufferTest.cpp b/src/lib/ringbuffer/TimestampedRingBufferDynamicTest.cpp similarity index 78% rename from src/lib/ringbuffer/TimestampedRingBufferTest.cpp rename to src/lib/ringbuffer/TimestampedRingBufferDynamicTest.cpp index 83f5fa7940e..15a64a5be9e 100644 --- a/src/lib/ringbuffer/TimestampedRingBufferTest.cpp +++ b/src/lib/ringbuffer/TimestampedRingBufferDynamicTest.cpp @@ -41,7 +41,7 @@ struct sample { }; -class TimestampedRingBufferTest : public ::testing::Test +class TimestampedRingBufferDynamicTest : public ::testing::Test { public: @@ -67,15 +67,24 @@ public: } }; -TEST_F(TimestampedRingBufferTest, goodInitialisation) +TEST_F(TimestampedRingBufferDynamicTest, goodInitialisation) { // WHEN: buffer was allocated // THEN: allocation should have succeed - ASSERT_EQ(true, _buffer->allocate(3)); - + EXPECT_TRUE(_buffer->allocate(3)); + EXPECT_TRUE(_buffer->valid()); + EXPECT_EQ(_buffer->get_length(), 3); } -TEST_F(TimestampedRingBufferTest, badInitialisation) +TEST_F(TimestampedRingBufferDynamicTest, RejectsInvalidSize) +{ + EXPECT_FALSE(_buffer->allocate(0)); + EXPECT_FALSE(_buffer->allocate(UINT8_MAX + 1u)); + EXPECT_TRUE(_buffer->valid()); + EXPECT_EQ(_buffer->get_length(), 3); +} + +TEST_F(TimestampedRingBufferDynamicTest, badInitialisation) { // WHEN: buffer allocation input is bad // THEN: allocation should fail @@ -85,7 +94,7 @@ TEST_F(TimestampedRingBufferTest, badInitialisation) // ASSERT_EQ(false, _buffer->allocate(0)); } -TEST_F(TimestampedRingBufferTest, orderOfSamples) +TEST_F(TimestampedRingBufferDynamicTest, orderOfSamples) { ASSERT_EQ(true, _buffer->allocate(3)); // GIVEN: allocated buffer @@ -103,7 +112,7 @@ TEST_F(TimestampedRingBufferTest, orderOfSamples) EXPECT_EQ(_y.time_us, _buffer->get_newest().time_us); } -TEST_F(TimestampedRingBufferTest, popSample) +TEST_F(TimestampedRingBufferDynamicTest, popSample) { ASSERT_EQ(true, _buffer->allocate(3)); _buffer->push(_x); @@ -115,20 +124,20 @@ TEST_F(TimestampedRingBufferTest, popSample) sample pop = {}; // WHEN: we want to retrieve a sample that is older than any in the buffer // THEN: we should not get any sample - EXPECT_EQ(false, _buffer->pop_first_older_than(0, &pop)); + EXPECT_FALSE(_buffer->pop_first_older_than(0, &pop)); // WHEN: when calling "pop_first_older_than" // THEN: we should get the first sample from the head that is older - EXPECT_EQ(true, _buffer->pop_first_older_than(_x.time_us + 1, &pop)); + EXPECT_TRUE(_buffer->pop_first_older_than(_x.time_us + 1, &pop)); EXPECT_EQ(_x.time_us, pop.time_us); - EXPECT_EQ(true, _buffer->pop_first_older_than(_y.time_us + 10, &pop)); + EXPECT_TRUE(_buffer->pop_first_older_than(_y.time_us + 10, &pop)); EXPECT_EQ(_y.time_us, pop.time_us); - EXPECT_EQ(true, _buffer->pop_first_older_than(_z.time_us + 100, &pop)); + EXPECT_TRUE(_buffer->pop_first_older_than(_z.time_us + 100, &pop)); EXPECT_EQ(_z.time_us, pop.time_us); // TODO: When changing the order of popping sample it does not behave as expected, fix this } -TEST_F(TimestampedRingBufferTest, askingForTooNewSample) +TEST_F(TimestampedRingBufferDynamicTest, askingForTooNewSample) { ASSERT_EQ(true, _buffer->allocate(3)); _buffer->push(_x); @@ -138,11 +147,11 @@ TEST_F(TimestampedRingBufferTest, askingForTooNewSample) sample pop = {}; // WHEN: all buffered samples are older by 0.1s than your query timestamp // THEN: should get no sample returned - EXPECT_EQ(true, _buffer->pop_first_older_than(_z.time_us + 99000, &pop)); - EXPECT_EQ(false, _buffer->pop_first_older_than(_y.time_us + 100000, &pop)); + EXPECT_TRUE(_buffer->pop_first_older_than(_z.time_us + 99000, &pop)); + EXPECT_FALSE(_buffer->pop_first_older_than(_y.time_us + 100000, &pop)); } -TEST_F(TimestampedRingBufferTest, reallocateBuffer) +TEST_F(TimestampedRingBufferDynamicTest, reallocateBuffer) { ASSERT_EQ(true, _buffer->allocate(5)); _buffer->push(_x); @@ -153,8 +162,7 @@ TEST_F(TimestampedRingBufferTest, reallocateBuffer) // GIVEN: allocated and filled buffer // WHEN: do another allocate call - _buffer->allocate(3); + EXPECT_TRUE(_buffer->allocate(3)); // THEN: its length should update EXPECT_EQ(3, _buffer->get_length()); - } diff --git a/src/lib/ringbuffer/TimestampedRingBufferStaticTest.cpp b/src/lib/ringbuffer/TimestampedRingBufferStaticTest.cpp new file mode 100644 index 00000000000..89c653c35e7 --- /dev/null +++ b/src/lib/ringbuffer/TimestampedRingBufferStaticTest.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** + * + * Copyright (c) 2019-2023 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include +#include +#include "TimestampedRingBuffer.hpp" + +struct Sample { + uint64_t time_us; + float data[3]; +}; + + +class TimestampedRingBufferStaticTest : public ::testing::Test +{ +public: + Sample _x, _y, _z, _w; + TimestampedRingBuffer *_buffer{nullptr}; + + void SetUp() override + { + _buffer = new TimestampedRingBuffer(); + _x.time_us = 1000000; + _x.data[0] = _x.data[1] = _x.data[2] = 1.5f; + + _y.time_us = 2000000; + _y.data[0] = _y.data[1] = _y.data[2] = 3.0f; + + _z.time_us = 3000000; + _z.data[0] = _z.data[1] = _z.data[2] = 4.0f; + + _w.time_us = 4000000; + _w.data[0] = _w.data[1] = _w.data[2] = 5.0f; + } + + void TearDown() override + { + delete _buffer; + } +}; + +TEST_F(TimestampedRingBufferStaticTest, goodInitialisation) +{ + // WHEN: buffer was allocated + // THEN: allocation should have succeed + EXPECT_TRUE(_buffer->valid()); + EXPECT_FALSE(_buffer->allocate(2)); + EXPECT_EQ(_buffer->get_length(), 3); +} + +TEST_F(TimestampedRingBufferStaticTest, NextPrevHelpers) +{ + EXPECT_EQ(_buffer->next(0), 1); + EXPECT_EQ(_buffer->next(1), 2); + EXPECT_EQ(_buffer->next(2), 0); + + EXPECT_EQ(_buffer->prev(0), 2); + EXPECT_EQ(_buffer->prev(1), 0); + EXPECT_EQ(_buffer->prev(2), 1); +} + +TEST_F(TimestampedRingBufferStaticTest, PushWrapAndIndices) +{ + _buffer->reset(); + ASSERT_TRUE(_buffer->empty()); + + _buffer->push(_x); + _buffer->push(_y); + EXPECT_EQ(_buffer->entries(), 2); + _buffer->push(_z); + + EXPECT_EQ(_buffer->entries(), 3); + EXPECT_EQ(_buffer->get_oldest().time_us, _x.time_us); + EXPECT_EQ(_buffer->get_newest().time_us, _z.time_us); + + // Overwrite once (ring wrap-around). + _buffer->push(_w); + + EXPECT_EQ(_buffer->entries(), 3); + EXPECT_EQ(_buffer->get_oldest().time_us, _y.time_us); + EXPECT_EQ(_buffer->get_newest().time_us, _w.time_us); +} + +TEST_F(TimestampedRingBufferStaticTest, PopFirstOlderThanDiscardsOlderHistory) +{ + _buffer->reset(); + _buffer->push(_x); + _buffer->push(_y); + _buffer->push(_z); + + Sample pop = {}; + + // Query timestamp older than any in the buffer: no match. + EXPECT_FALSE(_buffer->pop_first_older_than(0, &pop)); + + // Pop y (also discards x), leaving z as the only remaining Sample. + EXPECT_TRUE(_buffer->pop_first_older_than(_y.time_us + 10, &pop)); + EXPECT_EQ(pop.time_us, _y.time_us); + + EXPECT_EQ(_buffer->entries(), 1); + EXPECT_EQ(_buffer->get_oldest().time_us, _z.time_us); + EXPECT_EQ(_buffer->get_newest().time_us, _z.time_us); + + // Pop z (buffer becomes empty). + EXPECT_TRUE(_buffer->pop_first_older_than(_z.time_us + 1, &pop)); + EXPECT_EQ(pop.time_us, _z.time_us); + EXPECT_TRUE(_buffer->empty()); +} + +TEST_F(TimestampedRingBufferStaticTest, ResetClearsTimestamps) +{ + _buffer->push(_x); + _buffer->push(_y); + EXPECT_FALSE(_buffer->empty()); + + _buffer->reset(); + EXPECT_TRUE(_buffer->empty()); + + for (uint8_t i = 0; i < _buffer->get_length(); i++) { + EXPECT_EQ((*_buffer)[i].time_us, 0u); + } +} + +TEST_F(TimestampedRingBufferStaticTest, TotalSizeReflectsInlineStorage) +{ + EXPECT_EQ(_buffer->get_total_size(), static_cast(sizeof(TimestampedRingBuffer))); +} diff --git a/src/modules/ekf2/EKF2.cpp b/src/modules/ekf2/EKF2.cpp index 2bd9cf90b35..58b505345c8 100644 --- a/src/modules/ekf2/EKF2.cpp +++ b/src/modules/ekf2/EKF2.cpp @@ -2310,9 +2310,13 @@ void EKF2::UpdateAuxVelSample(ekf2_timestamps_s &ekf2_timestamps) // - use the landing target pose estimate as another source of velocity data landing_target_pose_s landing_target_pose; + if (!_param_ekf2_avel_en.get()) { + return; + } + if (_landing_target_pose_sub.update(&landing_target_pose)) { - // we can only use the landing target if it has a fixed position and a valid velocity estimate - if (landing_target_pose.is_static && landing_target_pose.rel_vel_valid) { + + if (landing_target_pose.rel_vel_ekf2_valid) { // velocity of vehicle relative to target has opposite sign to target relative to vehicle auxVelSample auxvel_sample{ .time_us = landing_target_pose.timestamp, diff --git a/src/modules/ekf2/EKF2.hpp b/src/modules/ekf2/EKF2.hpp index 4b9ef509429..fffed51789c 100644 --- a/src/modules/ekf2/EKF2.hpp +++ b/src/modules/ekf2/EKF2.hpp @@ -534,6 +534,8 @@ private: #if defined(CONFIG_EKF2_AUXVEL) (ParamExtFloat) _param_ekf2_avel_delay, ///< auxiliary velocity measurement delay relative to the IMU (mSec) + (ParamBool) + _param_ekf2_avel_en, ///< fuse landing_target_pose relative velocity as auxiliary velocity #endif // CONFIG_EKF2_AUXVEL (ParamExtFloat) diff --git a/src/modules/ekf2/params_aux_velocity.yaml b/src/modules/ekf2/params_aux_velocity.yaml index 93b38587c02..9d6814012eb 100644 --- a/src/modules/ekf2/params_aux_velocity.yaml +++ b/src/modules/ekf2/params_aux_velocity.yaml @@ -2,6 +2,15 @@ module_name: ekf2 parameters: - group: EKF2 definitions: + EKF2_AVEL_EN: + description: + short: Fuse the landing-target relative velocity as auxiliary velocity + long: |- + When enabled, EKF2 fuses the relative velocity published in landing_target_pose + (vx_rel, vy_rel) as a horizontal auxiliary velocity measurement. The data is + only fused when landing_target_pose.rel_vel_ekf2_valid is true. + type: boolean + default: 1 EKF2_AVEL_DELAY: description: short: Auxiliary Velocity Estimate delay relative to IMU measurements diff --git a/src/modules/flight_mode_manager/tasks/Auto/FlightTaskAuto.cpp b/src/modules/flight_mode_manager/tasks/Auto/FlightTaskAuto.cpp index 7fdf29ec046..80f2e13d2b8 100644 --- a/src/modules/flight_mode_manager/tasks/Auto/FlightTaskAuto.cpp +++ b/src/modules/flight_mode_manager/tasks/Auto/FlightTaskAuto.cpp @@ -93,6 +93,9 @@ bool FlightTaskAuto::updateInitialize() _sub_home_position.update(); _sub_vehicle_status.update(); _position_setpoint_triplet_sub.update(); +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + _prec_land_status_sub.update(); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR // require valid reference and valid target ret = ret && _evaluateGlobalReference() && _evaluatePositionSetpointTriplet(); @@ -238,7 +241,12 @@ void FlightTaskAuto::_prepareLandSetpoints() if (_type_previous != WaypointType::land) { // initialize yaw and xy-position - _land_heading = _yaw_setpoint; + _land_heading = PX4_ISFINITE(_yaw_setpoint) ? _yaw_setpoint : _yaw_setpoint_previous; + + if (!PX4_ISFINITE(_land_heading)) { + _land_heading = _yaw; + } + _stick_acceleration_xy.resetPosition(Vector2f(_triplet_current)); _initial_land_position = Vector3f(_triplet_current(0), _triplet_current(1), NAN); } @@ -246,6 +254,21 @@ void FlightTaskAuto::_prepareLandSetpoints() // Update xy-position in case of landing position changes (etc. precision landing) _land_position = Vector3f(_triplet_current(0), _triplet_current(1), NAN); +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + + // Use the raw navigator/precland yaw command here. _yaw_setpoint can stay finite from + // generic land yaw logic even after precland clears current.yaw. + const uint8_t pld_state = _prec_land_status_sub.get().state; + const bool pld_ongoing = pld_state != prec_land_status_s::PREC_LAND_STATE_STOPPED + && pld_state != prec_land_status_s::PREC_LAND_STATE_DONE; + + if (_param_pld_yaw_en.get() && pld_ongoing) { + const float prec_land_yaw = _position_setpoint_triplet_sub.get().current.yaw; + _land_heading = PX4_ISFINITE(prec_land_yaw) ? prec_land_yaw : _yaw; + } + +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + // User input assisted landing if (_param_mpc_land_rc_help.get() && _sticks.checkAndUpdateStickInputs()) { // Stick full up -1 -> stop, stick full down 1 -> double the speed diff --git a/src/modules/flight_mode_manager/tasks/Auto/FlightTaskAuto.hpp b/src/modules/flight_mode_manager/tasks/Auto/FlightTaskAuto.hpp index 6541c862d0e..eb21ca3a051 100644 --- a/src/modules/flight_mode_manager/tasks/Auto/FlightTaskAuto.hpp +++ b/src/modules/flight_mode_manager/tasks/Auto/FlightTaskAuto.hpp @@ -44,6 +44,9 @@ #include #include #include +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +#include +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR #include #include #include @@ -120,7 +123,10 @@ protected: WaypointType _type{WaypointType::idle}; /**< Type of current target triplet. */ uORB::SubscriptionData _position_setpoint_triplet_sub{ORB_ID(position_setpoint_triplet)}; - uORB::SubscriptionData _sub_home_position{ORB_ID(home_position)}; +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + uORB::SubscriptionData _prec_land_status_sub {ORB_ID(prec_land_status)}; +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + uORB::SubscriptionData _sub_home_position {ORB_ID(home_position)}; uORB::SubscriptionData _sub_vehicle_status{ORB_ID(vehicle_status)}; float _target_acceptance_radius{0.0f}; /**< Acceptances radius of the target */ @@ -141,6 +147,9 @@ protected: bool _want_takeoff{false}; DEFINE_PARAMETERS_CUSTOM_PARENT(FlightTask, +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + (ParamInt) _param_pld_yaw_en, +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR (ParamFloat) _param_mpc_xy_cruise, (ParamFloat) _param_nav_mc_alt_rad, //vertical acceptance radius at which waypoints are updated diff --git a/src/modules/landing_target_estimator/LandingTargetEstimator.cpp b/src/modules/landing_target_estimator/LandingTargetEstimator.cpp index 5e09de57d71..2b05dda66db 100644 --- a/src/modules/landing_target_estimator/LandingTargetEstimator.cpp +++ b/src/modules/landing_target_estimator/LandingTargetEstimator.cpp @@ -152,6 +152,7 @@ void LandingTargetEstimator::update() _target_pose.rel_pos_valid = true; _target_pose.rel_vel_valid = true; + _target_pose.rel_vel_ekf2_valid = _target_pose.is_static && _target_pose.rel_vel_valid; _target_pose.x_rel = x; _target_pose.y_rel = y; _target_pose.z_rel = _target_position_report.rel_pos_z ; diff --git a/src/modules/local_position_estimator/BlockLocalPositionEstimator.hpp b/src/modules/local_position_estimator/BlockLocalPositionEstimator.hpp index 62bcb579f0e..0959d661531 100644 --- a/src/modules/local_position_estimator/BlockLocalPositionEstimator.hpp +++ b/src/modules/local_position_estimator/BlockLocalPositionEstimator.hpp @@ -299,12 +299,6 @@ private: MapProjection _global_local_proj_ref{}; float _global_local_alt0{NAN}; - // target mode paramters from landing_target_estimator module - enum TargetMode { - Target_Moving = 0, - Target_Stationary = 1 - }; - // flow gyro filter BlockHighPass _flow_gyro_x_high_pass; BlockHighPass _flow_gyro_y_high_pass; @@ -457,7 +451,6 @@ private: (ParamFloat) _param_lpe_t_max_grade, (ParamFloat) _param_lpe_lt_cov, - (ParamInt) _param_ltest_mode, // init origin (ParamInt) _param_lpe_fake_origin, diff --git a/src/modules/local_position_estimator/sensors/landing_target.cpp b/src/modules/local_position_estimator/sensors/landing_target.cpp index 6472fc198fa..31528628893 100644 --- a/src/modules/local_position_estimator/sensors/landing_target.cpp +++ b/src/modules/local_position_estimator/sensors/landing_target.cpp @@ -8,7 +8,7 @@ static const uint64_t TARGET_TIMEOUT = 2000000; // [us] void BlockLocalPositionEstimator::landingTargetInit() { - if (_param_ltest_mode.get() == Target_Moving) { + if (!_sub_landing_target_pose.get().is_static) { // target is in moving mode, do not initialize return; } @@ -24,7 +24,7 @@ void BlockLocalPositionEstimator::landingTargetInit() int BlockLocalPositionEstimator::landingTargetMeasure(Vector &y) { - if (_param_ltest_mode.get() == Target_Stationary) { + if (_sub_landing_target_pose.get().is_static) { if (_sub_landing_target_pose.get().rel_vel_valid) { y(0) = _sub_landing_target_pose.get().vx_rel; y(1) = _sub_landing_target_pose.get().vy_rel; @@ -43,7 +43,7 @@ int BlockLocalPositionEstimator::landingTargetMeasure(Vector void BlockLocalPositionEstimator::landingTargetCorrect() { - if (_param_ltest_mode.get() == Target_Moving) { + if (!_sub_landing_target_pose.get().is_static) { // nothing to do in this mode return; } diff --git a/src/modules/logger/logged_topics.cpp b/src/modules/logger/logged_topics.cpp index fae125ecc5b..8bcf9a9608c 100644 --- a/src/modules/logger/logged_topics.cpp +++ b/src/modules/logger/logged_topics.cpp @@ -196,6 +196,23 @@ void LoggedTopics::add_default_topics() add_optional_topic_multi("estimator_status_flags", 10); add_optional_topic_multi("yaw_estimator_status", 1000); + // Vision target estimator topics +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + add_topic("vte_input", 50); + add_topic("vte_position", 100); + add_topic("vte_orientation", 100); + add_topic("vte_bias_init_status", 10); // High rate because rarely published and only for a short period of time + add_topic("vte_aid_gps_pos_target", 100); + add_topic("vte_aid_gps_pos_mission", 100); + add_topic("vte_aid_gps_vel_uav", 100); + add_topic("vte_aid_gps_vel_target", 100); + add_topic("vte_aid_fiducial_marker", 100); + add_topic("vte_aid_ev_yaw", 100); + add_topic("fiducial_marker_pos_report", 100); + add_topic("fiducial_marker_yaw_report", 100); + add_topic("target_gnss", 100); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + // log all raw sensors at minimal rate (at least 1 Hz) add_topic_multi("battery_status", 200, 3); add_topic_multi("differential_pressure", 1000, 2); diff --git a/src/modules/mavlink/mavlink_receiver.cpp b/src/modules/mavlink/mavlink_receiver.cpp index eb865512c73..e10d130056c 100644 --- a/src/modules/mavlink/mavlink_receiver.cpp +++ b/src/modules/mavlink/mavlink_receiver.cpp @@ -116,6 +116,9 @@ MavlinkReceiver::MavlinkReceiver(Mavlink &parent) : _parameters_manager(parent), _mavlink_timesync(parent) { +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + _param_vte_en = param_find("VTE_EN"); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR } void @@ -315,6 +318,23 @@ MavlinkReceiver::handle_message(mavlink_message_t *msg) break; #endif // !CONSTRAINED_FLASH +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +#if defined(MAVLINK_MSG_ID_TARGET_RELATIVE) + + case MAVLINK_MSG_ID_TARGET_RELATIVE: + handle_message_target_relative(msg); + break; +#endif // MAVLINK_MSG_ID_TARGET_RELATIVE + +#if defined(MAVLINK_MSG_ID_TARGET_ABSOLUTE) + + case MAVLINK_MSG_ID_TARGET_ABSOLUTE: + handle_message_target_absolute(msg); + break; +#endif // MAVLINK_MSG_ID_TARGET_ABSOLUTE + +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + case MAVLINK_MSG_ID_GIMBAL_MANAGER_SET_ATTITUDE: handle_message_gimbal_manager_set_attitude(msg); break; @@ -3046,6 +3066,241 @@ MavlinkReceiver::handle_message_debug_float_array(mavlink_message_t *msg) } #endif // !CONSTRAINED_FLASH +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + +#if defined(MAVLINK_MSG_ID_TARGET_ABSOLUTE) +void +MavlinkReceiver::handle_message_target_absolute(mavlink_message_t *msg) +{ + mavlink_target_absolute_t target_absolute; + mavlink_msg_target_absolute_decode(msg, &target_absolute); + + target_gnss_s target_GNSS_report{}; + + target_GNSS_report.timestamp = hrt_absolute_time(); + target_GNSS_report.timestamp_sample = _mavlink_timesync.sync_stamp(target_absolute.timestamp); + + bool updated = false; + + // Position: bit 0 + if (!(target_absolute.sensor_capabilities & static_cast(TargetAbsoluteSensorCapability::kPosition))) { + target_GNSS_report.abs_pos_updated = false; + + } else { + target_GNSS_report.abs_pos_updated = true; + target_GNSS_report.latitude_deg = target_absolute.lat * 1e-7; + target_GNSS_report.longitude_deg = target_absolute.lon * 1e-7; + target_GNSS_report.altitude_msl_m = target_absolute.alt; + target_GNSS_report.eph = target_absolute.position_std[0]; + target_GNSS_report.epv = target_absolute.position_std[1]; + updated = true; + } + + // Velocity: bit 1 + if (!(target_absolute.sensor_capabilities & static_cast(TargetAbsoluteSensorCapability::kVelocity))) { + target_GNSS_report.vel_ned_updated = false; + + } else { + const matrix::Quatf q_target(target_absolute.q_target); + const bool target_attitude_available = (fabsf(q_target(0)) + fabsf(q_target(1)) + fabsf(q_target(2)) + + fabsf(q_target(3))) > FLT_EPSILON; + + if (target_attitude_available) { + const matrix::Vector3f vel_target_body(target_absolute.vel[0], target_absolute.vel[1], target_absolute.vel[2]); + const matrix::Vector3f vel_target_ned = q_target.rotateVector(vel_target_body); + + target_GNSS_report.vel_ned_updated = true; + target_GNSS_report.vel_n_m_s = vel_target_ned(0); + target_GNSS_report.vel_e_m_s = vel_target_ned(1); + target_GNSS_report.vel_d_m_s = vel_target_ned(2); + target_GNSS_report.s_acc_m_s = fmaxf(fabsf(target_absolute.vel_std[0]), + fmaxf(fabsf(target_absolute.vel_std[1]), + fabsf(target_absolute.vel_std[2]))); + updated = true; + + } else { + target_GNSS_report.vel_ned_updated = false; + } + } + + if (updated) { _target_gnss_pub.publish(target_GNSS_report); } +} +#endif // MAVLINK_MSG_ID_TARGET_ABSOLUTE + +#if defined(MAVLINK_MSG_ID_TARGET_RELATIVE) +void +MavlinkReceiver::handle_message_target_relative(mavlink_message_t *msg) +{ + mavlink_target_relative_t target_relative; + mavlink_msg_target_relative_decode(msg, &target_relative); + + vehicle_attitude_s vehicle_attitude; + vehicle_local_position_s vehicle_local_position; + + // Unsupported sensor frame + if (target_relative.frame != TARGET_OBS_FRAME_LOCAL_OFFSET_NED && target_relative.frame != TARGET_OBS_FRAME_LOCAL_NED && + target_relative.frame != TARGET_OBS_FRAME_BODY_FRD && target_relative.frame != TARGET_OBS_FRAME_OTHER) { + mavlink_log_critical(&_mavlink_log_pub, "target relative: coordinate frame %" PRIu8 " unsupported.\t", + target_relative.frame); + events::send(events::ID("mavlink_rcv_target_rel_unsup_coord_frame"), events::Log::Error, + "Target relative: unsupported coordinate frame {1}", target_relative.frame); + + return; + } + + // Unsupported measurement type + if (target_relative.type != LANDING_TARGET_TYPE_VISION_FIDUCIAL) { + mavlink_log_critical(&_mavlink_log_pub, "target relative: type %" PRIu8 " unsupported.\t", + target_relative.type); + events::send(events::ID("mavlink_rcv_target_rel_unsup_type"), events::Log::Error, + "Target relative: unsupported type {1}", target_relative.type); + return; + } + + matrix::Quatf q_sensor(target_relative.q_sensor); + bool attitude_available = (fabsf(q_sensor(0)) + fabsf(q_sensor(1)) + fabsf(q_sensor(2)) + + fabsf(q_sensor(3))) > FLT_EPSILON; + + // Check if attitude can be infered based on the frame + if (!attitude_available) { + if (target_relative.frame == TARGET_OBS_FRAME_LOCAL_OFFSET_NED || target_relative.frame == TARGET_OBS_FRAME_LOCAL_NED) { + // Observation already in NED, set quaternion to identity (1,0,0,0) + q_sensor.setIdentity(); + attitude_available = true; + + } else if (target_relative.frame == TARGET_OBS_FRAME_BODY_FRD && _vehicle_attitude_sub.copy(&vehicle_attitude)) { + // Set the quaternion to the current attitude + const matrix::Quaternionf quat_att(&vehicle_attitude.q[0]); + q_sensor = quat_att; + attitude_available = true; + + } else if (target_relative.frame == TARGET_OBS_FRAME_OTHER) { + // Target sensor frame: OTHER and no quaternion is provided + mavlink_log_critical(&_mavlink_log_pub, + "target relative: coordinate frame %" PRIu8 " unsupported when the q_sensor is not filled.\t", + target_relative.frame); + events::send(events::ID("mavlink_rcv_target_rel_q_sensor_not_filled"), events::Log::Error, + "Target relative: unsupported coordinate frame {1} when the q_sensor is not filled", target_relative.frame); + } + } + + // Target cannot be sent without valid attitude + if (!attitude_available) { + return; + } + + // Forward target to the vision target estimator (VTE) or precland based VTE_EN + int32_t vte_enabled = 0; + + if (_param_vte_en == PARAM_INVALID) { + if (hrt_elapsed_time(&_vte_en_invalid_warn_last) > 20_s) { + PX4_WARN(" Could not find VTE_EN, target_relative msg ignored."); + _vte_en_invalid_warn_last = hrt_absolute_time(); + } + + return; + + } else { + param_get(_param_vte_en, &vte_enabled); + } + + if (!vte_enabled) { + + // Send the target directly to the precision landing algorithm in local NED frame + landing_target_pose_s landing_target_pose{}; + landing_target_pose.timestamp = _mavlink_timesync.sync_stamp(target_relative.timestamp); + + // Measurement already in local NED + if (target_relative.frame == TARGET_OBS_FRAME_LOCAL_NED) { + + landing_target_pose.x_abs = target_relative.x; + landing_target_pose.y_abs = target_relative.y; + landing_target_pose.z_abs = target_relative.z; + landing_target_pose.abs_pos_valid = true; + + _landing_target_pose_pub.publish(landing_target_pose); + + } else if (_vehicle_local_position_sub.copy(&vehicle_local_position) + && vehicle_local_position.xy_valid && vehicle_local_position.z_valid) { + + // If the local position is available, convert from sensor frame to local NED + matrix::Vector3f target_relative_frame(target_relative.x, target_relative.y, target_relative.z); + + if (target_relative.frame == TARGET_OBS_FRAME_BODY_FRD || target_relative.frame == TARGET_OBS_FRAME_OTHER) { + // Rotate measurement into vehicle-carried NED + target_relative_frame = q_sensor.rotateVector(target_relative_frame); + } + + // Convert from vehicle-carried NED to local NED + landing_target_pose.x_abs = target_relative_frame(0) + vehicle_local_position.x; + landing_target_pose.y_abs = target_relative_frame(1) + vehicle_local_position.y; + landing_target_pose.z_abs = target_relative_frame(2) + vehicle_local_position.z; + landing_target_pose.abs_pos_valid = true; + + _landing_target_pose_pub.publish(landing_target_pose); + } + + } else { + + // Only supported type: LANDING_TARGET_TYPE_VISION_FIDUCIAL + + // Position report + fiducial_marker_pos_report_s fiducial_marker_pos_report{}; + + const hrt_abstime now = hrt_absolute_time(); + const hrt_abstime timestamp_sample = _mavlink_timesync.sync_stamp(target_relative.timestamp); + + fiducial_marker_pos_report.timestamp = now; + fiducial_marker_pos_report.timestamp_sample = timestamp_sample; + matrix::Vector3f target_relative_frame(target_relative.x, target_relative.y, target_relative.z); + + // TARGET_OBS_FRAME_LOCAL_NED is absolute in local frame: convert to vehicle-relative. + if (target_relative.frame == TARGET_OBS_FRAME_LOCAL_NED) { + if (!_vehicle_local_position_sub.copy(&vehicle_local_position) + || !vehicle_local_position.xy_valid || !vehicle_local_position.z_valid) { + return; + } + + target_relative_frame(0) -= vehicle_local_position.x; + target_relative_frame(1) -= vehicle_local_position.y; + target_relative_frame(2) -= vehicle_local_position.z; + } + + fiducial_marker_pos_report.rel_pos[0] = target_relative_frame(0); + fiducial_marker_pos_report.rel_pos[1] = target_relative_frame(1); + fiducial_marker_pos_report.rel_pos[2] = target_relative_frame(2); + + fiducial_marker_pos_report.cov_rel_pos[0] = target_relative.pos_std[0] * target_relative.pos_std[0]; + fiducial_marker_pos_report.cov_rel_pos[1] = target_relative.pos_std[1] * target_relative.pos_std[1]; + fiducial_marker_pos_report.cov_rel_pos[2] = target_relative.pos_std[2] * target_relative.pos_std[2]; + + q_sensor.copyTo(fiducial_marker_pos_report.q); + _fiducial_marker_pos_report_pub.publish(fiducial_marker_pos_report); + + const matrix::Quatf q_target(target_relative.q_target); + const bool target_attitude_available = (fabsf(q_target(0)) + fabsf(q_target(1)) + fabsf(q_target(2)) + + fabsf(q_target(3))) > FLT_EPSILON; + + if (target_attitude_available) { + // Yaw report + fiducial_marker_yaw_report_s fiducial_marker_yaw_report{}; + fiducial_marker_yaw_report.timestamp = now; + fiducial_marker_yaw_report.timestamp_sample = timestamp_sample; + + // Transform quaternion from the target's frame to the TARGET_OBS_FRAME to the yaw relative to NED + const matrix::Quatf q_in_ned = q_sensor * q_target; + const float target_yaw_ned = matrix::Eulerf(q_in_ned).psi(); + + fiducial_marker_yaw_report.yaw_ned = target_yaw_ned; + fiducial_marker_yaw_report.yaw_var_ned = target_relative.yaw_std * target_relative.yaw_std; + _fiducial_marker_yaw_report_pub.publish(fiducial_marker_yaw_report); + } + } + +} +#endif // MAVLINK_MSG_ID_TARGET_RELATIVE +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + void MavlinkReceiver::handle_message_onboard_computer_status(mavlink_message_t *msg) { diff --git a/src/modules/mavlink/mavlink_receiver.h b/src/modules/mavlink/mavlink_receiver.h index 5d22b784aa2..62d7c6aa5bd 100644 --- a/src/modules/mavlink/mavlink_receiver.h +++ b/src/modules/mavlink/mavlink_receiver.h @@ -126,8 +126,24 @@ # include #endif // !CONSTRAINED_FLASH +# if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +# include +# include +# include +# endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + using namespace time_literals; +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +enum class TargetAbsoluteSensorCapability : uint8_t { + kPosition = (1 << 0), + kVelocity = (1 << 1), + kAcceleration = (1 << 2), + kAttitude = (1 << 3), + kRates = (1 << 4), +}; +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + class Mavlink; class MavlinkReceiver : public ModuleParams @@ -230,6 +246,12 @@ private: void handle_message_debug_vect(mavlink_message_t *msg); void handle_message_named_value_float(mavlink_message_t *msg); #endif // !CONSTRAINED_FLASH + +# if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + void handle_message_target_relative(mavlink_message_t *msg); + void handle_message_target_absolute(mavlink_message_t *msg); +# endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + void handle_message_request_event(mavlink_message_t *msg); void CheckHeartbeats(const hrt_abstime &t, bool force = false); @@ -360,6 +382,14 @@ private: uORB::Publication _debug_vect_pub{ORB_ID(debug_vect)}; #endif // !CONSTRAINED_FLASH +# if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + uORB::Publication _fiducial_marker_pos_report_pub {ORB_ID(fiducial_marker_pos_report)}; + uORB::Publication _fiducial_marker_yaw_report_pub{ORB_ID(fiducial_marker_yaw_report)}; + uORB::Publication _target_gnss_pub{ORB_ID(target_gnss)}; + param_t _param_vte_en{PARAM_INVALID}; + hrt_abstime _vte_en_invalid_warn_last{0}; +# endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + // ORB publications (multi) uORB::PublicationMulti _distance_sensor_pub{ORB_ID(distance_sensor)}; uORB::PublicationMulti _aux_global_position_pub{ORB_ID(aux_global_position)}; diff --git a/src/modules/navigator/precland.cpp b/src/modules/navigator/precland.cpp index a111bf75c93..848c5e3415e 100644 --- a/src/modules/navigator/precland.cpp +++ b/src/modules/navigator/precland.cpp @@ -47,6 +47,8 @@ #include #include +#include +#include #include #include @@ -68,6 +70,12 @@ PrecLand::PrecLand(Navigator *navigator) : _handle_param_acceleration_hor = param_find("MPC_ACC_HOR"); _handle_param_xy_vel_cruise = param_find("MPC_XY_CRUISE"); +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +# if defined(CONFIG_VTEST_MOVING) + _handle_param_z_v_auto_dn = param_find("MPC_Z_V_AUTO_DN"); +# endif // CONFIG_VTEST_MOVING +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + updateParams(); } @@ -78,6 +86,10 @@ PrecLand::on_activation() _search_cnt = 0; _last_slewrate_time = 0; +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + reset_target_yaw_state(); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + vehicle_local_position_s *vehicle_local_position = _navigator->get_local_position(); if (!_map_ref.isInitialized()) { @@ -122,8 +134,35 @@ PrecLand::on_active() _target_pose_valid = false; } +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + + // get orientation measurement + if (_param_pld_yaw_en.get()) { + vte_orientation_s target_orientation; + + if (_target_orientation_sub.update(&target_orientation)) { + if (target_orientation.orientation_valid) { + _target_yaw_valid = true; + _last_target_yaw_update = target_orientation.timestamp; + _target_yaw = target_orientation.yaw; + + } else { + reset_target_yaw_state(); + } + } + + if (_target_yaw_valid && ((hrt_elapsed_time(&_last_target_yaw_update) / 1e6f) > _param_pld_btout.get())) { + reset_target_yaw_state(); + } + + } else { + reset_target_yaw_state(); + } + +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + // stop if we are landed - if (_navigator->get_land_detected()->landed) { + if (_navigator->get_land_detected()->landed && _state != PrecLandState::Done) { switch_to_state_done(); } @@ -161,11 +200,21 @@ PrecLand::on_active() break; } +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + publish_prec_land_status(map_prec_land_state(_state)); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR } void PrecLand::on_inactivation() { + clear_current_yaw_setpoint(); + _navigator->set_position_setpoint_triplet_updated(); + +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + reset_target_yaw_state(); + publish_prec_land_status(prec_land_status_s::PREC_LAND_STATE_STOPPED); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR _is_activated = false; } @@ -181,6 +230,16 @@ PrecLand::updateParams() if (_handle_param_xy_vel_cruise != PARAM_INVALID) { param_get(_handle_param_xy_vel_cruise, &_param_xy_vel_cruise); } + +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +# if defined(CONFIG_VTEST_MOVING) + + if (_handle_param_z_v_auto_dn != PARAM_INVALID) { + param_get(_handle_param_z_v_auto_dn, &_param_z_v_auto_dn); + } + +# endif // CONFIG_VTEST_MOVING +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR } void @@ -257,8 +316,9 @@ PrecLand::run_state_horizontal_approach() } - float x = _target_pose.x_abs; - float y = _target_pose.y_abs; + matrix::Vector2f target_position_sp = get_target_position_setpoint(); + float x = target_position_sp(0); + float y = target_position_sp(1); slewrate(x, y); @@ -268,6 +328,10 @@ PrecLand::run_state_horizontal_approach() pos_sp_triplet->current.alt = _approach_alt; pos_sp_triplet->current.type = position_setpoint_s::SETPOINT_TYPE_POSITION; +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + update_current_yaw_setpoint(); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + _navigator->set_position_setpoint_triplet_updated(); } @@ -294,10 +358,16 @@ PrecLand::run_state_descend_above_target() return; } + const matrix::Vector2f target_position_sp = get_target_position_setpoint(); + // XXX need to transform to GPS coords because mc_pos_control only looks at that - _map_ref.reproject(_target_pose.x_abs, _target_pose.y_abs, pos_sp_triplet->current.lat, pos_sp_triplet->current.lon); + _map_ref.reproject(target_position_sp(0), target_position_sp(1), pos_sp_triplet->current.lat, + pos_sp_triplet->current.lon); pos_sp_triplet->current.type = position_setpoint_s::SETPOINT_TYPE_LAND; +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + update_current_yaw_setpoint(); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR _navigator->set_position_setpoint_triplet_updated(); } @@ -352,6 +422,7 @@ PrecLand::switch_to_state_start() if (check_state_conditions(PrecLandState::Start)) { position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet(); pos_sp_triplet->current.type = position_setpoint_s::SETPOINT_TYPE_POSITION; + clear_current_yaw_setpoint(); _navigator->set_position_setpoint_triplet_updated(); _search_cnt++; @@ -400,6 +471,8 @@ PrecLand::switch_to_state_final_approach() { if (check_state_conditions(PrecLandState::FinalApproach)) { print_state_switch_message("final approach"); + clear_current_yaw_setpoint(); + _navigator->set_position_setpoint_triplet_updated(); _state = PrecLandState::FinalApproach; _state_start_time = hrt_absolute_time(); return true; @@ -415,6 +488,7 @@ PrecLand::switch_to_state_search() position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet(); pos_sp_triplet->current.alt = _navigator->get_home_position()->alt + _param_pld_srch_alt.get(); pos_sp_triplet->current.type = position_setpoint_s::SETPOINT_TYPE_POSITION; + clear_current_yaw_setpoint(); _navigator->set_position_setpoint_triplet_updated(); _target_acquired_time = 0; @@ -433,6 +507,7 @@ PrecLand::switch_to_state_fallback() pos_sp_triplet->current.lon = _navigator->get_global_position()->lon; pos_sp_triplet->current.alt = _navigator->get_global_position()->alt; pos_sp_triplet->current.type = position_setpoint_s::SETPOINT_TYPE_LAND; + clear_current_yaw_setpoint(); _navigator->set_position_setpoint_triplet_updated(); _state = PrecLandState::Fallback; @@ -443,6 +518,8 @@ PrecLand::switch_to_state_fallback() bool PrecLand::switch_to_state_done() { + clear_current_yaw_setpoint(); + _navigator->set_position_setpoint_triplet_updated(); _state = PrecLandState::Done; _state_start_time = hrt_absolute_time(); return true; @@ -453,6 +530,47 @@ void PrecLand::print_state_switch_message(const char *state_name) PX4_INFO("Precland: switching to %s", state_name); } +matrix::Vector2f PrecLand::get_target_position_setpoint() +{ + matrix::Vector2f target_position_sp(_target_pose.x_abs, _target_pose.y_abs); + +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +# if defined(CONFIG_VTEST_MOVING) + vehicle_local_position_s *vehicle_local_position = _navigator->get_local_position(); + + if (_target_pose.is_static || !_target_pose.rel_vel_valid || !vehicle_local_position->v_xy_valid) { + return target_position_sp; + } + + const matrix::Vector2f target_rel_velocity(_target_pose.vx_rel, _target_pose.vy_rel); + const matrix::Vector2f vehicle_velocity(vehicle_local_position->vx, vehicle_local_position->vy); + + if (!PX4_ISFINITE(_target_pose.z_rel) || !target_rel_velocity.isAllFinite() || !vehicle_velocity.isAllFinite()) { + return target_position_sp; + } + + float mpc_z_v_auto_dn = _param_z_v_auto_dn; + static constexpr float kMinAbsMpcZVAutoDnMps = 1e-3f; + + if (fabsf(mpc_z_v_auto_dn) < kMinAbsMpcZVAutoDnMps) { + mpc_z_v_auto_dn = (mpc_z_v_auto_dn >= 0.f) ? kMinAbsMpcZVAutoDnMps : -kMinAbsMpcZVAutoDnMps; + } + + // Reconstruct the absolute target velocity in the local NED frame from the relative + // velocity published by the VTE and the EKF2 vehicle velocity. + const matrix::Vector2f target_velocity = target_rel_velocity + vehicle_velocity; + const float min_prediction_time = math::min(_param_pld_moving_t_min.get(), _param_pld_moving_t_max.get()); + const float max_prediction_time = math::max(_param_pld_moving_t_min.get(), _param_pld_moving_t_max.get()); + float intersection_time_s = fabsf(_target_pose.z_rel / mpc_z_v_auto_dn); + intersection_time_s = math::constrain(intersection_time_s, min_prediction_time, max_prediction_time); + + target_position_sp += target_velocity * intersection_time_s; +# endif // CONFIG_VTEST_MOVING +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + + return target_position_sp; +} + bool PrecLand::check_state_conditions(PrecLandState state) { vehicle_local_position_s *vehicle_local_position = _navigator->get_local_position(); @@ -465,8 +583,10 @@ bool PrecLand::check_state_conditions(PrecLandState state) // if we're already in this state, only want to make it invalid if we reached the target but can't see it anymore if (_state == PrecLandState::HorizontalApproach) { - if (fabsf(_target_pose.x_abs - vehicle_local_position->x) < _param_pld_hacc_rad.get() - && fabsf(_target_pose.y_abs - vehicle_local_position->y) < _param_pld_hacc_rad.get()) { + const matrix::Vector2f target_position_sp = get_target_position_setpoint(); + + if (fabsf(target_position_sp(0) - vehicle_local_position->x) < _param_pld_hacc_rad.get() + && fabsf(target_position_sp(1) - vehicle_local_position->y) < _param_pld_hacc_rad.get()) { // we've reached the position where we last saw the target. If we don't see it now, we need to do something return _target_pose_valid && _target_pose.abs_pos_valid; @@ -494,9 +614,10 @@ bool PrecLand::check_state_conditions(PrecLandState state) } else { // if not already in this state, need to be above target to enter it + const matrix::Vector2f target_position_sp = get_target_position_setpoint(); return _target_pose_updated && _target_pose.abs_pos_valid - && fabsf(_target_pose.x_abs - vehicle_local_position->x) < _param_pld_hacc_rad.get() - && fabsf(_target_pose.y_abs - vehicle_local_position->y) < _param_pld_hacc_rad.get(); + && fabsf(target_position_sp(0) - vehicle_local_position->x) < _param_pld_hacc_rad.get() + && fabsf(target_position_sp(1) - vehicle_local_position->y) < _param_pld_hacc_rad.get(); } case PrecLandState::FinalApproach: @@ -575,3 +696,54 @@ void PrecLand::slewrate(float &sp_x, float &sp_y) sp_x = sp_curr(0); sp_y = sp_curr(1); } + +void PrecLand::clear_current_yaw_setpoint() +{ + position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet(); + pos_sp_triplet->current.yaw = NAN; +} + +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +void PrecLand::update_current_yaw_setpoint() +{ + position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet(); + pos_sp_triplet->current.yaw = (_param_pld_yaw_en.get() && _target_yaw_valid) ? _target_yaw : NAN; +} + +void PrecLand::reset_target_yaw_state() +{ + _target_yaw = 0.f; + _target_yaw_valid = false; + _last_target_yaw_update = 0; +} + +uint8_t PrecLand::map_prec_land_state(PrecLandState state) +{ + switch (state) { + case PrecLandState::Start: return prec_land_status_s::PREC_LAND_STATE_START; + + case PrecLandState::HorizontalApproach: return prec_land_status_s::PREC_LAND_STATE_HORIZONTAL; + + case PrecLandState::DescendAboveTarget: return prec_land_status_s::PREC_LAND_STATE_DESCEND; + + case PrecLandState::FinalApproach: return prec_land_status_s::PREC_LAND_STATE_FINAL; + + case PrecLandState::Search: return prec_land_status_s::PREC_LAND_STATE_SEARCH; + + case PrecLandState::Fallback: return prec_land_status_s::PREC_LAND_STATE_FALLBACK; + + case PrecLandState::Done: return prec_land_status_s::PREC_LAND_STATE_DONE; + } + + return prec_land_status_s::PREC_LAND_STATE_STOPPED; +} + +void PrecLand::publish_prec_land_status(uint8_t state) +{ + prec_land_status_s prec_land_status{}; + prec_land_status.timestamp = hrt_absolute_time(); + prec_land_status.state = state; + _prec_land_status_pub.publish(prec_land_status); +} + +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR diff --git a/src/modules/navigator/precland.h b/src/modules/navigator/precland.h index df07ff7bd5f..b148a081836 100644 --- a/src/modules/navigator/precland.h +++ b/src/modules/navigator/precland.h @@ -46,6 +46,11 @@ #include #include +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +#include +#include +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + #include "navigator_mode.h" #include "mission_block.h" @@ -105,11 +110,40 @@ private: // check if a given state could be changed into. Return true if possible to transition to state, false otherwise bool check_state_conditions(PrecLandState state); + + /** + * Compute the horizontal landing-target position setpoint in the local NED frame. + * + * For a static target, returns the latest absolute target position. + * For a moving target (only when the vision target estimator is built with + * CONFIG_VTEST_MOVING and the target velocity is valid), shifts the position forward along + * the estimated absolute target velocity by an intersection time bounded by + * PLD_MOVING_T_MIN / PLD_MOVING_T_MAX, so the vehicle aims at where the target will be at + * touchdown rather than where it was last seen. + */ + matrix::Vector2f get_target_position_setpoint(); void slewrate(float &sp_x, float &sp_y); + void clear_current_yaw_setpoint(); + +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + void update_current_yaw_setpoint(); + void reset_target_yaw_state(); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR landing_target_pose_s _target_pose{}; /**< precision landing target position */ uORB::Subscription _target_pose_sub{ORB_ID(landing_target_pose)}; + +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + uORB::Subscription _target_orientation_sub {ORB_ID(vte_orientation)}; + float _target_yaw{0.f}; + bool _target_yaw_valid{false}; + hrt_abstime _last_target_yaw_update{0}; + uORB::Publication _prec_land_status_pub {ORB_ID(prec_land_status)}; + void publish_prec_land_status(uint8_t state); + static uint8_t map_prec_land_state(PrecLandState state); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + bool _target_pose_valid{false}; /**< whether we have received a landing target position message */ bool _target_pose_updated{false}; /**< wether the landing target position message is updated */ @@ -133,6 +167,13 @@ private: bool _is_activated {false}; /**< indicates if precland is activated */ DEFINE_PARAMETERS( +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + (ParamInt) _param_pld_yaw_en, +# if defined(CONFIG_VTEST_MOVING) + (ParamFloat) _param_pld_moving_t_max, + (ParamFloat) _param_pld_moving_t_min, +# endif // CONFIG_VTEST_MOVING +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR (ParamFloat) _param_pld_btout, (ParamFloat) _param_pld_hacc_rad, (ParamFloat) _param_pld_fappr_alt, @@ -147,4 +188,11 @@ private: float _param_acceleration_hor{0.0f}; float _param_xy_vel_cruise{0.0f}; +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +# if defined(CONFIG_VTEST_MOVING) + param_t _handle_param_z_v_auto_dn {PARAM_INVALID}; + float _param_z_v_auto_dn{0.0f}; +# endif // CONFIG_VTEST_MOVING +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + }; diff --git a/src/modules/navigator/precland_params.yaml b/src/modules/navigator/precland_params.yaml index 979123c4dc3..0791c4b8a54 100644 --- a/src/modules/navigator/precland_params.yaml +++ b/src/modules/navigator/precland_params.yaml @@ -25,6 +25,30 @@ parameters: max: 10 decimal: 2 increment: 0.1 + PLD_MOVING_T_MAX: + description: + short: Maximum moving-target prediction time + long: |- + When the landing target is moving, precision land aims at the estimated future + target position after a constrained prediction time. This sets the maximum time. + type: float + default: 3.0 + min: 0.1 + max: 60 + unit: s + decimal: 2 + PLD_MOVING_T_MIN: + description: + short: Minimum moving-target prediction time + long: |- + When the landing target is moving, precision land aims at the estimated future + target position after a constrained prediction time. This sets the minimum time. + type: float + default: 2.0 + min: 0.1 + max: 30 + unit: s + decimal: 2 PLD_FAPPR_ALT: description: short: Final approach altitude @@ -70,3 +94,11 @@ parameters: default: 3 min: 0 max: 100 + PLD_YAW_EN: + description: + short: Set to true to control yaw while landing. + long: Control the orientation when landing. The orientation comes from the topic vte_orientation. + type: boolean + default: 0 + min: 0 + max: 1 diff --git a/src/modules/simulation/simulator_mavlink/SimulatorMavlink.cpp b/src/modules/simulation/simulator_mavlink/SimulatorMavlink.cpp index 5a603af33c6..ffb4d05d0ea 100644 --- a/src/modules/simulation/simulator_mavlink/SimulatorMavlink.cpp +++ b/src/modules/simulation/simulator_mavlink/SimulatorMavlink.cpp @@ -97,6 +97,12 @@ SimulatorMavlink::SimulatorMavlink() : } _esc_status_pub.advertise(); +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + _fiducial_marker_pos_report_pub.advertise(); + _fiducial_marker_yaw_report_pub.advertise(); + _target_gnss_pub.advertise(); + _param_vte_en = param_find("VTE_EN"); +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR } void SimulatorMavlink::parameters_update(bool force) @@ -382,6 +388,22 @@ void SimulatorMavlink::handle_message(const mavlink_message_t *msg) handle_message_landing_target(msg); break; +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +#if defined(MAVLINK_MSG_ID_TARGET_RELATIVE) + + case MAVLINK_MSG_ID_TARGET_RELATIVE: + handle_message_target_relative(msg); + break; +#endif // MAVLINK_MSG_ID_TARGET_RELATIVE + +#if defined(MAVLINK_MSG_ID_TARGET_ABSOLUTE) + + case MAVLINK_MSG_ID_TARGET_ABSOLUTE: + handle_message_target_absolute(msg); + break; +#endif // MAVLINK_MSG_ID_TARGET_ABSOLUTE +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + case MAVLINK_MSG_ID_HIL_STATE_QUATERNION: handle_message_hil_state_quaternion(msg); break; @@ -664,6 +686,231 @@ void SimulatorMavlink::handle_message_landing_target(const mavlink_message_t *ms } } + +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + +#if defined(MAVLINK_MSG_ID_TARGET_ABSOLUTE) +void +SimulatorMavlink::handle_message_target_absolute(const mavlink_message_t *msg) +{ + mavlink_target_absolute_t target_absolute; + mavlink_msg_target_absolute_decode(msg, &target_absolute); + + target_gnss_s target_GNSS_report{}; + target_GNSS_report.timestamp = hrt_absolute_time(); + target_GNSS_report.timestamp_sample = target_absolute.timestamp; + + bool updated = false; + + // Position: bit 0 + if (!(target_absolute.sensor_capabilities & static_cast(TargetAbsoluteSensorCapability::kPosition))) { + target_GNSS_report.abs_pos_updated = false; + + } else { + target_GNSS_report.abs_pos_updated = true; + target_GNSS_report.latitude_deg = target_absolute.lat * 1e-7; + target_GNSS_report.longitude_deg = target_absolute.lon * 1e-7; + target_GNSS_report.altitude_msl_m = target_absolute.alt; + target_GNSS_report.eph = target_absolute.position_std[0]; + target_GNSS_report.epv = target_absolute.position_std[1]; + updated = true; + } + + // Velocity: bit 1 + if (!(target_absolute.sensor_capabilities & static_cast(TargetAbsoluteSensorCapability::kVelocity))) { + target_GNSS_report.vel_ned_updated = false; + + } else { + const matrix::Quatf q_target(target_absolute.q_target); + const bool target_attitude_available = (fabsf(q_target(0)) + fabsf(q_target(1)) + fabsf(q_target(2)) + + fabsf(q_target(3))) > FLT_EPSILON; + + if (target_attitude_available) { + const matrix::Vector3f vel_target_body(target_absolute.vel[0], target_absolute.vel[1], target_absolute.vel[2]); + const matrix::Vector3f vel_target_ned = q_target.rotateVector(vel_target_body); + + target_GNSS_report.vel_ned_updated = true; + target_GNSS_report.vel_n_m_s = vel_target_ned(0); + target_GNSS_report.vel_e_m_s = vel_target_ned(1); + target_GNSS_report.vel_d_m_s = vel_target_ned(2); + target_GNSS_report.s_acc_m_s = fmaxf(fabsf(target_absolute.vel_std[0]), + fmaxf(fabsf(target_absolute.vel_std[1]), + fabsf(target_absolute.vel_std[2]))); + updated = true; + + } else { + target_GNSS_report.vel_ned_updated = false; + } + } + + if (updated) { _target_gnss_pub.publish(target_GNSS_report); } +} +#endif // MAVLINK_MSG_ID_TARGET_ABSOLUTE + + +#if defined(MAVLINK_MSG_ID_TARGET_RELATIVE) +void SimulatorMavlink::handle_message_target_relative(const mavlink_message_t *msg) +{ + mavlink_target_relative_t target_relative; + mavlink_msg_target_relative_decode(msg, &target_relative); + + vehicle_attitude_s vehicle_attitude; + vehicle_local_position_s vehicle_local_position; + + // Unsupported sensor frame + if (target_relative.frame != TARGET_OBS_FRAME_LOCAL_OFFSET_NED && target_relative.frame != TARGET_OBS_FRAME_LOCAL_NED && + target_relative.frame != TARGET_OBS_FRAME_BODY_FRD && target_relative.frame != TARGET_OBS_FRAME_OTHER) { + PX4_WARN("target relative: coordinate frame %d unsupported", (int)target_relative.frame); + return; + } + + // Unsupported measurement type + if (target_relative.type != LANDING_TARGET_TYPE_VISION_FIDUCIAL) { + PX4_WARN("target relative: unsupported type %d", (int)target_relative.type); + return; + } + + matrix::Quatf q_sensor(target_relative.q_sensor); + bool attitude_available = (fabsf(q_sensor(0)) + fabsf(q_sensor(1)) + fabsf(q_sensor(2)) + + fabsf(q_sensor(3))) > FLT_EPSILON; + + // Check if attitude can be infered based on the frame + if (!attitude_available) { + if (target_relative.frame == TARGET_OBS_FRAME_LOCAL_OFFSET_NED || target_relative.frame == TARGET_OBS_FRAME_LOCAL_NED) { + // Observation already in NED, set quaternion to identity (1,0,0,0) + q_sensor.setIdentity(); + attitude_available = true; + + } else if (target_relative.frame == TARGET_OBS_FRAME_BODY_FRD && _vehicle_attitude_sub.copy(&vehicle_attitude)) { + // Set the quaternion to the current attitude + const matrix::Quaternionf quat_att(&vehicle_attitude.q[0]); + q_sensor = quat_att; + attitude_available = true; + + } else if (target_relative.frame == TARGET_OBS_FRAME_OTHER) { + // Target sensor frame: OTHER and no quaternion is provided + PX4_WARN("target relative: coordinate frame %d unsupported when the q_sensor is not filled", + (int)target_relative.frame); + } + } + + // Target cannot be sent without valid attitude + if (!attitude_available) { + return; + } + + // Forward target to the vision target estimator (VTE) or precland based VTE_EN + int32_t vte_enabled = 0; + + if (_param_vte_en == PARAM_INVALID) { + if (hrt_elapsed_time(&_vte_en_invalid_warn_last) > 20_s) { + PX4_WARN(" Could not find VTE_EN, target_relative msg ignored."); + _vte_en_invalid_warn_last = hrt_absolute_time(); + } + + return; + + } else { + param_get(_param_vte_en, &vte_enabled); + } + + if (!vte_enabled) { + + // Send the target directly to the precision landing algorithm in local NED frame + landing_target_pose_s landing_target_pose{}; + landing_target_pose.timestamp = target_relative.timestamp; + + // Measurement already in local NED + if (target_relative.frame == TARGET_OBS_FRAME_LOCAL_NED) { + + landing_target_pose.x_abs = target_relative.x; + landing_target_pose.y_abs = target_relative.y; + landing_target_pose.z_abs = target_relative.z; + landing_target_pose.abs_pos_valid = true; + + _landing_target_pose_pub.publish(landing_target_pose); + + } else if (_vehicle_local_position_sub.copy(&vehicle_local_position) + && vehicle_local_position.xy_valid && vehicle_local_position.z_valid) { + + // If the local position is available, convert from sensor frame to local NED + matrix::Vector3f target_relative_frame(target_relative.x, target_relative.y, target_relative.z); + + if (target_relative.frame == TARGET_OBS_FRAME_BODY_FRD || target_relative.frame == TARGET_OBS_FRAME_OTHER) { + // Rotate measurement into vehicle-carried NED + target_relative_frame = q_sensor.rotateVector(target_relative_frame); + } + + // Convert from vehicle-carried NED to local NED + landing_target_pose.x_abs = target_relative_frame(0) + vehicle_local_position.x; + landing_target_pose.y_abs = target_relative_frame(1) + vehicle_local_position.y; + landing_target_pose.z_abs = target_relative_frame(2) + vehicle_local_position.z; + landing_target_pose.abs_pos_valid = true; + + _landing_target_pose_pub.publish(landing_target_pose); + } + + } else { + + // Only supported type: LANDING_TARGET_TYPE_VISION_FIDUCIAL + + // Position report + fiducial_marker_pos_report_s fiducial_marker_pos_report{}; + + const hrt_abstime now = hrt_absolute_time(); + const hrt_abstime timestamp_sample = target_relative.timestamp; + + fiducial_marker_pos_report.timestamp = now; + fiducial_marker_pos_report.timestamp_sample = timestamp_sample; + matrix::Vector3f target_relative_frame(target_relative.x, target_relative.y, target_relative.z); + + // TARGET_OBS_FRAME_LOCAL_NED is absolute in local frame: convert to vehicle-relative. + if (target_relative.frame == TARGET_OBS_FRAME_LOCAL_NED) { + if (!_vehicle_local_position_sub.copy(&vehicle_local_position) + || !vehicle_local_position.xy_valid || !vehicle_local_position.z_valid) { + return; + } + + target_relative_frame(0) -= vehicle_local_position.x; + target_relative_frame(1) -= vehicle_local_position.y; + target_relative_frame(2) -= vehicle_local_position.z; + } + + fiducial_marker_pos_report.rel_pos[0] = target_relative_frame(0); + fiducial_marker_pos_report.rel_pos[1] = target_relative_frame(1); + fiducial_marker_pos_report.rel_pos[2] = target_relative_frame(2); + + fiducial_marker_pos_report.cov_rel_pos[0] = target_relative.pos_std[0] * target_relative.pos_std[0]; + fiducial_marker_pos_report.cov_rel_pos[1] = target_relative.pos_std[1] * target_relative.pos_std[1]; + fiducial_marker_pos_report.cov_rel_pos[2] = target_relative.pos_std[2] * target_relative.pos_std[2]; + + q_sensor.copyTo(fiducial_marker_pos_report.q); + _fiducial_marker_pos_report_pub.publish(fiducial_marker_pos_report); + + const matrix::Quatf q_target(target_relative.q_target); + const bool target_attitude_available = (fabsf(q_target(0)) + fabsf(q_target(1)) + fabsf(q_target(2)) + + fabsf(q_target(3))) > FLT_EPSILON; + + if (target_attitude_available) { + // Yaw report + fiducial_marker_yaw_report_s fiducial_marker_yaw_report{}; + fiducial_marker_yaw_report.timestamp = now; + fiducial_marker_yaw_report.timestamp_sample = timestamp_sample; + + // Transform quaternion from the target's frame to the TARGET_OBS_FRAME to the yaw relative to NED + const matrix::Quatf q_in_ned = q_sensor * q_target; + const float target_yaw_ned = matrix::Eulerf(q_in_ned).psi(); + + fiducial_marker_yaw_report.yaw_ned = target_yaw_ned; + fiducial_marker_yaw_report.yaw_var_ned = target_relative.yaw_std * target_relative.yaw_std; + _fiducial_marker_yaw_report_pub.publish(fiducial_marker_yaw_report); + } + } + +} +#endif // MAVLINK_MSG_ID_TARGET_RELATIVE +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + void SimulatorMavlink::handle_message_odometry(const mavlink_message_t *msg) { mavlink_odometry_t odom_in; diff --git a/src/modules/simulation/simulator_mavlink/SimulatorMavlink.hpp b/src/modules/simulation/simulator_mavlink/SimulatorMavlink.hpp index 5c1e9481e8a..605b68ffbb2 100644 --- a/src/modules/simulation/simulator_mavlink/SimulatorMavlink.hpp +++ b/src/modules/simulation/simulator_mavlink/SimulatorMavlink.hpp @@ -63,6 +63,12 @@ #include #include #include +#include +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +#include +#include +#include +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR #include #include #include @@ -113,6 +119,16 @@ static inline SensorSource operator &(A lhs, B rhs) ); } +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +enum class TargetAbsoluteSensorCapability : uint8_t { + kPosition = (1 << 0), + kVelocity = (1 << 1), + kAcceleration = (1 << 2), + kAttitude = (1 << 3), + kRates = (1 << 4), +}; +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR + class SimulatorMavlink : public ModuleParams { public: @@ -226,6 +242,8 @@ private: void handle_message_hil_sensor(const mavlink_message_t *msg); void handle_message_hil_state_quaternion(const mavlink_message_t *msg); void handle_message_landing_target(const mavlink_message_t *msg); + void handle_message_target_relative(const mavlink_message_t *msg); + void handle_message_target_absolute(const mavlink_message_t *msg); void handle_message_odometry(const mavlink_message_t *msg); void handle_message_optical_flow(const mavlink_message_t *msg); void handle_message_rc_channels(const mavlink_message_t *msg); @@ -251,6 +269,14 @@ private: uORB::Publication _gpos_ground_truth_pub{ORB_ID(vehicle_global_position_groundtruth)}; uORB::Publication _lpos_ground_truth_pub{ORB_ID(vehicle_local_position_groundtruth)}; uORB::Publication _input_rc_pub{ORB_ID(input_rc)}; + uORB::Publication _landing_target_pose_pub{ORB_ID(landing_target_pose)}; +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR + uORB::Publication _fiducial_marker_pos_report_pub {ORB_ID(fiducial_marker_pos_report)}; + uORB::Publication _fiducial_marker_yaw_report_pub{ORB_ID(fiducial_marker_yaw_report)}; + uORB::Publication _target_gnss_pub{ORB_ID(target_gnss)}; + param_t _param_vte_en{PARAM_INVALID}; + hrt_abstime _vte_en_invalid_warn_last{0}; +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR //rpm uORB::Publication _rpm_pub{ORB_ID(rpm)}; @@ -268,6 +294,8 @@ private: uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)}; uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)}; uORB::Subscription _battery_status_sub{ORB_ID(battery_status)}; + uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)}; + uORB::Subscription _vehicle_local_position_sub{ORB_ID(vehicle_local_position)}; // hil map_ref data MapProjection _global_local_proj_ref{}; diff --git a/src/modules/vision_target_estimator/CMakeLists.txt b/src/modules/vision_target_estimator/CMakeLists.txt new file mode 100644 index 00000000000..ae56eec79ca --- /dev/null +++ b/src/modules/vision_target_estimator/CMakeLists.txt @@ -0,0 +1,307 @@ +############################################################################ +# +# Copyright (c) 2026 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Vision Target Estimator (VTEST) Symforce code generation +# +option(VTEST_SYMFORCE_GEN "vtest generate symforce output" OFF) +option(VTEST_UPDATE_COMMITTED_DERIVATION "Rewrite committed default generated files" OFF) + +function(vtest_generated_files_in_dir out_var base_dir) + set(files) + + foreach(file_name ${ARGN}) + list(APPEND files ${base_dir}/${file_name}) + endforeach() + + set(${out_var} "${files}" PARENT_SCOPE) +endfunction() + +# Check if symforce is available +execute_process( + COMMAND ${PYTHON_EXECUTABLE} -m symforce.symbolic + RESULT_VARIABLE PYTHON_SYMFORCE_EXIT_CODE + OUTPUT_QUIET + ERROR_QUIET +) + +# Enable symforce generation if a non-default configuration is used +if(CONFIG_VTEST_MOVING) + set(VTEST_SYMFORCE_GEN ON) +endif() + +if(VTEST_SYMFORCE_GEN AND NOT (${PYTHON_SYMFORCE_EXIT_CODE} EQUAL 0)) + message(WARNING "VTEST_SYMFORCE_GEN requested, but SymForce is not available. Using committed pre-generated VTE headers.") +endif() + +# Set up paths and default variables +set(VTEST_DERIVATION_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Position/vtest_derivation) +set(VTEST_PREGENERATED_STATIC_DIR ${VTEST_DERIVATION_SRC_DIR}/generated) +set(VTEST_PREGENERATED_MOVING_DIR ${VTEST_DERIVATION_SRC_DIR}/generated_moving) +set(VTEST_POSITION_GENERATED_HEADERS + state.h + predictCov.h + computeInnovCov.h + predictState.h + getTransitionMatrix.h + applyCorrection.h +) + +vtest_generated_files_in_dir(VTEST_PREGENERATED_STATIC_FILES + ${VTEST_PREGENERATED_STATIC_DIR} + ${VTEST_POSITION_GENERATED_HEADERS} +) +vtest_generated_files_in_dir(VTEST_PREGENERATED_MOVING_FILES + ${VTEST_PREGENERATED_MOVING_DIR} + ${VTEST_POSITION_GENERATED_HEADERS} +) + +set(VTEST_DERIVATION_DST_DIR ${CMAKE_CURRENT_BINARY_DIR}/vtest_derivation) +file(MAKE_DIRECTORY ${VTEST_DERIVATION_DST_DIR}) +vtest_generated_files_in_dir(VTEST_GENERATED_FILE_LIST_DST + ${VTEST_DERIVATION_DST_DIR}/generated + ${VTEST_POSITION_GENERATED_HEADERS} +) + +# Use one file as the dependency anchor. The custom_command OUTPUT will ensure all are generated. +set(VTEST_GENERATED_FILES ${VTEST_DERIVATION_DST_DIR}/generated/state.h) +set(VTEST_GENERATED_DERIVATION_INCLUDE_PATH ${CMAKE_CURRENT_BINARY_DIR}) + +set(VTEST_ORIENTATION_DERIVATION_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Orientation/vtest_derivation) +set(VTEST_ORIENTATION_PREGENERATED_DIR ${VTEST_ORIENTATION_DERIVATION_SRC_DIR}/generated) +set(VTEST_ORIENTATION_GENERATED_HEADERS + predictState.h + getTransitionMatrix.h + predictCov.h +) +vtest_generated_files_in_dir(VTEST_ORIENTATION_PREGENERATED_FILES + ${VTEST_ORIENTATION_PREGENERATED_DIR} + ${VTEST_ORIENTATION_GENERATED_HEADERS} +) +set(VTEST_ORIENTATION_DERIVATION_DST_DIR ${CMAKE_CURRENT_BINARY_DIR}/vte_orientation_derivation) +file(MAKE_DIRECTORY ${VTEST_ORIENTATION_DERIVATION_DST_DIR}) +vtest_generated_files_in_dir(VTEST_ORIENTATION_GENERATED_FILE_LIST_DST + ${VTEST_ORIENTATION_DERIVATION_DST_DIR}/generated + ${VTEST_ORIENTATION_GENERATED_HEADERS} +) +set(VTEST_ORIENTATION_GENERATED_FILES ${VTEST_ORIENTATION_DERIVATION_DST_DIR}/generated/predictCov.h) + +set(VTEST_GENERATED_TARGET "") + +if(VTEST_SYMFORCE_GEN AND (${PYTHON_SYMFORCE_EXIT_CODE} EQUAL 0)) + + set(VTEST_SYMFORCE_TARGET_DEPS) + + # Regenerate committed defaults when requested. + if(VTEST_UPDATE_COMMITTED_DERIVATION) + add_custom_command( + OUTPUT + ${VTEST_PREGENERATED_STATIC_FILES} + COMMAND + ${PYTHON_EXECUTABLE} ${VTEST_DERIVATION_SRC_DIR}/derivation.py + DEPENDS + ${VTEST_DERIVATION_SRC_DIR}/derivation.py + ${VTEST_DERIVATION_SRC_DIR}/utils/derivation_utils.py + + WORKING_DIRECTORY ${VTEST_DERIVATION_SRC_DIR} + COMMENT "VTEST Symforce code generation (default, committed)" + USES_TERMINAL + ) + list(APPEND VTEST_SYMFORCE_TARGET_DEPS ${VTEST_PREGENERATED_STATIC_FILES}) + + if(CONFIG_VTEST_MOVING) + set(VTEST_DERIVATION_MOVING_TMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/vtest_derivation_committed_moving) + file(MAKE_DIRECTORY ${VTEST_DERIVATION_MOVING_TMP_DIR}) + + add_custom_command( + OUTPUT + ${VTEST_PREGENERATED_MOVING_FILES} + COMMAND + ${CMAKE_COMMAND} -E remove_directory ${VTEST_DERIVATION_MOVING_TMP_DIR}/generated + COMMAND + ${PYTHON_EXECUTABLE} ${VTEST_DERIVATION_SRC_DIR}/derivation.py --moving + COMMAND + ${CMAKE_COMMAND} -E remove_directory ${VTEST_PREGENERATED_MOVING_DIR} + COMMAND + ${CMAKE_COMMAND} -E make_directory ${VTEST_PREGENERATED_MOVING_DIR} + COMMAND + ${CMAKE_COMMAND} -E copy_directory ${VTEST_DERIVATION_MOVING_TMP_DIR}/generated ${VTEST_PREGENERATED_MOVING_DIR} + DEPENDS + ${VTEST_DERIVATION_SRC_DIR}/derivation.py + ${VTEST_DERIVATION_SRC_DIR}/utils/derivation_utils.py + WORKING_DIRECTORY ${VTEST_DERIVATION_MOVING_TMP_DIR} + COMMENT "VTEST Symforce code generation (moving, committed)" + USES_TERMINAL + ) + list(APPEND VTEST_SYMFORCE_TARGET_DEPS ${VTEST_PREGENERATED_MOVING_FILES}) + endif() + + add_custom_command( + OUTPUT + ${VTEST_ORIENTATION_PREGENERATED_FILES} + COMMAND + ${PYTHON_EXECUTABLE} ${VTEST_ORIENTATION_DERIVATION_SRC_DIR}/derivation.py + DEPENDS + ${VTEST_ORIENTATION_DERIVATION_SRC_DIR}/derivation.py + WORKING_DIRECTORY ${VTEST_ORIENTATION_DERIVATION_SRC_DIR} + COMMENT "VTEST orientation Symforce code generation (committed)" + USES_TERMINAL + ) + list(APPEND VTEST_SYMFORCE_TARGET_DEPS ${VTEST_ORIENTATION_PREGENERATED_FILES}) + endif() + + set(SYMFORCE_ARGS) + if(CONFIG_VTEST_MOVING) + message(STATUS "vtest: symforce --moving") + list(APPEND SYMFORCE_ARGS --moving) + endif() + + add_custom_command( + OUTPUT + ${VTEST_GENERATED_FILE_LIST_DST} + COMMAND + ${PYTHON_EXECUTABLE} ${VTEST_DERIVATION_SRC_DIR}/derivation.py ${SYMFORCE_ARGS} + DEPENDS + ${VTEST_DERIVATION_SRC_DIR}/derivation.py + ${VTEST_DERIVATION_SRC_DIR}/utils/derivation_utils.py + + WORKING_DIRECTORY ${VTEST_DERIVATION_DST_DIR} + COMMENT "VTEST Symforce code generation" + USES_TERMINAL + ) + list(APPEND VTEST_SYMFORCE_TARGET_DEPS ${VTEST_GENERATED_FILE_LIST_DST}) + + add_custom_command( + OUTPUT + ${VTEST_ORIENTATION_GENERATED_FILE_LIST_DST} + COMMAND + ${PYTHON_EXECUTABLE} ${VTEST_ORIENTATION_DERIVATION_SRC_DIR}/derivation.py + DEPENDS + ${VTEST_ORIENTATION_DERIVATION_SRC_DIR}/derivation.py + WORKING_DIRECTORY ${VTEST_ORIENTATION_DERIVATION_DST_DIR} + COMMENT "VTEST orientation Symforce code generation" + USES_TERMINAL + ) + list(APPEND VTEST_SYMFORCE_TARGET_DEPS ${VTEST_ORIENTATION_GENERATED_FILE_LIST_DST}) + + add_custom_target(vtest_symforce_generate + DEPENDS ${VTEST_SYMFORCE_TARGET_DEPS} + ) + set(VTEST_GENERATED_TARGET vtest_symforce_generate) + +else() + if(CONFIG_VTEST_MOVING) + set(VTEST_PREGENERATED_SOURCE_DIR ${VTEST_PREGENERATED_MOVING_DIR}) + set(VTEST_PREGENERATED_SOURCE_FILES ${VTEST_PREGENERATED_MOVING_FILES}) + set(VTEST_PREGENERATED_CONFIG moving) + else() + set(VTEST_PREGENERATED_SOURCE_DIR ${VTEST_PREGENERATED_STATIC_DIR}) + set(VTEST_PREGENERATED_SOURCE_FILES ${VTEST_PREGENERATED_STATIC_FILES}) + set(VTEST_PREGENERATED_CONFIG static) + endif() + + add_custom_command( + OUTPUT + ${VTEST_GENERATED_FILE_LIST_DST} + COMMAND + ${CMAKE_COMMAND} -E remove_directory ${VTEST_DERIVATION_DST_DIR}/generated + COMMAND + ${CMAKE_COMMAND} -E make_directory ${VTEST_DERIVATION_DST_DIR}/generated + COMMAND + ${CMAKE_COMMAND} -E copy_directory ${VTEST_PREGENERATED_SOURCE_DIR} ${VTEST_DERIVATION_DST_DIR}/generated + DEPENDS + ${VTEST_PREGENERATED_SOURCE_FILES} + COMMENT "VTEST using pre-generated symforce outputs (${VTEST_PREGENERATED_CONFIG})" + ) + + add_custom_command( + OUTPUT + ${VTEST_ORIENTATION_GENERATED_FILE_LIST_DST} + COMMAND + ${CMAKE_COMMAND} -E remove_directory ${VTEST_ORIENTATION_DERIVATION_DST_DIR}/generated + COMMAND + ${CMAKE_COMMAND} -E make_directory ${VTEST_ORIENTATION_DERIVATION_DST_DIR}/generated + COMMAND + ${CMAKE_COMMAND} -E copy_directory ${VTEST_ORIENTATION_PREGENERATED_DIR} + ${VTEST_ORIENTATION_DERIVATION_DST_DIR}/generated + DEPENDS + ${VTEST_ORIENTATION_PREGENERATED_FILES} + COMMENT "VTEST orientation using pre-generated symforce outputs" + ) + + add_custom_target(vtest_derivation_prebuilt + DEPENDS ${VTEST_GENERATED_FILE_LIST_DST} ${VTEST_ORIENTATION_GENERATED_FILE_LIST_DST} + ) + set(VTEST_GENERATED_TARGET vtest_derivation_prebuilt) +endif() + +if(VTEST_GENERATED_TARGET) + add_dependencies(prebuild_targets ${VTEST_GENERATED_TARGET}) +endif() + +if(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) + px4_add_module( + MODULE modules__vision_target_estimator + MAIN vision_target_estimator + STACK_MAX + 5000 + SRCS + VisionTargetEst.cpp + tasks/PrecLandTask.cpp + Position/VTEPosition.cpp + Position/KF_position.cpp + Orientation/VTEOrientation.cpp + Orientation/KF_orientation.cpp + + ${VTEST_GENERATED_FILES} + ${VTEST_ORIENTATION_GENERATED_FILES} + MODULE_CONFIG + vision_target_estimator_params.yaml + DEPENDS + mathlib + px4_work_queue + ) + + # Public because module headers expose generated vtest/vte_orientation headers. + target_include_directories(modules__vision_target_estimator BEFORE PUBLIC + ${VTEST_GENERATED_DERIVATION_INCLUDE_PATH} + ) + + if(VTEST_GENERATED_TARGET) + add_dependencies(modules__vision_target_estimator ${VTEST_GENERATED_TARGET}) + endif() +endif() + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/src/modules/vision_target_estimator/Kconfig b/src/modules/vision_target_estimator/Kconfig new file mode 100644 index 00000000000..35007b0c790 --- /dev/null +++ b/src/modules/vision_target_estimator/Kconfig @@ -0,0 +1,24 @@ +menuconfig MODULES_VISION_TARGET_ESTIMATOR + bool "vision_target_estimator" + default n + depends on !BOARD_CONSTRAINED_MEMORY + depends on !BOARD_CONSTRAINED_FLASH + ---help--- + Enable support for vision_target_estimator + +menuconfig USER_VISION_TARGET_ESTIMATOR + bool "vision_target_estimator running as userspace module" + default y + depends on BOARD_PROTECTED && MODULES_VISION_TARGET_ESTIMATOR + ---help--- + Put vision_target_estimator in userspace memory + +menuconfig VTEST_MOVING + depends on MODULES_VISION_TARGET_ESTIMATOR + bool "vtest with moving target" + default n + depends on !BOARD_CONSTRAINED_MEMORY + depends on !BOARD_CONSTRAINED_FLASH + ---help--- + Enable support for estimation of moving targets. + WARNING: Experimental beta version diff --git a/src/modules/vision_target_estimator/Orientation/KF_orientation.cpp b/src/modules/vision_target_estimator/Orientation/KF_orientation.cpp new file mode 100644 index 00000000000..f4a01ffadd7 --- /dev/null +++ b/src/modules/vision_target_estimator/Orientation/KF_orientation.cpp @@ -0,0 +1,145 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file KF_orientation.cpp + * @brief Filter to estimate the orientation of static and moving targets. State: [yaw, yaw_rate] + * + * @author Jonas Perolini + * + */ + +#include "KF_orientation.h" + +#include +#include + +#include +#include +#include +#include + +namespace vision_target_estimator +{ + +using VectorState = KF_orientation::VectorState; +using SquareMatrixState = KF_orientation::SquareMatrixState; + +void KF_orientation::predict(float dt) +{ + if (!PX4_ISFINITE(dt) || (dt < 0.f)) { + return; + } + + VectorState state_next; + SquareMatrixState cov_next; + + predictState(dt, EmptyInput{}, _state, _state_covariance, state_next, cov_next); + + _state = state_next; + _state_covariance = cov_next; +} + +SquareMatrixState KF_orientation::getTransitionMatrix(float dt) const +{ + return sym::Gettransitionmatrix(dt); +} + +void KF_orientation::predictState(float dt, const EmptyInput &input, + const VectorState &x_in, + const SquareMatrixState &P_in, + VectorState &x_out, + SquareMatrixState &P_out) +{ + (void)input; + + x_out = sym::Predictstate(dt, x_in); + x_out(KF_orientation::kYaw) = matrix::wrap_pi(x_out(KF_orientation::kYaw)); + + // Keep invalid values from injecting covariance and use generated covariance propagation. + const float yaw_acc_var = (PX4_ISFINITE(_yaw_acc_var) && (_yaw_acc_var > 0.f)) ? _yaw_acc_var : 0.f; + P_out = sym::Predictcov(dt, yaw_acc_var, P_in); +} + +void KF_orientation::computeInnovation(const VectorState &state, + const SquareMatrixState &cov, + const ScalarMeas &meas, + float &innov, float &innov_var) const +{ + + innov = meas.val - (meas.H.transpose() * state)(0, 0); + innov_var = (meas.H.transpose() * cov * meas.H)(0, 0) + meas.unc; + + // Wrap innovations for yaw measurements + const bool is_yaw_meas = (fabsf(meas.H(KF_orientation::kYaw)) > 0.f) && (fabsf(meas.H(KF_orientation::kYawRate)) < FLT_EPSILON); + + if (is_yaw_meas) { + innov = matrix::wrap_pi(innov); + } +} + +void KF_orientation::pushHistory(const uint64_t time_us) +{ + _oosm.push(time_us, _state, _state_covariance, EmptyInput{}); +} + +void KF_orientation::resetHistory() +{ + _oosm.reset(); +} + +FusionResult KF_orientation::fuseScalarAtTime(const ScalarMeas &meas, uint64_t now_us, float nis_threshold) +{ + return _oosm.fuse(*this, meas, now_us, nis_threshold, _state, _state_covariance, EmptyInput{}); +} + +void KF_orientation::applyCorrection(VectorState &state, + SquareMatrixState &cov, + const VectorState &K, + float innov, float S) +{ + state = state + K * innov; + state(KF_orientation::kYaw) = matrix::wrap_pi(state(KF_orientation::kYaw)); + + for (size_t row = 0; row < KF_orientation::kSize; row++) { + for (size_t col = 0; col < KF_orientation::kSize; col++) { + cov(row, col) -= K(row) * K(col) * S; + } + } + + for (size_t i = 0; i < KF_orientation::kSize; i++) { + cov(i, i) = fmaxf(cov(i, i), kMinVar); + } +} + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/Orientation/KF_orientation.h b/src/modules/vision_target_estimator/Orientation/KF_orientation.h new file mode 100644 index 00000000000..6b3ebb4c0a8 --- /dev/null +++ b/src/modules/vision_target_estimator/Orientation/KF_orientation.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file KF_orientation.h + * @brief Filter to estimate the orientation of static and moving targets. State: [yaw, yaw_rate] + * + * @author Jonas Perolini + * + */ + +#include + +#include + +#pragma once + +#include "../VTEOosm.h" +#include "../common.h" + +namespace vision_target_estimator +{ + +class KF_orientation +{ +public: + enum State : uint8_t { + kYaw = 0, + kYawRate, + kSize + }; + using VectorState = matrix::Vector; + using SquareMatrixState = matrix::SquareMatrix; + + friend class OOSMManager; + + KF_orientation() = default; + ~KF_orientation() = default; + static constexpr float kMinVar = 1e-9f; + + struct ScalarMeas { + uint64_t time_us; + float val; + float unc; + VectorState H; + }; + + void predict(float dt); + + // Primary Fusion Interface (history-consistent OOSM) + // Projected correction OOSM approximation: + // - Most accurate with bounded delays and when fusions are processed in timestamp order (oldest -> newest). + // - Does not replay intermediate measurement updates (unlike EKF2's delayed fusion horizon). + // Returns FusionResult describing the result for logging. + FusionResult fuseScalarAtTime(const ScalarMeas &meas, uint64_t now_us, float nis_threshold); + + // History Management + void pushHistory(const uint64_t time_us); + void resetHistory(); + + // State + void setState(const VectorState &state) { _state = state; } + void setStateCovarianceDiag(const VectorState &var) + { + const SquareMatrixState var_mat = diag(var); + _state_covariance = var_mat; + }; + + const VectorState &getState() const { return _state; } + const SquareMatrixState &getStateCovariance() const { return _state_covariance; } + VectorState getStateCovarianceDiag() const { return _state_covariance.diag(); } + + void setYawAccVar(float var) { _yaw_acc_var = var; } + +private: + SquareMatrixState getTransitionMatrix(float dt) const; + + void predictState(float dt, const EmptyInput &input, + const VectorState &x_in, + const SquareMatrixState &P_in, + VectorState &x_out, + SquareMatrixState &P_out); + + void computeInnovation(const VectorState &state, + const SquareMatrixState &cov, const ScalarMeas &meas, + float &innov, float &innov_var) const; + + void applyCorrection(VectorState &state, + SquareMatrixState &cov, + const VectorState &K, + float innov, float S); + + VectorState _state{}; + SquareMatrixState _state_covariance{}; + + float _yaw_acc_var{0.f}; // white yaw-acceleration noise PSD (rad^2 / s^3, or (rad/s^2)^2 / Hz) + + // OOSM history buffer: + // 0.5 s window @ 50 Hz predict rate = 25 samples. + // Note that the 0.5 s window is enforced with kOosmMaxTimeUs = 500_ms. + OOSMManager _oosm; +}; +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/Orientation/VTEOrientation.cpp b/src/modules/vision_target_estimator/Orientation/VTEOrientation.cpp new file mode 100644 index 00000000000..95ee7150b2c --- /dev/null +++ b/src/modules/vision_target_estimator/Orientation/VTEOrientation.cpp @@ -0,0 +1,304 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VTEOrientation.cpp + * @brief Estimate the orientation of a target by processing and fusing sensor + * data in a Kalman Filter. + * + * @author Jonas Perolini + * + */ + +#include + +#include + +#include "VTEOrientation.h" + + +namespace vision_target_estimator +{ + +using namespace matrix; +using OrientationStateVec = KF_orientation::VectorState; + +VTEOrientation::VTEOrientation() : ModuleParams(nullptr) +{ + _vte_aid_ev_yaw_pub.advertise(); + _target_orientation_pub.advertise(); + + updateParams(); +} + +VTEOrientation::~VTEOrientation() = default; + +bool VTEOrientation::init() +{ + _target_est_yaw.resetHistory(); + return true; +} + +void VTEOrientation::resetFilter() +{ + _estimator_initialized = false; + _target_est_yaw.resetHistory(); +} + +void VTEOrientation::update() +{ + if (_parameter_update_sub.updated()) { + updateParams(); + } + + // Predict the target yaw state using the constant yaw-rate model. + if (_estimator_initialized) { + const hrt_abstime now_us = nowUs(); + + if (now_us < _last_predict) { + resetFilter(); + PX4_WARN("VTE orientation invalid _last_predict time"); + return; + } + + const uint64_t dt_us = now_us - _last_predict; + + // Guard against long scheduling gaps for which the constant yaw-rate assumption breaks down. + static constexpr uint64_t kMaxPredictionDeltaTimeUs = 100_ms; // Filter runs at 50 Hz, expect dt = 20 ms. + + if (dt_us > kMaxPredictionDeltaTimeUs) { + resetFilter(); + PX4_WARN("VTE orientation stale, resetting filter"); + return; + } + + predictionStep(dt_us * kMicrosecondsToSeconds); + _last_predict = now_us; + } + + // Fuse the latest observation and publish innovations. + if (performUpdateStep()) { + _last_update = _last_predict; + } + + if (_estimator_initialized) { + // Store the post-fusion posterior snapshot at the current timestamp for OOSM fusion. + _target_est_yaw.pushHistory(_last_predict); + publishTarget(); + } +} + +void VTEOrientation::initEstimator(const VisionObs &vision_obs) +{ + // Seed from the first valid yaw sample; yaw-rate starts at zero until an observer provides it. + OrientationStateVec state_init{}; + state_init(KF_orientation::kYaw) = vision_obs.yaw; + + OrientationStateVec state_var_init; + state_var_init.setAll(fmaxf(_param_vte_yaw_unc_in.get(), kMinVariance)); + + _target_est_yaw.setState(state_init); + _target_est_yaw.setStateCovarianceDiag(state_var_init); + _target_est_yaw.resetHistory(); + + PX4_DEBUG("VTE Orientation initialized with yaw: %.2f [rad]", (double)vision_obs.yaw); + + _estimator_initialized = true; + _last_update = nowUs(); + _last_predict = _last_update; +} + +void VTEOrientation::predictionStep(float dt) +{ + _target_est_yaw.setYawAccVar(fmaxf(_param_vte_yaw_acc_unc.get(), kMinVariance)); + _target_est_yaw.predict(dt); +} + +bool VTEOrientation::performUpdateStep() +{ + VisionObs vision_obs{}; + + if (!_vte_aid_mask.flags.use_vision_pos || !processObsVision(vision_obs)) { + return false; + } + + if (!_estimator_initialized) { + initEstimator(vision_obs); + } + + return fuseMeas(vision_obs); +} + +bool VTEOrientation::shouldEmitWarning(hrt_abstime &last_warn) +{ + const hrt_abstime now = nowUs(); + + if ((last_warn == 0) || (now < last_warn) || ((now - last_warn) > kWarnThrottleIntervalUs)) { + last_warn = now; + return true; + } + + return false; +} + +bool VTEOrientation::isVisionDataValid(const fiducial_marker_yaw_report_s &fiducial_marker_yaw) +{ + if (!isMeasRecent(fiducial_marker_yaw.timestamp_sample)) { + if (shouldEmitWarning(_vision_warn_last)) { + PX4_WARN("VTE: Vision yaw too old!"); + } + + return false; + } + + if (!PX4_ISFINITE(fiducial_marker_yaw.yaw_ned) || !PX4_ISFINITE(fiducial_marker_yaw.yaw_var_ned)) { + if (shouldEmitWarning(_vision_warn_last)) { + PX4_WARN("VTE: Vision yaw is corrupt!"); + } + + return false; + } + + return true; +} + +bool VTEOrientation::processObsVision(VisionObs &vision_obs) +{ + fiducial_marker_yaw_report_s fiducial_marker_yaw; + + if (!_fiducial_marker_yaw_report_sub.update(&fiducial_marker_yaw) || + !isVisionDataValid(fiducial_marker_yaw)) { + return false; + } + + const float min_ev_angle_var = sq(fmaxf(_param_vte_ev_angle_noise.get(), kMinObservationNoise)); + const float yaw_unc = fmaxf(fiducial_marker_yaw.yaw_var_ned, min_ev_angle_var); + + vision_obs.timestamp = fiducial_marker_yaw.timestamp_sample; + vision_obs.yaw = wrap_pi(fiducial_marker_yaw.yaw_ned); + vision_obs.yaw_var = yaw_unc; + + return true; +} + +bool VTEOrientation::fuseMeas(const VisionObs &vision_obs) +{ + vte_aid_source1d_s target_innov = {}; + const float nis_threshold = fmaxf(_param_vte_yaw_nis_thre.get(), kMinNisThreshold); + + target_innov.timestamp_sample = vision_obs.timestamp; + target_innov.timestamp = nowUs(); + target_innov.time_last_predict = _last_predict; + target_innov.time_since_meas_ms = static_cast(signedTimeDiffUs( + _last_predict, vision_obs.timestamp)) * kMicrosecondsToMilliseconds; + + OrientationStateVec meas_h_theta{}; + meas_h_theta(KF_orientation::kYaw) = 1.f; + + const KF_orientation::ScalarMeas meas_input{ + vision_obs.timestamp, vision_obs.yaw, vision_obs.yaw_var, meas_h_theta}; + + target_innov.observation = meas_input.val; + target_innov.observation_variance = meas_input.unc; + + const FusionResult result = _target_est_yaw.fuseScalarAtTime(meas_input, _last_predict, nis_threshold); + + target_innov.innovation = result.innov; + target_innov.innovation_variance = result.innov_var; + target_innov.test_ratio = result.test_ratio; + target_innov.fusion_status = static_cast(result.status); + target_innov.history_steps = result.history_steps; + + _vte_aid_ev_yaw_pub.publish(target_innov); + + return (result.status == FusionStatus::STATUS_FUSED_CURRENT || result.status == FusionStatus::STATUS_FUSED_OOSM); +} + +void VTEOrientation::publishTarget() +{ + _orientation_msg = {}; + + const OrientationStateVec &state = _target_est_yaw.getState(); + const OrientationStateVec state_var = _target_est_yaw.getStateCovarianceDiag(); + + _orientation_msg.timestamp = _last_predict; + _orientation_msg.orientation_valid = !hasTimedOut(_last_update, _target_valid_timeout_us); + + _orientation_msg.yaw = state(KF_orientation::kYaw); + _orientation_msg.cov_yaw = state_var(KF_orientation::kYaw); + + _orientation_msg.yaw_rate = state(KF_orientation::kYawRate); + _orientation_msg.cov_yaw_rate = state_var(KF_orientation::kYawRate); + + _target_orientation_pub.publish(_orientation_msg); +} + +void VTEOrientation::print_status() const +{ + const auto yes_no = [](const bool value) { return value ? "yes" : "no"; }; + const auto age_s = [](const hrt_abstime timestamp) -> double { + if (timestamp == 0) + { + return -1.; + } + + return signedTimeDiffUs(nowUs(), timestamp) * 1e-6; + }; + + const bool orientation_valid = _estimator_initialized && !hasTimedOut(_last_update, _target_valid_timeout_us); + + PX4_INFO(" orientation state: initialized: %s, valid: %s, last predict/update age: %.3f / %.3f s", + yes_no(_estimator_initialized), yes_no(orientation_valid), age_s(_last_predict), age_s(_last_update)); + + if (!_estimator_initialized) { + return; + } + + const OrientationStateVec &state = _target_est_yaw.getState(); + + PX4_INFO(" yaw: %.3f rad (%.1f deg)", + (double)state(KF_orientation::kYaw), + (double)math::degrees(state(KF_orientation::kYaw))); + PX4_INFO(" yaw rate: %.3f rad/s", + (double)state(KF_orientation::kYawRate)); +} + +void VTEOrientation::updateParams() +{ + parameter_update_s pupdate; + _parameter_update_sub.copy(&pupdate); + + ModuleParams::updateParams(); +} + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/Orientation/VTEOrientation.h b/src/modules/vision_target_estimator/Orientation/VTEOrientation.h new file mode 100644 index 00000000000..0ef56ff11ac --- /dev/null +++ b/src/modules/vision_target_estimator/Orientation/VTEOrientation.h @@ -0,0 +1,182 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VTEOrientation.h + * @brief Estimate the orientation of a target by processing and fusing sensor + * data in a Kalman Filter. + * + * @author Jonas Perolini + * + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../common.h" +#include "KF_orientation.h" + +namespace vision_target_estimator +{ + +using namespace time_literals; + +class VTEOrientation : public ModuleParams +{ +public: + VTEOrientation(); + virtual ~VTEOrientation(); + + /** + * Run the predict/update cycle once. Pulls in the latest yaw observation, initializes the + * filter on the first viable sample, fuses it, and publishes the state. + */ + void update(); + + /** Prepare per-axis history buffers. Call once at startup. */ + bool init(); + + /** Drop the estimator state so the next valid observation re-initializes it. */ + void resetFilter(); + + /** Timeout after which the whole filter is declared stale (see @c timedOut). */ + void setVteTimeout(hrt_abstime tout) { _vte_timeout_us = tout; } + + /** Maximum age for the published yaw to be marked valid. */ + void setTargetValidTimeout(hrt_abstime tout) + { + _target_valid_timeout_us = tout; + } + + /** Maximum age for a raw observation to still be considered for fusion. */ + void setMeasRecentTimeout(hrt_abstime tout) + { + _meas_recent_timeout_us = tout; + } + + /** Set the active aid-source bitmap (@see SensorFusionMaskU). */ + void setVteAidMask(uint16_t mask_value) + { + _vte_aid_mask.value = mask_value; + } + + /** True once the filter has been initialised and has not received updates within the timeout. */ + bool timedOut() const + { + return _estimator_initialized && hasTimedOut(_last_update, _vte_timeout_us); + } + + /** True when at least one yaw aid source is enabled (required to keep the estimator running). */ + bool fusionEnabled() const + { + return _vte_aid_mask.flags.use_vision_pos; + } + + void print_status() const; + +protected: + /* + * update parameters. + */ + void updateParams() override; + + uORB::Publication _target_orientation_pub{ORB_ID(vte_orientation)}; + + // publish innovations target_estimator_gps_pos + uORB::Publication _vte_aid_ev_yaw_pub{ORB_ID(vte_aid_ev_yaw)}; + + uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; + +private: + struct VisionObs { + hrt_abstime timestamp{0}; + float yaw{0.f}; + float yaw_var{0.f}; + }; + + /** Seed state and covariance from the first valid yaw sample. */ + void initEstimator(const VisionObs &vision_obs); + /** Pull in new observations, initialise on first valid sample, and run fusion. */ + bool performUpdateStep(); + /** Advance the yaw state forward by @p dt using the constant yaw-rate model. */ + void predictionStep(float dt); + + inline bool isMeasRecent(hrt_abstime ts) const + { + return !hasTimedOut(ts, _meas_recent_timeout_us); + } + + bool isVisionDataValid(const fiducial_marker_yaw_report_s &fiducial_marker_yaw); + bool processObsVision(VisionObs &vision_obs); + bool fuseMeas(const VisionObs &vision_obs); + void publishTarget(); + bool shouldEmitWarning(hrt_abstime &last_warn); + + uORB::Subscription _fiducial_marker_yaw_report_sub{ORB_ID(fiducial_marker_yaw_report)}; + + bool _estimator_initialized{false}; + + KF_orientation _target_est_yaw{}; + vte_orientation_s _orientation_msg{}; + + hrt_abstime _last_predict{0}; // timestamp of last filter prediction + hrt_abstime _last_update{0}; // timestamp of last filter update (used to check timeout) + hrt_abstime _vision_warn_last{0}; + + /* parameters from vision_target_estimator_params.yaml */ + hrt_abstime _vte_timeout_us{3_s}; + hrt_abstime _target_valid_timeout_us{2_s}; + hrt_abstime _meas_recent_timeout_us{1_s}; + SensorFusionMaskU _vte_aid_mask{}; + + DEFINE_PARAMETERS( + (ParamFloat) _param_vte_yaw_unc_in, + (ParamFloat) _param_vte_yaw_acc_unc, + (ParamFloat) _param_vte_ev_angle_noise, + (ParamFloat) _param_vte_yaw_nis_thre + ) +}; +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/Orientation/vtest_derivation/derivation.py b/src/modules/vision_target_estimator/Orientation/vtest_derivation/derivation.py new file mode 100644 index 00000000000..5db893c2b66 --- /dev/null +++ b/src/modules/vision_target_estimator/Orientation/vtest_derivation/derivation.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" + Copyright (c) 2026 PX4 Development Team + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. Neither the name PX4 nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +File: derivation.py +Description: + Orientation state and covariance prediction derivation. +""" + +import re + +import symforce +symforce.set_epsilon_to_symbol() + +import symforce.symbolic as sf +from symforce.values import Values +import sympy as sp + + +def generate_px4_function(function_name, output_names): + from symforce.codegen import Codegen, CppConfig + import os + + return_key = output_names[0] if output_names is not None and len(output_names) == 1 else None + + codegen = Codegen.function( + function_name, + output_names=output_names, + return_key=return_key, + config=CppConfig(zero_initialization_sparsity_threshold=1), + ) + + metadata = codegen.generate_function( + output_dir="generated", + skip_directory_nesting=True, + ) + + for generated_file in metadata.generated_files: + print(f" |- {os.path.relpath(generated_file, metadata.output_dir)}") + + generated_path = os.path.abspath(metadata.generated_files[0]) + + with open(generated_path) as generated_file: + content = generated_file.read() + + content = content.replace("std::max", "math::max") + content = content.replace("std::min", "math::min") + content = content.replace("Eigen", "matrix") + content = content.replace("matrix/Dense", "matrix/math.hpp") + + # Avoid reserved naming pattern: underscore + uppercase identifier. + content = re.sub(r'_([A-Z])', lambda match: '_' + match.group(1).lower(), content) + + with open(generated_path, "w") as generated_file: + generated_file.write(content) + + +class MState(sf.Matrix): + SHAPE = (2, 2) + + +class VState(sf.Matrix): + SHAPE = (2, 1) + + +State = Values( + yaw=sf.V1(), + yaw_rate=sf.V1(), +) + + +def symbolic_state(state_structure): + symbolic = Values() + for key in state_structure.keys_recursive(): + var_type = type(state_structure[key]) + if hasattr(var_type, "symbolic"): + symbolic[key] = var_type.symbolic(key) + return symbolic + + +def matrix_to_state(state_vector: VState) -> Values: + state_values = Values() + for idx, key in enumerate(State.keys_recursive()): + state_values[key] = state_vector[idx] + return state_values + + +def state_to_matrix(state_values: Values) -> VState: + return VState(state_values.to_storage()) + + +def predict_state_with_input(dt: sf.Scalar, state_values: Values, yaw_acc: sf.Scalar) -> Values: + state_pred = state_values.copy() + state_pred["yaw"] = state_values["yaw"] + dt * state_values["yaw_rate"] + dt**2 * yaw_acc / 2 + state_pred["yaw_rate"] = state_values["yaw_rate"] + dt * yaw_acc + return state_pred + + +def get_Phi_and_G(dt: sf.Scalar): + state = symbolic_state(State) + yaw_acc = sf.Symbol("yaw_acc") + state_pred_matrix = state_to_matrix(predict_state_with_input(dt, state, yaw_acc)) + + # Compute Phi = ∂f/∂x + Phi = state_pred_matrix.jacobian([state]) + # Compute G = ∂f/∂w + G = state_pred_matrix.jacobian(yaw_acc) + return Phi, G + + +def predictState(dt: sf.Scalar, state: VState) -> VState: + state_values = matrix_to_state(state) + return state_to_matrix(predict_state_with_input(dt, state_values, sf.S(0))) + + +def getTransitionMatrix(dt: sf.Scalar) -> MState: + Phi, _ = get_Phi_and_G(dt) + return Phi + + +def derive_discrete_process_noise(dt: sf.Scalar, yaw_acc_var: sf.Scalar) -> MState: + tau = sf.Symbol("tau") + _, G_tau = get_Phi_and_G(tau) + + # Continuous-time white yaw acceleration enters through d/dtau of the discrete G(tau). + G_continuous = G_tau.jacobian(tau) + + Q = sf.Matrix.zeros(State.storage_dim(), State.storage_dim()) + + for row in range(State.storage_dim()): + for col in range(State.storage_dim()): + integrand = G_continuous[row, 0] * G_continuous[col, 0] * yaw_acc_var + Q[row, col] = sp.integrate(integrand, (tau, 0, dt)) + + return Q + + +def predictCov(dt: sf.Scalar, yaw_acc_var: sf.Scalar, covariance: MState) -> MState: + Phi, _ = get_Phi_and_G(dt) + Q = derive_discrete_process_noise(dt, yaw_acc_var) + return Phi * covariance * Phi.T + Q + + +print("Derive VTEST orientation equations...") +generate_px4_function(predictState, output_names=["predict_state"]) +generate_px4_function(getTransitionMatrix, output_names=["transition_matrix"]) +generate_px4_function(predictCov, output_names=["cov_updated"]) diff --git a/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/getTransitionMatrix.h b/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/getTransitionMatrix.h new file mode 100644 index 00000000000..a9c52066de5 --- /dev/null +++ b/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/getTransitionMatrix.h @@ -0,0 +1,47 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: getTransitionMatrix + * + * Args: + * dt: Scalar + * + * Outputs: + * transition_matrix: Matrix22 + */ +template +matrix::Matrix Gettransitionmatrix(const Scalar dt) +{ + // Total ops: 0 + + // Input arrays + + // Intermediate terms (0) + + // Output terms (1) + matrix::Matrix _transition_matrix; + + _transition_matrix.setZero(); + + _transition_matrix(0, 0) = 1; + _transition_matrix(0, 1) = dt; + _transition_matrix(1, 1) = 1; + + return _transition_matrix; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/predictCov.h b/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/predictCov.h new file mode 100644 index 00000000000..d0dc011759f --- /dev/null +++ b/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/predictCov.h @@ -0,0 +1,56 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: predictCov + * + * Args: + * dt: Scalar + * yaw_acc_var: Scalar + * covariance: Matrix22 + * + * Outputs: + * cov_updated: Matrix22 + */ +template +matrix::Matrix Predictcov(const Scalar dt, const Scalar yaw_acc_var, + const matrix::Matrix &covariance) +{ + // Total ops: 18 + + // Input arrays + + // Intermediate terms (3) + const Scalar _tmp0 = covariance(1, 1) * dt; + const Scalar _tmp1 = _tmp0 + covariance(0, 1); + const Scalar _tmp2 = (Scalar(1) / Scalar(2)) * std::pow(dt, Scalar(2)) * yaw_acc_var; + + // Output terms (1) + matrix::Matrix _cov_updated; + + _cov_updated(0, 0) = + _tmp1 * dt + covariance(0, 0) + covariance(1, 0) * dt + (Scalar(1) / Scalar(3)) * [&]() { + const Scalar base = dt; + return base * base * base; + }() * yaw_acc_var; + _cov_updated(1, 0) = _tmp0 + _tmp2 + covariance(1, 0); + _cov_updated(0, 1) = _tmp1 + _tmp2; + _cov_updated(1, 1) = covariance(1, 1) + dt * yaw_acc_var; + + return _cov_updated; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/predictState.h b/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/predictState.h new file mode 100644 index 00000000000..6be511e4157 --- /dev/null +++ b/src/modules/vision_target_estimator/Orientation/vtest_derivation/generated/predictState.h @@ -0,0 +1,46 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: predictState + * + * Args: + * dt: Scalar + * state: Matrix21 + * + * Outputs: + * predict_state: Matrix21 + */ +template +matrix::Matrix Predictstate(const Scalar dt, + const matrix::Matrix &state) +{ + // Total ops: 2 + + // Input arrays + + // Intermediate terms (0) + + // Output terms (1) + matrix::Matrix _predict_state; + + _predict_state(0, 0) = dt * state(1, 0) + state(0, 0); + _predict_state(1, 0) = state(1, 0); + + return _predict_state; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/KF_position.cpp b/src/modules/vision_target_estimator/Position/KF_position.cpp new file mode 100644 index 00000000000..791cc33428d --- /dev/null +++ b/src/modules/vision_target_estimator/Position/KF_position.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file KF_position.cpp + * @brief Filter to estimate the pose of moving targets. State: [pos_rel, vel_uav, bias, acc_target, vel_target] + * + * @author Jonas Perolini + * + */ + +#include "KF_position.h" + +#include + +#include +#include +#include +#include +#include +#include + +namespace vision_target_estimator +{ + +void KF_position::predict(float dt, float acc_uav) +{ + + if (!PX4_ISFINITE(dt) || (dt < 0.f) || !PX4_ISFINITE(acc_uav)) { + return; + } + + _last_acc = acc_uav; + + VectorState state_next; + SquareMatrixState cov_next; + + predictState(dt, acc_uav, _state, _state_covariance, state_next, cov_next); + + _state = state_next; + _state_covariance = cov_next; +} + +KF_position::SquareMatrixState KF_position::getTransitionMatrix(float dt) const +{ + return sym::Gettransitionmatrix(dt); +} + +void KF_position::predictState(float dt, float acc, + const VectorState &x_in, + const SquareMatrixState &P_in, + VectorState &x_out, + SquareMatrixState &P_out) +{ + x_out = sym::Predictstate(dt, x_in, acc); + P_out = sym::Predictcov(dt, _input_var, _bias_var, _acc_var, P_in); +} + +void KF_position::computeInnovation(const VectorState &state, + const SquareMatrixState &cov, + const ScalarMeas &meas, + float &innov, float &innov_var) const +{ + innov = meas.val - (meas.H.transpose() * state)(0, 0); + innov_var = sym::Computeinnovcov(meas.unc, cov, meas.H.transpose()); +} + +void KF_position::pushHistory(const uint64_t time_us) +{ + _oosm.push(time_us, _state, _state_covariance, _last_acc); +} + +void KF_position::resetHistory() +{ + _oosm.reset(); +} + +FusionResult KF_position::fuseScalarAtTime(const ScalarMeas &meas, uint64_t now_us, float nis_threshold) +{ + return _oosm.fuse(*this, meas, now_us, nis_threshold, _state, _state_covariance, _last_acc); +} + +void KF_position::applyCorrection(VectorState &state, SquareMatrixState &cov, const VectorState &K, float innov, float S) +{ + VectorState state_new; + SquareMatrixState cov_new; + + sym::Applycorrection(state, cov, K, innov, S, &state_new, &cov_new); + + state = state_new; + cov = cov_new; + + // Clamp diagonal assuming a small epsilon for stability: + for (size_t i = 0; i < kStateSize; i++) { + cov(i, i) = fmaxf(cov(i, i), kMinVar); + } +} + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/Position/KF_position.h b/src/modules/vision_target_estimator/Position/KF_position.h new file mode 100644 index 00000000000..a01d81b1166 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/KF_position.h @@ -0,0 +1,137 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file KF_position.h + * @brief Per-axis Kalman Filter for VTEST position states. + * + * @author Jonas Perolini + * + */ + +#pragma once + +#include +#include + +#include +#include + +#include "../VTEOosm.h" +#include "../common.h" + +namespace vision_target_estimator +{ + +class KF_position +{ +public: + static constexpr size_t kStateSize = vtest::State::size; + using VectorState = matrix::Vector; + using SquareMatrixState = matrix::SquareMatrix; + + friend class OOSMManager; + + KF_position() = default; + ~KF_position() = default; + static constexpr float kMinVar = 1e-9f; + + struct ScalarMeas { + uint64_t time_us; + float val; + float unc; + VectorState H; + }; + + void predict(float dt, float acc_uav); + + // Primary Fusion Interface (history-consistent OOSM) + // Projected correction OOSM approximation: + // - Most accurate with bounded delays and when fusions are processed in timestamp order (oldest -> newest). + // - Does not replay intermediate measurement updates (unlike EKF2's delayed fusion horizon). + // Returns FusionResult describing the result for logging. + FusionResult fuseScalarAtTime(const ScalarMeas &meas, uint64_t now_us, float nis_threshold); + + // History Management + void pushHistory(const uint64_t time_us); + void resetHistory(); + + // Setters / Getters + void setState(const VectorState &state) { _state = state; } + void setStateCovarianceDiag(const VectorState &var) + { + const SquareMatrixState var_mat = diag(var); + _state_covariance = var_mat; + }; + + const VectorState &getState() const { return _state; } + const SquareMatrixState &getStateCovariance() const { return _state_covariance; } + VectorState getStateCovarianceDiag() const { return _state_covariance.diag(); } + + void setInputVar(float var) { _input_var = var; } + void setBiasVar(float var) { _bias_var = var; } + void setTargetAccVar(float var) { _acc_var = var; } + +private: + SquareMatrixState getTransitionMatrix(float dt) const; + + void predictState(float dt, float acc, + const VectorState &x_in, + const SquareMatrixState &P_in, + VectorState &x_out, + SquareMatrixState &P_out); + + void computeInnovation(const VectorState &state, + const SquareMatrixState &cov, const ScalarMeas &meas, + float &innov, float &innov_var) const; + + void applyCorrection(VectorState &state, + SquareMatrixState &cov, + const VectorState &K, + float innov, float S); + + VectorState _state{}; + SquareMatrixState _state_covariance{}; + + float _bias_var{0.f}; // bias random-walk spectral density (m^2 / s) + float _acc_var{0.f}; // target acceleration random-walk spectral density ((m/s^2)^2 / s) + float _input_var{0.f}; // white UAV acceleration noise PSD (m^2 / s^3, or (m/s^2)^2 / Hz) + + float _last_acc{0.f}; // last UAV acceleration input (also used as OOSM fallback input) + + // OOSM history buffer: + // 0.5 s window @ 50 Hz predict rate = 25 samples. + // Note that the 0.5 s window is enforced with kOosmMaxTimeUs = 500_ms. + OOSMManager _oosm; +}; +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/Position/VTEPosition.cpp b/src/modules/vision_target_estimator/Position/VTEPosition.cpp new file mode 100644 index 00000000000..6f1506d8471 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/VTEPosition.cpp @@ -0,0 +1,1690 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VTEPosition.cpp + * @brief Estimate the state of a target by processing and fusing sensor data in a Kalman Filter. + * + * @author Jonas Perolini + * + */ + +#include + +#include +#include + +#include + +#include "VTEPosition.h" + +namespace vision_target_estimator +{ + +using namespace matrix; + +VTEPosition::VTEPosition() : + ModuleParams(nullptr) +{ + _target_pose_pub.advertise(); + _target_estimator_state_pub.advertise(); + _vte_aid_gps_pos_target_pub.advertise(); + _vte_aid_gps_pos_mission_pub.advertise(); + _vte_aid_gps_vel_uav_pub.advertise(); + _vte_aid_gps_vel_target_pub.advertise(); + _vte_aid_fiducial_marker_pub.advertise(); + _vte_bias_init_status_pub.advertise(); + + updateParams(); +} + +VTEPosition::~VTEPosition() +{ + perf_free(_vte_predict_perf); + perf_free(_vte_update_perf); + perf_free(_vte_fusion_perf); +} + +bool VTEPosition::shouldEmitWarning(hrt_abstime &last_warn) +{ + const hrt_abstime now = nowUs(); + + if ((last_warn == 0) || (now < last_warn) || ((now - last_warn) > kWarnThrottleIntervalUs)) { + last_warn = now; + return true; + } + + return false; +} + +bool VTEPosition::init() +{ + // Check valid vtest_derivation/generated/state.h + if (vtest::Axis::size != kExpectedAxisCount) { + PX4_ERR("VTE: Invalid axis size: %d, expected %d. Generate vtest_derivation/derivation.py", + static_cast(vtest::Axis::size), kExpectedAxisCount); + return false; + } + +#if defined(CONFIG_VTEST_MOVING) + PX4_INFO("VTE for moving target init"); + PX4_WARN("VTE for moving targets has not been thoroughly tested"); + + if (vtest::State::size != kExpectedMovingPositionStateCount) { + PX4_ERR("VTE: Invalid state size: %d, expected %d. Generate vtest_derivation/derivation.py", + static_cast(vtest::State::size), kExpectedMovingPositionStateCount); + return false; + } + +#else + PX4_INFO("VTE for static target init"); + + if (vtest::State::size != kExpectedStaticPositionStateCount) { + PX4_ERR("VTE: Invalid state size: %d, expected %d. Generate vtest_derivation/derivation.py", + static_cast(vtest::State::size), kExpectedStaticPositionStateCount); + return false; + } + +#endif // CONFIG_VTEST_MOVING + + for (int axis = 0; axis < vtest::Axis::size; ++axis) { + _target_est_pos[axis].resetHistory(); + } + + return true; +} + +void VTEPosition::resetFilter() +{ + _estimator_initialized = false; + _last_relative_meas_fused_time = 0; + _bias.set = false; + _pre_bias_reference = PreBiasReference::kUnknown; + resetBiasAveraging(); + + for (int axis = 0; axis < vtest::Axis::size; ++axis) { + _target_est_pos[axis].resetHistory(); + } +} + +void VTEPosition::update(const Vector3f &acc_ned) +{ + if (_parameter_update_sub.updated()) { + updateParams(); + } + + checkMeasurementInputs(); + + // Predict the target state using a constant relative-acceleration model. + if (_estimator_initialized) { + const hrt_abstime now_us = nowUs(); + + if (now_us < _last_predict) { + resetFilter(); + PX4_WARN("VTE position invalid _last_predict time"); + return; + } + + const uint64_t dt_us = now_us - _last_predict; + + // Guard against large dt values for which the constant acceleration assumption does not hold. + static constexpr uint64_t kMaxPredictionDeltaTimeUs = 100_ms; // Filter runs at 50 Hz, expect dt = 20 ms. + + if (dt_us > kMaxPredictionDeltaTimeUs) { + resetFilter(); + PX4_WARN("VTE position stale, resetting filter"); + return; + } + + const float dt = dt_us * kMicrosecondsToSeconds; + perf_begin(_vte_predict_perf); + predictionStep(acc_ned, dt); + perf_end(_vte_predict_perf); + + _last_predict = now_us; + } + + // Update with the newest observations, fuse if the filter is initialised, + // and publish any resulting innovations. + if (performUpdateStep(acc_ned)) { + _last_update = _last_predict; + } + + if (_estimator_initialized) { + // Store the post-fusion posterior snapshot at the current timestamp for OOSM fusion. + for (int axis = 0; axis < vtest::Axis::size; ++axis) { + _target_est_pos[axis].pushHistory(_last_predict); + } + + publishTarget(); + } +} + +bool VTEPosition::initEstimator(const AxisEstimatorStates &state_init) +{ + // Get initial variance from params + const float state_pos_var = fmaxf(_param_vte_pos_unc_in.get(), kMinVariance); + const float state_vel_var = fmaxf(_param_vte_vel_unc_in.get(), kMinVariance); + const float state_bias_var = fmaxf(_param_vte_bias_unc_in.get(), kMinVariance); + + EstimatorState state_var_init{}; + state_var_init(vtest::State::pos_rel) = state_pos_var; + state_var_init(vtest::State::vel_uav) = state_vel_var; + state_var_init(vtest::State::bias) = state_bias_var; + +#if defined(CONFIG_VTEST_MOVING) + const float state_acc_var = fmaxf(_param_vte_acc_unc_in.get(), kMinVariance); + const float state_target_vel_var = fmaxf(_param_vte_vel_unc_in.get(), kMinVariance); + state_var_init(vtest::State::acc_target) = state_acc_var; + state_var_init(vtest::State::vel_target) = state_target_vel_var; + +#endif // CONFIG_VTEST_MOVING + + for (int i = 0; i < vtest::Axis::size; i++) { + _target_est_pos[i].setState(state_init[i]); + _target_est_pos[i].setStateCovarianceDiag(state_var_init); + } + + // Debug INFO + PX4_DEBUG("Rel pos init %.2f %.2f %.2f", (double)state_init[vtest::Axis::x](vtest::State::pos_rel), + (double)state_init[vtest::Axis::y](vtest::State::pos_rel), + (double)state_init[vtest::Axis::z](vtest::State::pos_rel)); + PX4_DEBUG("Vel uav init %.2f %.2f %.2f", (double)state_init[vtest::Axis::x](vtest::State::vel_uav), + (double)state_init[vtest::Axis::y](vtest::State::vel_uav), + (double)state_init[vtest::Axis::z](vtest::State::vel_uav)); + PX4_DEBUG("GNSS bias init %.2f %.2f %.2f", (double)state_init[vtest::Axis::x](vtest::State::bias), + (double)state_init[vtest::Axis::y](vtest::State::bias), + (double)state_init[vtest::Axis::z](vtest::State::bias)); + +#if defined(CONFIG_VTEST_MOVING) + PX4_DEBUG("Target acc init %.2f %.2f %.2f", (double)state_init[vtest::Axis::x](vtest::State::acc_target), + (double)state_init[vtest::Axis::y](vtest::State::acc_target), + (double)state_init[vtest::Axis::z](vtest::State::acc_target)); + PX4_DEBUG("Target vel init %.2f %.2f %.2f", (double)state_init[vtest::Axis::x](vtest::State::vel_target), + (double)state_init[vtest::Axis::y](vtest::State::vel_target), + (double)state_init[vtest::Axis::z](vtest::State::vel_target)); +#endif // CONFIG_VTEST_MOVING + + return true; +} + +void VTEPosition::predictionStep(const Vector3f &vehicle_acc_ned, const float dt) +{ + const float bias_var = fmaxf(_param_vte_bias_unc.get(), kMinVariance); + const float uav_acc_var = fmaxf(_param_vte_acc_d_unc.get(), kMinVariance); +#if defined(CONFIG_VTEST_MOVING) + const float target_acc_var = fmaxf(_param_vte_acc_t_unc.get(), kMinVariance); +#endif // CONFIG_VTEST_MOVING + + //Decoupled dynamics, we neglect the off diag elements. + for (int i = 0; i < vtest::Axis::size; i++) { +#if defined(CONFIG_VTEST_MOVING) + _target_est_pos[i].setTargetAccVar(target_acc_var); +#endif // CONFIG_VTEST_MOVING + + // We assume an isotropic uncertainty (cov = sigma^2 * I) + // The rotated input covariance from body to NED R*(sigma^2 * I)*R^T = sigma^2*I because R*R^T = I. + _target_est_pos[i].setBiasVar(bias_var); + _target_est_pos[i].setInputVar(uav_acc_var); + + _target_est_pos[i].predict(dt, vehicle_acc_ned(i)); + } +} + +bool VTEPosition::performUpdateStep(const Vector3f &vehicle_acc_ned) +{ + // Gather observations and tag the fusion mask bits for each new valid source. + resetObservations(); + ObsValidMaskU fusion_mask{}; + processObservations(fusion_mask, _obs_buffer); + + if (fusion_mask.value == 0) { + return false; + } + + if (!_estimator_initialized) { + if (!hasNewPositionSensorData(fusion_mask)) { + return false; + } + + if (!initializeEstimator(fusion_mask, _obs_buffer)) { + return false; + } + } + + if (!_bias.set) { + updateBiasIfObservable(fusion_mask, _obs_buffer); + } + + return fuseActiveMeasurements(vehicle_acc_ned, fusion_mask, _obs_buffer); +} + +void VTEPosition::resetObservations() +{ + for (auto &obs : _obs_buffer) { + obs = {}; + } +} + +void VTEPosition::processObservations(ObsValidMaskU &fusion_mask, + TargetObs observations[kObsTypeCount]) +{ + if (_vte_aid_mask.flags.use_vision_pos) { + fusion_mask.flags.fuse_vision = processObsVision(observations[obsIndex(ObsType::kFiducialMarker)]); + } + + if (updateUavGpsData()) { + if (_vte_aid_mask.flags.use_mission_pos && _mission_land_position.valid) { + fusion_mask.flags.fuse_mission_pos = processObsGNSSPosMission(observations[obsIndex(ObsType::kMissionGpsPos)]); + } + + if (_vte_aid_mask.flags.use_uav_gps_vel && _uav_gps_vel.valid) { + fusion_mask.flags.fuse_uav_gps_vel = processObsGNSSVelUav(observations[obsIndex(ObsType::kUavGpsVel)]); + } + } + + target_gnss_s target_gnss{}; + + if (_target_gnss_sub.update(&target_gnss)) { + const bool target_gps_position_valid = isTargetGpsPositionValid(target_gnss); + + if (_vte_aid_mask.flags.use_target_gps_pos && _uav_gps_position.valid + && target_gps_position_valid && target_gnss.abs_pos_updated) { + fusion_mask.flags.fuse_target_gps_pos = processObsGNSSPosTarget(target_gnss, + observations[obsIndex(ObsType::kTargetGpsPos)]); + } + +#if defined(CONFIG_VTEST_MOVING) + + if (isTargetGpsVelocityValid(target_gnss)) { + + updateTargetGpsVelocity(target_gnss); + + if (_vte_aid_mask.flags.use_target_gps_vel && _target_gps_vel.valid) { + fusion_mask.flags.fuse_target_gps_vel = processObsGNSSVelTarget(target_gnss, + observations[obsIndex(ObsType::kTargetGpsVel)]); + } + } + +#endif // CONFIG_VTEST_MOVING + + } +} + +bool VTEPosition::isVisionDataValid(const fiducial_marker_pos_report_s &fiducial_marker_pose) +{ + if (!isMeasRecent(fiducial_marker_pose.timestamp_sample)) { + if (shouldEmitWarning(_vision_pos_warn_last)) { + PX4_WARN("VTE: Vision data too old!"); + } + + return false; + } + + const bool finite_measurement = Vector3f(fiducial_marker_pose.rel_pos).isAllFinite(); + + if (!finite_measurement) { + if (shouldEmitWarning(_vision_pos_warn_last)) { + PX4_WARN("VTE: Vision meas is corrupt!"); + } + + return false; + } + + const bool finite_cov = Vector3f(fiducial_marker_pose.cov_rel_pos).isAllFinite(); + + if (!finite_cov) { + if (shouldEmitWarning(_vision_pos_warn_last)) { + PX4_WARN("VTE: Vision cov is corrupt!"); + } + + return false; + } + + // Rotate vision observation into vc-NED using the reported attitude quaternion + const bool finite_q = PX4_ISFINITE(fiducial_marker_pose.q[0]) + && PX4_ISFINITE(fiducial_marker_pose.q[1]) + && PX4_ISFINITE(fiducial_marker_pose.q[2]) + && PX4_ISFINITE(fiducial_marker_pose.q[3]); + + if (!finite_q) { + if (shouldEmitWarning(_vision_pos_warn_last)) { + PX4_WARN("VTE: Vision attitude quaternion is corrupt!"); + } + + return false; + } + + return true; +} + +bool VTEPosition::isUavGpsPositionValid() +{ + if (!isMeasRecent(_uav_gps_position.timestamp)) { + return false; + } + + if (!isLatLonAltValid(_uav_gps_position.lat_deg, _uav_gps_position.lon_deg, + _uav_gps_position.alt_m, "UAV GPS ", &_uav_gps_pos_warn_last)) { + return false; + } + + if (_gps_pos_is_offset && !_gps_pos_offset_ned.valid) { + PX4_DEBUG("Uav Gps position invalid offset!"); // Debug because this message can spam + return false; + } + + return true; +} + +bool VTEPosition::isUavGpsVelocityValid() +{ + // Check freshness first to early-out on stale samples before touching the payload. + if (!isMeasRecent(_uav_gps_vel.timestamp)) { + return false; + } + + if (!_uav_gps_vel.xyz.isAllFinite()) { + if (shouldEmitWarning(_uav_gps_vel_warn_last)) { + PX4_WARN("UAV GPS velocity not finite! vx: %.1f, vy: %.1f, vz: %.1f", + (double)_uav_gps_vel.xyz(vtest::Axis::x), (double)_uav_gps_vel.xyz(vtest::Axis::y), + (double)_uav_gps_vel.xyz(vtest::Axis::z)); + } + + return false; + } + + if (_gps_pos_is_offset && !_velocity_offset_ned.valid) { + PX4_DEBUG("Uav Gps velocity invalid offset!"); + return false; + } + + return true; +} + +bool VTEPosition::updateUavGpsData() +{ + sensor_gps_s vehicle_gps_position; + const bool vehicle_gps_position_updated = _vehicle_gps_position_sub.update(&vehicle_gps_position); + + if (vehicle_gps_position_updated) { + // Position + _uav_gps_position.lat_deg = vehicle_gps_position.latitude_deg; + _uav_gps_position.lon_deg = vehicle_gps_position.longitude_deg; + _uav_gps_position.alt_m = (float)vehicle_gps_position.altitude_msl_m; + _uav_gps_position.timestamp = vehicle_gps_position.timestamp_sample; + _uav_gps_position.eph = vehicle_gps_position.eph; + _uav_gps_position.epv = vehicle_gps_position.epv; + _uav_gps_position.valid = isUavGpsPositionValid(); + + // Velocity + _uav_gps_vel.timestamp = vehicle_gps_position.timestamp_sample; + _uav_gps_vel.xyz(vtest::Axis::x) = vehicle_gps_position.vel_n_m_s; + _uav_gps_vel.xyz(vtest::Axis::y) = vehicle_gps_position.vel_e_m_s; + _uav_gps_vel.xyz(vtest::Axis::z) = vehicle_gps_position.vel_d_m_s; + _uav_gps_vel.uncertainty = vehicle_gps_position.s_variance_m_s; + _uav_gps_vel.valid = vehicle_gps_position.vel_ned_valid && isUavGpsVelocityValid(); + + } else { + // Check if stored data is still valid + _uav_gps_position.valid = _uav_gps_position.valid && isMeasRecent(_uav_gps_position.timestamp); + _uav_gps_vel.valid = _uav_gps_vel.valid && isMeasRecent(_uav_gps_vel.timestamp); + } + + return vehicle_gps_position_updated; +} + +#if defined(CONFIG_VTEST_MOVING) +void VTEPosition::updateTargetGpsVelocity(const target_gnss_s &target_gnss) +{ + _target_gps_vel.timestamp = target_gnss.timestamp_sample; + _target_gps_vel.valid = isMeasRecent(target_gnss.timestamp_sample); + + _target_gps_vel.xyz(vtest::Axis::x) = target_gnss.vel_n_m_s; + _target_gps_vel.xyz(vtest::Axis::y) = target_gnss.vel_e_m_s; + _target_gps_vel.xyz(vtest::Axis::z) = target_gnss.vel_d_m_s; +} +#endif // CONFIG_VTEST_MOVING + +bool VTEPosition::isTargetGpsPositionValid(const target_gnss_s &target_gnss) +{ + if (!isMeasRecent(target_gnss.timestamp_sample)) { + return false; + } + + if (!isLatLonAltValid(target_gnss.latitude_deg, target_gnss.longitude_deg, + target_gnss.altitude_msl_m, "Target GPS ", &_target_gps_pos_warn_last)) { + return false; + } + + return true; +} + +bool VTEPosition::isTargetGpsVelocityValid(const target_gnss_s &target_gnss) +{ + if (!isMeasRecent(target_gnss.timestamp_sample)) { + return false; + } + + const Vector3f target_vel_ned{target_gnss.vel_n_m_s, target_gnss.vel_e_m_s, target_gnss.vel_d_m_s}; + + if (!target_gnss.vel_ned_updated || !target_vel_ned.isAllFinite()) { + if (shouldEmitWarning(_target_gps_vel_warn_last)) { + PX4_WARN("Target GPS velocity is corrupt!"); + } + + return false; + } + + return true; +} + +bool VTEPosition::initializeEstimator(const ObsValidMaskU &fusion_mask, + const TargetObs observations[kObsTypeCount]) +{ + if (!hasNewPositionSensorData(fusion_mask)) { + return false; + } + + if (!hasInitialVelocityEstimate()) { + if (shouldEmitWarning(_init_vel_warn_last)) { + PX4_WARN("No UAV velocity estimate. Estimator cannot be started."); + } + + return false; + } + + // If both GNSS and vision are available at startup, only keep the GNSS-first + // path when bias averaging is explicitly enabled. + // Otherwise, trust vision and activate the bias immediately. + const bool has_vision_observation = fusion_mask.flags.fuse_vision; + const bool can_average_initial_bias = shouldSetBias(has_vision_observation) && isBiasAveragingEnabled(); + + Vector3f initial_position{}; + const PreBiasReference initial_reference = selectInitialPosition(fusion_mask, observations, initial_position, + !can_average_initial_bias); + const bool average_initial_bias = shouldAverageInitialBias(has_vision_observation, initial_reference); + + Vector3f initial_bias{}; + + if (shouldSetBias(has_vision_observation) && !average_initial_bias) { + selectInitialBiasFromGnss(observations, initial_position, initial_bias); + } + + AxisEstimatorStates state_init{}; + buildInitialStateArray(initial_position, selectInitialUavVelocity(), initial_bias, state_init); + + if (!initEstimator(state_init)) { + resetFilter(); + return false; + } + + PX4_DEBUG("VTE Position Estimator properly initialized."); + _estimator_initialized = true; + _pre_bias_reference = _bias.set ? PreBiasReference::kUnknown : initial_reference; + _last_update = nowUs(); + _last_predict = _last_update; + + for (int axis = 0; axis < vtest::Axis::size; ++axis) { + _target_est_pos[axis].resetHistory(); + } + + return true; +} + +bool VTEPosition::hasInitialVelocityEstimate() const +{ + return (_local_velocity.valid && isMeasRecent(_local_velocity.timestamp)) + || (_uav_gps_vel.valid && isMeasRecent(_uav_gps_vel.timestamp)); +} + +Vector3f VTEPosition::selectInitialUavVelocity() const +{ + // Prefer GNSS-derived velocity when available; local velocity is a fallback. + if (_uav_gps_vel.valid && isMeasRecent(_uav_gps_vel.timestamp)) { + return _uav_gps_vel.xyz; + } + + if (_local_velocity.valid && isMeasRecent(_local_velocity.timestamp)) { + return _local_velocity.xyz; + } + + return Vector3f{}; +} + +void VTEPosition::selectInitialBiasFromGnss(const TargetObs observations[kObsTypeCount], + const Vector3f &initial_position, Vector3f &initial_bias) +{ + PX4_DEBUG("VTE Position setting GNSS bias."); + const hrt_abstime sample_time = observations[obsIndex(ObsType::kFiducialMarker)].timestamp; + Vector3f gnss_sample{}; + + if (selectBiasGnssSample(sample_time, gnss_sample)) { + initial_bias = gnss_sample - initial_position; + } + + _bias.set = true; +} + +void VTEPosition::buildInitialStateArray(const Vector3f &initial_position, + const Vector3f &initial_uav_velocity, const Vector3f &initial_bias, + AxisEstimatorStates &state_init) const +{ +#if defined(CONFIG_VTEST_MOVING) + // Assume null target absolute acceleration; seed target velocity from GNSS when recent. + Vector3f initial_target_velocity{}; + + if (_target_gps_vel.valid && isMeasRecent(_target_gps_vel.timestamp)) { + initial_target_velocity = _target_gps_vel.xyz; + } + +#endif // CONFIG_VTEST_MOVING + + for (int axis = 0; axis < vtest::Axis::size; ++axis) { + state_init[axis](vtest::State::pos_rel) = initial_position(axis); + state_init[axis](vtest::State::vel_uav) = initial_uav_velocity(axis); + state_init[axis](vtest::State::bias) = initial_bias(axis); + +#if defined(CONFIG_VTEST_MOVING) + state_init[axis](vtest::State::acc_target) = 0.f; + state_init[axis](vtest::State::vel_target) = initial_target_velocity(axis); +#endif // CONFIG_VTEST_MOVING + } +} + +VTEPosition::PreBiasReference VTEPosition::selectInitialPosition(const ObsValidMaskU &fusion_mask, + const TargetObs observations[kObsTypeCount], matrix::Vector3f &initial_position, + const bool prefer_vision) +{ + // Before the GNSS bias is ready, initialize from vision when requested and + // otherwise fall back to the available GNSS position source. + if (prefer_vision && fusion_mask.flags.fuse_vision) { + initial_position = observations[obsIndex(ObsType::kFiducialMarker)].meas_xyz; + return PreBiasReference::kVision; + } + + if (fusion_mask.flags.fuse_target_gps_pos) { + initial_position = observations[obsIndex(ObsType::kTargetGpsPos)].meas_xyz; + return PreBiasReference::kGnss; + } + + if (fusion_mask.flags.fuse_mission_pos) { + initial_position = observations[obsIndex(ObsType::kMissionGpsPos)].meas_xyz; + return PreBiasReference::kGnss; + } + + if (!prefer_vision && fusion_mask.flags.fuse_vision) { + initial_position = observations[obsIndex(ObsType::kFiducialMarker)].meas_xyz; + return PreBiasReference::kVision; + } + + return PreBiasReference::kUnknown; +} + +bool VTEPosition::getOffsetUavVel(const hrt_abstime sample_time, Vector3f &uav_velocity_ned) const +{ + if (!_uav_gps_vel.valid || !isTimeDifferenceWithin(_uav_gps_vel.timestamp, sample_time, _meas_updated_timeout_us)) { + return false; + } + + uav_velocity_ned = _uav_gps_vel.xyz; + + if (_gps_pos_is_offset) { + if (!_velocity_offset_ned.valid + || !isTimeDifferenceWithin(_velocity_offset_ned.timestamp, _uav_gps_vel.timestamp, _meas_updated_timeout_us)) { + return false; + } + + uav_velocity_ned -= _velocity_offset_ned.xyz; + } + + return true; +} + +bool VTEPosition::selectBiasGnssSample(const hrt_abstime sample_time, Vector3f &gnss_sample) +{ + // Velocity-propagation below compensates for the lag between the cached GNSS sample and + // the requested vision sample, so the alignment gate uses recent-measurement + // tolerance and not the tighter "updated" gate which can reject usable samples. + if (!_pos_rel_gnss.valid || !isMeasRecent(_pos_rel_gnss.timestamp) + || !isTimeDifferenceWithin(_pos_rel_gnss.timestamp, sample_time, _meas_recent_timeout_us)) { + return false; + } + + gnss_sample = _pos_rel_gnss.xyz; + + const int64_t dt_us = signedTimeDiffUs(sample_time, _pos_rel_gnss.timestamp); + + if (dt_us != 0) { + const float dt = static_cast(dt_us) * kMicrosecondsToSeconds; + Vector3f uav_velocity_ned{}; + bool has_velocity_for_propagation = false; + + if (_local_velocity.valid + && isTimeDifferenceWithin(_local_velocity.timestamp, sample_time, _meas_updated_timeout_us)) { + uav_velocity_ned = _local_velocity.xyz; + has_velocity_for_propagation = true; + + } else if (getOffsetUavVel(sample_time, uav_velocity_ned)) { + has_velocity_for_propagation = true; + } + + if (has_velocity_for_propagation) { + gnss_sample -= uav_velocity_ned * dt; + } + } + + return true; +} + +void VTEPosition::updateBiasIfObservable(const ObsValidMaskU &fusion_mask, + const TargetObs observations[kObsTypeCount]) +{ + if (!fusion_mask.flags.fuse_vision) { + return; + } + + const TargetObs &vision_obs = observations[obsIndex(ObsType::kFiducialMarker)]; + const hrt_abstime sample_time = vision_obs.timestamp; + + if (sample_time == 0) { + return; + } + + Vector3f initial_position{}; + selectInitialPosition(fusion_mask, observations, initial_position); + + Vector3f gnss_sample{}; + + if (!selectBiasGnssSample(sample_time, gnss_sample)) { + if (_bias.averaging_active) { + PX4_WARN("GNSS unavailable, ending bias averaging and switching to vision."); + activateBiasEstimate(initial_position, _bias.initial_lpf.getState()); + + } else if (_pre_bias_reference == PreBiasReference::kGnss) { + // The state was initialized GNSS-referenced, so vision fusion is currently + // gated on the GNSS bias being observable. Without an aligned GNSS sample + // we would never make progress and vision would be blocked indefinitely. + // Activate the bias with a zero offset so the filter unblocks. + PX4_WARN("GNSS bias not observable, setting bias to zero."); + activateBiasEstimate(initial_position, Vector3f{}); + } + + return; + } + + const Vector3f initial_bias = gnss_sample - initial_position; + + if (!_bias.averaging_active && shouldAverageInitialBias(fusion_mask.flags.fuse_vision)) { + PX4_INFO("GNSS/vision bias observable, averaging initial GNSS bias."); + startBiasAveraging(initial_bias, sample_time); + return; + } + + if (_bias.averaging_active) { + if (!updateBiasAveraging(initial_bias, sample_time)) { + return; + } + + PX4_INFO("GNSS bias averaging complete, setting position and bias."); + const Vector3f filtered_bias = _bias.initial_lpf.getState(); + activateBiasEstimate(gnss_sample - filtered_bias, filtered_bias); + return; + } + + PX4_INFO("GNSS/vision bias observable, setting position and bias."); + activateBiasEstimate(initial_position, initial_bias); +} + +void VTEPosition::startBiasAveraging(const Vector3f &bias_sample, const hrt_abstime sample_time) +{ + _bias.initial_lpf.reset(bias_sample); + _bias.averaging_active = true; + _bias.stable_delta_count = 0; + _bias.averaging_start_time = sample_time; + _bias.last_sample_time = sample_time; + + publishBiasInitStatus(bias_sample, bias_sample, 0.f, sample_time); +} + +bool VTEPosition::updateBiasAveraging(const Vector3f &bias_sample, const hrt_abstime sample_time) +{ + static constexpr float kInitialBiasLpfMinTimeFactor{2.f}; + static constexpr uint8_t kRequiredStableBiasDeltas{5}; + + if (!_bias.averaging_active) { + return false; + } + + // Ignore duplicate or out-of-order samples: the LPF's alpha was set from the previous + // interval's dt, so reusing it here would re-apply the same time step and double-count + // the measurement without reflecting any elapsed time. + if (sample_time <= _bias.last_sample_time) { + return false; + } + + const Vector3f filtered_bias_before_update = _bias.initial_lpf.getState(); + const float bias_delta = (bias_sample - filtered_bias_before_update).norm(); + + const float dt = static_cast(sample_time - _bias.last_sample_time) * kMicrosecondsToSeconds; + _bias.initial_lpf.update(bias_sample, dt); + _bias.last_sample_time = sample_time; + + const Vector3f filtered_bias_logged = _bias.initial_lpf.getState(); + publishBiasInitStatus(bias_sample, filtered_bias_logged, bias_delta, sample_time); + + if (bias_delta <= getBiasAveragingThreshold()) { + if (_bias.stable_delta_count < UINT8_MAX) { + ++_bias.stable_delta_count; + } + + } else { + _bias.stable_delta_count = 0; + } + + const hrt_abstime min_averaging_time_us = static_cast( + kInitialBiasLpfMinTimeFactor * kInitialBiasLpfTimeConstantS * 1e6f); + const bool min_time_elapsed = (sample_time >= _bias.averaging_start_time) + && ((sample_time - _bias.averaging_start_time) >= min_averaging_time_us); + const bool stable = (_bias.stable_delta_count >= kRequiredStableBiasDeltas) && min_time_elapsed; + const bool timed_out = (sample_time >= _bias.averaging_start_time) + && ((sample_time - _bias.averaging_start_time) >= getBiasAveragingTimeoutUs()); + + return stable || timed_out; +} + +void VTEPosition::resetBiasAveraging() +{ + _bias.averaging_active = false; + _bias.stable_delta_count = 0; + _bias.averaging_start_time = 0; + _bias.last_sample_time = 0; + _bias.initial_lpf.reset(Vector3f{}); +} + +void VTEPosition::activateBiasEstimate(const Vector3f &initial_position, const Vector3f &initial_bias) +{ + const float pos_var = fmaxf(_param_vte_pos_unc_in.get(), kMinVariance); + const float bias_var = fmaxf(_param_vte_bias_unc_in.get(), kMinVariance); + + for (int axis = 0; axis < vtest::Axis::size; ++axis) { + KF_position &filter = _target_est_pos[axis]; + EstimatorState state = filter.getState(); + state(vtest::State::bias) = initial_bias(axis); + state(vtest::State::pos_rel) = initial_position(axis); + filter.setState(state); + + EstimatorState state_var = filter.getStateCovarianceDiag(); + state_var(vtest::State::bias) = bias_var; + state_var(vtest::State::pos_rel) = pos_var; + filter.setStateCovarianceDiag(state_var); + + // Bias initialization is a state reset: restart OOSM history to avoid mixing pre/post-reset states. + filter.resetHistory(); + } + + PX4_DEBUG("Rel pos init %.2f %.2f %.2f", (double)initial_position(vtest::Axis::x), + (double)initial_position(vtest::Axis::y), (double)initial_position(vtest::Axis::z)); + + PX4_DEBUG("GNSS bias init %.2f %.2f %.2f", (double)initial_bias(vtest::Axis::x), + (double)initial_bias(vtest::Axis::y), (double)initial_bias(vtest::Axis::z)); + + _bias.set = true; + _pre_bias_reference = PreBiasReference::kUnknown; + resetBiasAveraging(); +} + +void VTEPosition::publishBiasInitStatus(const Vector3f &raw_bias, const Vector3f &filtered_bias, + const float raw_bias_delta_norm, const hrt_abstime sample_time) +{ + vte_bias_init_status_s status{}; + status.timestamp = sample_time; + status.raw_bias[0] = raw_bias(vtest::Axis::x); + status.raw_bias[1] = raw_bias(vtest::Axis::y); + status.raw_bias[2] = raw_bias(vtest::Axis::z); + status.filtered_bias[0] = filtered_bias(vtest::Axis::x); + status.filtered_bias[1] = filtered_bias(vtest::Axis::y); + status.filtered_bias[2] = filtered_bias(vtest::Axis::z); + status.delta_norm = raw_bias_delta_norm; + _vte_bias_init_status_pub.publish(status); +} + +bool VTEPosition::fuseActiveMeasurements(const matrix::Vector3f &vehicle_acc_ned, ObsValidMaskU &fusion_mask, + const TargetObs observations[kObsTypeCount]) +{ + const bool gnss_ready = !shouldBlockGnssFusionUntilBiasReady(); + const bool vision_ready = !shouldBlockVisionFusionUntilBiasReady(); + bool position_fused = false; + + if (fusion_mask.flags.fuse_target_gps_pos && gnss_ready) { + const TargetObs &obs = observations[obsIndex(ObsType::kTargetGpsPos)]; + + if ((obs.timestamp != 0) && fuseMeas(vehicle_acc_ned, obs)) { + position_fused = true; + + if (!_bias.set) { + _pre_bias_reference = PreBiasReference::kGnss; + } + } + } + + if (fusion_mask.flags.fuse_mission_pos && gnss_ready) { + const TargetObs &obs = observations[obsIndex(ObsType::kMissionGpsPos)]; + + if ((obs.timestamp != 0) && fuseMeas(vehicle_acc_ned, obs)) { + position_fused = true; + + if (!_bias.set) { + _pre_bias_reference = PreBiasReference::kGnss; + } + } + } + + if (fusion_mask.flags.fuse_vision && vision_ready) { + const TargetObs &obs = observations[obsIndex(ObsType::kFiducialMarker)]; + + if ((obs.timestamp != 0) && fuseMeas(vehicle_acc_ned, obs)) { + position_fused = true; + + if (!_bias.set) { + _pre_bias_reference = PreBiasReference::kVision; + } + + _last_relative_meas_fused_time = nowUs(); + } + } + + if (fusion_mask.flags.fuse_uav_gps_vel) { + const TargetObs &obs = observations[obsIndex(ObsType::kUavGpsVel)]; + + if (obs.timestamp != 0) { + fuseMeas(vehicle_acc_ned, obs); + } + } + +#if defined(CONFIG_VTEST_MOVING) + + if (fusion_mask.flags.fuse_target_gps_vel) { + const TargetObs &obs = observations[obsIndex(ObsType::kTargetGpsVel)]; + + if (obs.timestamp != 0) { + fuseMeas(vehicle_acc_ned, obs); + } + } + +#endif // CONFIG_VTEST_MOVING + + return position_fused; +} + +/*Vision observation: [rx, ry, rz]*/ +bool VTEPosition::processObsVision(TargetObs &obs) +{ + fiducial_marker_pos_report_s report; + + if (!_fiducial_marker_pos_report_sub.update(&report) || !isVisionDataValid(report)) { + return false; + } + + const matrix::Quaternionf quat_att(report.q); + const Vector3f vision_rel(report.rel_pos); + const Vector3f vision_ned = quat_att.rotateVector(vision_rel); + const float min_ev_pos_var = sq(fmaxf(_param_vte_ev_pos_noise.get(), kMinObservationNoise)); + + // Rotate covariance matrix to vc-NED + const SquareMatrix cov_mat = diag(Vector3f( + fmaxf(report.cov_rel_pos[0], min_ev_pos_var), + fmaxf(report.cov_rel_pos[1], min_ev_pos_var), + fmaxf(report.cov_rel_pos[2], min_ev_pos_var))); + const matrix::Dcmf r_att = matrix::Dcm(quat_att); + const SquareMatrix cov_rotated = r_att * cov_mat * r_att.transpose(); + + // Relative position + if (!vision_ned.isAllFinite()) { + if (shouldEmitWarning(_vision_pos_warn_last)) { + PX4_WARN("VTE: Vision position NED is corrupt!"); + } + + return false; + } + + obs.timestamp = report.timestamp_sample; + + obs.type = ObsType::kFiducialMarker; + obs.updated(vtest::Axis::x) = true; + obs.updated(vtest::Axis::y) = true; + obs.updated(vtest::Axis::z) = true; + + // Assume noise correlation negligible: + obs.meas_h_xyz(vtest::Axis::x, vtest::State::pos_rel) = 1; + obs.meas_h_xyz(vtest::Axis::y, vtest::State::pos_rel) = 1; + obs.meas_h_xyz(vtest::Axis::z, vtest::State::pos_rel) = 1; + + obs.meas_xyz = vision_ned; + + // Assume off diag elements ~ 0 + obs.meas_unc_xyz(vtest::Axis::x) = cov_rotated(vtest::Axis::x, vtest::Axis::x); + obs.meas_unc_xyz(vtest::Axis::y) = cov_rotated(vtest::Axis::y, vtest::Axis::y); + obs.meas_unc_xyz(vtest::Axis::z) = cov_rotated(vtest::Axis::z, vtest::Axis::z); + + return true; +} + +/*Drone GNSS velocity observation: [vel_uav_x, vel_uav_y ,vel_uav_z]*/ +bool VTEPosition::processObsGNSSVelUav(TargetObs &obs) const +{ + Vector3f vel_uav_ned{}; + + if (!getOffsetUavVel(_uav_gps_vel.timestamp, vel_uav_ned)) { + return false; + } + + const float min_gps_vel_var = getMinGpsVelVar(); + + obs.meas_xyz = vel_uav_ned; + + obs.meas_h_xyz(vtest::Axis::x, vtest::State::vel_uav) = 1; + obs.meas_h_xyz(vtest::Axis::y, vtest::State::vel_uav) = 1; + obs.meas_h_xyz(vtest::Axis::z, vtest::State::vel_uav) = 1; + + const float unc = fmaxf(sq(_uav_gps_vel.uncertainty), min_gps_vel_var); + obs.meas_unc_xyz(vtest::Axis::x) = unc; + obs.meas_unc_xyz(vtest::Axis::y) = unc; + obs.meas_unc_xyz(vtest::Axis::z) = unc; + + obs.timestamp = _uav_gps_vel.timestamp; + + obs.type = ObsType::kUavGpsVel; + + obs.updated(vtest::Axis::x) = true; + obs.updated(vtest::Axis::y) = true; + obs.updated(vtest::Axis::z) = true; + + return true; +} + +#if defined(CONFIG_VTEST_MOVING) + +/*Target GNSS velocity observation: [r_dotx, r_doty, r_dotz]*/ +bool VTEPosition::processObsGNSSVelTarget(const target_gnss_s &target_gnss, TargetObs &obs) const +{ + // If the target is moving, the relative velocity is expressed as the drone velocity minus the target velocity. + obs.meas_xyz(vtest::Axis::x) = target_gnss.vel_n_m_s; + obs.meas_xyz(vtest::Axis::y) = target_gnss.vel_e_m_s; + obs.meas_xyz(vtest::Axis::z) = target_gnss.vel_d_m_s; + + const float unc = fmaxf(sq(target_gnss.s_acc_m_s), getMinGpsVelVar()); + + obs.meas_unc_xyz(vtest::Axis::x) = unc; + obs.meas_unc_xyz(vtest::Axis::y) = unc; + obs.meas_unc_xyz(vtest::Axis::z) = unc; + + obs.meas_h_xyz(vtest::Axis::x, vtest::State::vel_target) = 1; + obs.meas_h_xyz(vtest::Axis::y, vtest::State::vel_target) = 1; + obs.meas_h_xyz(vtest::Axis::z, vtest::State::vel_target) = 1; + + obs.timestamp = target_gnss.timestamp_sample; + + obs.type = ObsType::kTargetGpsVel; + + obs.updated(vtest::Axis::x) = true; + obs.updated(vtest::Axis::y) = true; + obs.updated(vtest::Axis::z) = true; + + return true; +} + +#endif // CONFIG_VTEST_MOVING + +/*Target GNSS mission observation: [rx + bx, ry + by, rz + bz]*/ +bool VTEPosition::processObsGNSSPosMission(TargetObs &obs) +{ + // Obtain GPS relative measurements in NED as target_global - uav_gps_global followed by global2local transformation + Vector3f gps_relative_pos; + get_vector_to_next_waypoint(_uav_gps_position.lat_deg, _uav_gps_position.lon_deg, + _mission_land_position.lat_deg, _mission_land_position.lon_deg, + &gps_relative_pos(0), &gps_relative_pos(1)); + + // Down direction (if the drone is above the target, the relative position is positive) + gps_relative_pos(2) = _uav_gps_position.alt_m - _mission_land_position.alt_m; + + // Offset gps relative position to the center of mass: + if (_gps_pos_is_offset) { + + if (!_gps_pos_offset_ned.valid + || !isTimeDifferenceWithin(_gps_pos_offset_ned.timestamp, _uav_gps_position.timestamp, _meas_updated_timeout_us)) { + return false; + } + + gps_relative_pos += _gps_pos_offset_ned.xyz; + } + + const float min_gps_pos_var = getMinGpsPosVar(); + const float gps_unc_horizontal = fmaxf(sq(_uav_gps_position.eph), min_gps_pos_var); + const float gps_unc_vertical = fmaxf(sq(_uav_gps_position.epv), min_gps_pos_var); + + if (!gps_relative_pos.isAllFinite() || !PX4_ISFINITE(gps_unc_horizontal) || !PX4_ISFINITE(gps_unc_vertical)) { + if (shouldEmitWarning(_mission_pos_warn_last)) { + PX4_WARN("Mission position observation is invalid!"); + } + + return false; + } + + // GPS already in NED, no rotation required. + // Obs: [pos_rel + bias] + obs.meas_h_xyz(vtest::Axis::x, vtest::State::pos_rel) = 1; + obs.meas_h_xyz(vtest::Axis::y, vtest::State::pos_rel) = 1; + obs.meas_h_xyz(vtest::Axis::z, vtest::State::pos_rel) = 1; + + obs.timestamp = _uav_gps_position.timestamp; + + obs.meas_xyz = gps_relative_pos; + + obs.meas_unc_xyz(vtest::Axis::x) = gps_unc_horizontal; + obs.meas_unc_xyz(vtest::Axis::y) = gps_unc_horizontal; + obs.meas_unc_xyz(vtest::Axis::z) = gps_unc_vertical; + + if (_bias.set) { + obs.meas_h_xyz(vtest::Axis::x, vtest::State::bias) = 1; + obs.meas_h_xyz(vtest::Axis::y, vtest::State::bias) = 1; + obs.meas_h_xyz(vtest::Axis::z, vtest::State::bias) = 1; + } + + obs.type = ObsType::kMissionGpsPos; + + obs.updated(vtest::Axis::x) = true; + obs.updated(vtest::Axis::y) = true; + obs.updated(vtest::Axis::z) = true; + + // Keep track of the latest GNSS-relative position used for bias initialization. + // Mission and target GPS position fusion are mutually exclusive, so the mission + // path can refresh this cache unconditionally. + _pos_rel_gnss.timestamp = obs.timestamp; + _pos_rel_gnss.valid = gps_relative_pos.isAllFinite(); + _pos_rel_gnss.xyz = gps_relative_pos; + + return true; +} + +/*Target GNSS observation: [rx + bx, ry + by, rz + bz]*/ +bool VTEPosition::processObsGNSSPosTarget(const target_gnss_s &target_gnss, TargetObs &obs) +{ + const int64_t time_diff_us = signedTimeDiffUs(target_gnss.timestamp_sample, _uav_gps_position.timestamp); + const float dt_sync_us = fabsf(static_cast(time_diff_us)); + + if (dt_sync_us > _meas_recent_timeout_us) { + PX4_DEBUG("Time diff between UAV GNSS and target GNSS too high: %.2f [ms] > timeout: %.2f [ms]", + static_cast(dt_sync_us * kMicrosecondsToMilliseconds), + static_cast(_meas_recent_timeout_us * kMicrosecondsToMilliseconds)); + return false; + } + + double uav_lat_deg = _uav_gps_position.lat_deg; + double uav_lon_deg = _uav_gps_position.lon_deg; + float uav_alt_m = _uav_gps_position.alt_m; + + const float dt_sync_s = static_cast(time_diff_us) * kMicrosecondsToSeconds; + const float dt_sync_s_abs = fabsf(dt_sync_s); + bool uav_position_interpolated = false; + + // Compensate UAV motion during the latency interval + static constexpr float kGnssSyncInterpolationMinTimeS = 0.1f; + + Vector3f uav_vel_ned{}; + + if ((dt_sync_s_abs > kGnssSyncInterpolationMinTimeS) + && getOffsetUavVel(_uav_gps_position.timestamp, uav_vel_ned)) { + + const float delta_n = uav_vel_ned(vtest::Axis::x) * dt_sync_s; + const float delta_e = uav_vel_ned(vtest::Axis::y) * dt_sync_s; + + double lat_res = uav_lat_deg; + double lon_res = uav_lon_deg; + add_vector_to_global_position(uav_lat_deg, uav_lon_deg, delta_n, delta_e, &lat_res, &lon_res); + uav_lat_deg = lat_res; + uav_lon_deg = lon_res; + uav_alt_m = _uav_gps_position.alt_m - uav_vel_ned(vtest::Axis::z) * dt_sync_s; + uav_position_interpolated = true; + } + + // Obtain GPS relative measurements in NED as target_global - uav_gps_global followed by global2local transformation + Vector3f gps_relative_pos; + get_vector_to_next_waypoint(uav_lat_deg, uav_lon_deg, + target_gnss.latitude_deg, target_gnss.longitude_deg, + &gps_relative_pos(0), &gps_relative_pos(1)); + + // Down direction (if the drone is above the target, the relative position is positive) + gps_relative_pos(2) = uav_alt_m - target_gnss.altitude_msl_m; + + // Offset gps relative position to the center of mass: + if (_gps_pos_is_offset) { + if (!_gps_pos_offset_ned.valid + || !isTimeDifferenceWithin(_gps_pos_offset_ned.timestamp, _uav_gps_position.timestamp, _meas_updated_timeout_us)) { + + return false; + } + + gps_relative_pos += _gps_pos_offset_ned.xyz; + } + + // Var(aX - bY) = a^2 Var(X) + b^2Var(Y) - 2ab Cov(X,Y) + const float propagation_unc = uav_position_interpolated + ? sq(_uav_gps_vel.uncertainty * dt_sync_s_abs) : 0.f; + const float min_gps_pos_var = getMinGpsPosVar(); + const float gps_unc_horizontal = fmaxf(sq(_uav_gps_position.eph), min_gps_pos_var) + + fmaxf(sq(target_gnss.eph), min_gps_pos_var) + + propagation_unc; + const float gps_unc_vertical = fmaxf(sq(_uav_gps_position.epv), min_gps_pos_var) + + fmaxf(sq(target_gnss.epv), min_gps_pos_var) + + propagation_unc; + + if (!gps_relative_pos.isAllFinite() || !PX4_ISFINITE(gps_unc_horizontal) || !PX4_ISFINITE(gps_unc_vertical)) { + if (shouldEmitWarning(_target_gps_pos_warn_last)) { + PX4_WARN("Target GNSS position observation is invalid!"); + } + + return false; + } + + // GPS already in NED, no rotation required. + // Obs: [pos_rel + bias] + obs.meas_h_xyz(vtest::Axis::x, vtest::State::pos_rel) = 1; + obs.meas_h_xyz(vtest::Axis::y, vtest::State::pos_rel) = 1; + obs.meas_h_xyz(vtest::Axis::z, vtest::State::pos_rel) = 1; + + if (_bias.set) { + obs.meas_h_xyz(vtest::Axis::x, vtest::State::bias) = 1; + obs.meas_h_xyz(vtest::Axis::y, vtest::State::bias) = 1; + obs.meas_h_xyz(vtest::Axis::z, vtest::State::bias) = 1; + } + + obs.timestamp = target_gnss.timestamp_sample; + + obs.meas_xyz = gps_relative_pos; + + obs.meas_unc_xyz(vtest::Axis::x) = gps_unc_horizontal; + obs.meas_unc_xyz(vtest::Axis::y) = gps_unc_horizontal; + obs.meas_unc_xyz(vtest::Axis::z) = gps_unc_vertical; + + obs.type = ObsType::kTargetGpsPos; + + obs.updated(vtest::Axis::x) = true; + obs.updated(vtest::Axis::y) = true; + obs.updated(vtest::Axis::z) = true; + + // Keep track of the latest GNSS relative position used for bias initialization. + _pos_rel_gnss.timestamp = obs.timestamp; + _pos_rel_gnss.valid = gps_relative_pos.isAllFinite(); + _pos_rel_gnss.xyz = gps_relative_pos; + + return true; +} + +bool VTEPosition::fuseMeas(const Vector3f &vehicle_acc_ned, const TargetObs &target_obs) +{ + perf_begin(_vte_update_perf); + const float nis_threshold = fmaxf(_param_vte_pos_nis_thre.get(), kMinNisThreshold); + + vte_aid_source3d_s target_innov = {}; + target_innov.timestamp_sample = target_obs.timestamp; + target_innov.timestamp = nowUs(); + target_innov.time_last_predict = _last_predict; + target_innov.time_since_meas_ms = static_cast(signedTimeDiffUs(_last_predict, target_obs.timestamp)) + * kMicrosecondsToMilliseconds; + + bool any_axis_fused = false; + uint8_t history_steps = 0; + + for (int j = 0; j < vtest::Axis::size; j++) { + + if (!target_obs.updated(j)) { + target_innov.fusion_status[j] = static_cast(FusionStatus::STATUS_IDLE); + continue; // nothing to do for this axis + } + + const KF_position::ScalarMeas meas_input{target_obs.timestamp, target_obs.meas_xyz(j), + target_obs.meas_unc_xyz(j), target_obs.meas_h_xyz.row(j)}; + + target_innov.observation[j] = meas_input.val; + target_innov.observation_variance[j] = meas_input.unc; + + perf_begin(_vte_fusion_perf); + const FusionResult result = _target_est_pos[j].fuseScalarAtTime(meas_input, _last_predict, nis_threshold); + perf_end(_vte_fusion_perf); + + target_innov.innovation[j] = result.innov; + target_innov.innovation_variance[j] = result.innov_var; + target_innov.test_ratio[j] = result.test_ratio; + target_innov.fusion_status[j] = static_cast(result.status); + any_axis_fused |= (result.status == FusionStatus::STATUS_FUSED_CURRENT || + result.status == FusionStatus::STATUS_FUSED_OOSM); + + if (result.status == FusionStatus::STATUS_FUSED_OOSM) { + history_steps = math::max(result.history_steps, history_steps); + } + } + + target_innov.history_steps = history_steps; + + perf_end(_vte_update_perf); + publishInnov(target_innov, target_obs.type); + + return any_axis_fused; +} + +void VTEPosition::publishInnov(const vte_aid_source3d_s &target_innov, const ObsType type) +{ + // Publish innovations + switch (type) { + case ObsType::kTargetGpsPos: + _vte_aid_gps_pos_target_pub.publish(target_innov); + break; + + case ObsType::kMissionGpsPos: + _vte_aid_gps_pos_mission_pub.publish(target_innov); + break; + + case ObsType::kUavGpsVel: + _vte_aid_gps_vel_uav_pub.publish(target_innov); + break; + + case ObsType::kTargetGpsVel: + _vte_aid_gps_vel_target_pub.publish(target_innov); + break; + + case ObsType::kFiducialMarker: + _vte_aid_fiducial_marker_pub.publish(target_innov); + break; + + case ObsType::kTypeCount: + break; + } +} + +void VTEPosition::publishTarget() +{ + _vte_state = {}; + _target_pose = {}; + + _target_pose.timestamp = _last_predict; + _vte_state.timestamp = _last_predict; + +#if defined(CONFIG_VTEST_MOVING) + _target_pose.is_static = false; +#else + _target_pose.is_static = true; +#endif // CONFIG_VTEST_MOVING + + // Get state + const EstimatorState &state_x = _target_est_pos[vtest::Axis::x].getState(); + const EstimatorState &state_y = _target_est_pos[vtest::Axis::y].getState(); + const EstimatorState &state_z = _target_est_pos[vtest::Axis::z].getState(); + + const EstimatorState state_var_x = _target_est_pos[vtest::Axis::x].getStateCovarianceDiag(); + const EstimatorState state_var_y = _target_est_pos[vtest::Axis::y].getStateCovarianceDiag(); + const EstimatorState state_var_z = _target_est_pos[vtest::Axis::z].getStateCovarianceDiag(); + + // Fill target relative pose + _target_pose.x_rel = state_x(vtest::State::pos_rel); + _target_pose.y_rel = state_y(vtest::State::pos_rel); + _target_pose.z_rel = state_z(vtest::State::pos_rel); + + _target_pose.cov_x_rel = state_var_x(vtest::State::pos_rel); + _target_pose.cov_y_rel = state_var_y(vtest::State::pos_rel); + _target_pose.cov_z_rel = state_var_z(vtest::State::pos_rel); + + // Fill target relative velocity + _target_pose.vx_rel = -state_x(vtest::State::vel_uav); + _target_pose.vy_rel = -state_y(vtest::State::vel_uav); + _target_pose.vz_rel = -state_z(vtest::State::vel_uav); + + _target_pose.cov_vx_rel = state_var_x(vtest::State::vel_uav); + _target_pose.cov_vy_rel = state_var_y(vtest::State::vel_uav); + _target_pose.cov_vz_rel = state_var_z(vtest::State::vel_uav); + +#if defined(CONFIG_VTEST_MOVING) + const EstimatorStateCovariance &state_cov_x = _target_est_pos[vtest::Axis::x].getStateCovariance(); + const EstimatorStateCovariance &state_cov_y = _target_est_pos[vtest::Axis::y].getStateCovariance(); + const EstimatorStateCovariance &state_cov_z = _target_est_pos[vtest::Axis::z].getStateCovariance(); + + // If target is moving, relative velocity = vel_target - vel_uav + _target_pose.vx_rel += state_x(vtest::State::vel_target); + _target_pose.vy_rel += state_y(vtest::State::vel_target); + _target_pose.vz_rel += state_z(vtest::State::vel_target); + + // Var(vel_target - vel_uav) = Var(vel_target) + Var(vel_uav) - 2 Cov(vel_uav, vel_target) + _target_pose.cov_vx_rel += state_var_x(vtest::State::vel_target) + - 2.f * state_cov_x(vtest::State::vel_uav, vtest::State::vel_target); + _target_pose.cov_vy_rel += state_var_y(vtest::State::vel_target) + - 2.f * state_cov_y(vtest::State::vel_uav, vtest::State::vel_target); + _target_pose.cov_vz_rel += state_var_z(vtest::State::vel_target) + - 2.f * state_cov_z(vtest::State::vel_uav, vtest::State::vel_target); + +#endif // CONFIG_VTEST_MOVING + + // Fill vision target estimator state + _vte_state.rel_pos[0] = _target_pose.x_rel; + _vte_state.rel_pos[1] = _target_pose.y_rel; + _vte_state.rel_pos[2] = _target_pose.z_rel; + + _vte_state.cov_rel_pos[0] = _target_pose.cov_x_rel; + _vte_state.cov_rel_pos[1] = _target_pose.cov_y_rel; + _vte_state.cov_rel_pos[2] = _target_pose.cov_z_rel; + + // Fill uav velocity + _vte_state.vel_uav[0] = state_x(vtest::State::vel_uav); + _vte_state.vel_uav[1] = state_y(vtest::State::vel_uav); + _vte_state.vel_uav[2] = state_z(vtest::State::vel_uav); + + _vte_state.cov_vel_uav[0] = state_var_x(vtest::State::vel_uav); + _vte_state.cov_vel_uav[1] = state_var_y(vtest::State::vel_uav); + _vte_state.cov_vel_uav[2] = state_var_z(vtest::State::vel_uav); + + _vte_state.bias[0] = state_x(vtest::State::bias); + _vte_state.bias[1] = state_y(vtest::State::bias); + _vte_state.bias[2] = state_z(vtest::State::bias); + + _vte_state.cov_bias[0] = state_var_x(vtest::State::bias); + _vte_state.cov_bias[1] = state_var_y(vtest::State::bias); + _vte_state.cov_bias[2] = state_var_z(vtest::State::bias); + +#if defined(CONFIG_VTEST_MOVING) + + _vte_state.vel_target[0] = state_x(vtest::State::vel_target); + _vte_state.vel_target[1] = state_y(vtest::State::vel_target); + _vte_state.vel_target[2] = state_z(vtest::State::vel_target); + + _vte_state.cov_vel_target[0] = state_var_x(vtest::State::vel_target); + _vte_state.cov_vel_target[1] = state_var_y(vtest::State::vel_target); + _vte_state.cov_vel_target[2] = state_var_z(vtest::State::vel_target); + + _vte_state.acc_target[0] = state_x(vtest::State::acc_target); + _vte_state.acc_target[1] = state_y(vtest::State::acc_target); + _vte_state.acc_target[2] = state_z(vtest::State::acc_target); + + _vte_state.cov_acc_target[0] = state_var_x(vtest::State::acc_target); + _vte_state.cov_acc_target[1] = state_var_y(vtest::State::acc_target); + _vte_state.cov_acc_target[2] = state_var_z(vtest::State::acc_target); + +#endif // CONFIG_VTEST_MOVING + + const Vector3f rel_pos{_target_pose.x_rel, _target_pose.y_rel, _target_pose.z_rel}; + const Vector3f rel_vel{_target_pose.vx_rel, _target_pose.vy_rel, _target_pose.vz_rel}; + const bool relative_position_recent = !hasTimedOut(_last_update, _target_valid_timeout_us); + _target_pose.rel_pos_valid = relative_position_recent && rel_pos.isAllFinite(); + _target_pose.rel_vel_valid = _target_pose.rel_pos_valid && rel_vel.isAllFinite(); // Velocity cannot be valid if position invalid + + // EKF2 auxiliary velocity aiding must only use velocity backed by a recent relative + // measurement (vision). GNSS/mission position can keep the target estimate valid, but it is not a + // relative measurement and therefore must not enable this aiding path by itself. + const hrt_abstime now = nowUs(); + const bool recent_relative_fusion = (_last_relative_meas_fused_time != 0) + && (now >= _last_relative_meas_fused_time) + && ((now - _last_relative_meas_fused_time) < _meas_recent_timeout_us); + _target_pose.rel_vel_ekf2_valid = _target_pose.is_static && _target_pose.rel_vel_valid && recent_relative_fusion; + + _vte_state.rel_pos_valid = _target_pose.rel_pos_valid; + _vte_state.rel_vel_valid = _target_pose.rel_vel_valid; + + // Prec land does not check _target_pose.abs_pos_valid. Only send the target if abs pose valid. + if (_local_position.valid && _target_pose.rel_pos_valid) { + _target_pose.x_abs = _target_pose.x_rel + _local_position.xyz(0); + _target_pose.y_abs = _target_pose.y_rel + _local_position.xyz(1); + _target_pose.z_abs = _target_pose.z_rel + _local_position.xyz(2); + _target_pose.abs_pos_valid = true; + + _target_pose_pub.publish(_target_pose); + + } + + _target_estimator_state_pub.publish(_vte_state); +} + +void VTEPosition::print_status() const +{ + const auto yes_no = [](const bool value) { return value ? "yes" : "no"; }; + const auto age_s = [](const hrt_abstime timestamp) -> double { + if (timestamp == 0) + { + return -1.; + } + + return signedTimeDiffUs(nowUs(), timestamp) * 1e-6; + }; + const auto pre_bias_reference_name = [this]() { + switch (_pre_bias_reference) { + case PreBiasReference::kVision: return "vision"; + + case PreBiasReference::kGnss: return "gnss"; + + default: return "unknown"; + } + }; + + const bool relative_position_valid = _estimator_initialized && !hasTimedOut(_last_update, _target_valid_timeout_us); + + PX4_INFO(" position state: initialized: %s, valid: %s, last predict/update age: %.3f / %.3f s", + yes_no(_estimator_initialized), yes_no(relative_position_valid), age_s(_last_predict), age_s(_last_update)); + PX4_INFO(" rel pos/vel/ekf2 vel valid: %s / %s / %s", + yes_no(_target_pose.rel_pos_valid), + yes_no(_target_pose.rel_vel_valid), + yes_no(_target_pose.rel_vel_ekf2_valid)); + + if (_estimator_initialized) { + const EstimatorState &state_x = _target_est_pos[vtest::Axis::x].getState(); + const EstimatorState &state_y = _target_est_pos[vtest::Axis::y].getState(); + const EstimatorState &state_z = _target_est_pos[vtest::Axis::z].getState(); + + PX4_INFO(" rel pos: [%.3f, %.3f, %.3f]", + (double)state_x(vtest::State::pos_rel), + (double)state_y(vtest::State::pos_rel), + (double)state_z(vtest::State::pos_rel)); + PX4_INFO(" gnss bias: [%.3f, %.3f, %.3f]", + (double)state_x(vtest::State::bias), + (double)state_y(vtest::State::bias), + (double)state_z(vtest::State::bias)); + +#if defined(CONFIG_VTEST_MOVING) + PX4_INFO(" target vel: [%.3f, %.3f, %.3f]", + (double)state_x(vtest::State::vel_target), + (double)state_y(vtest::State::vel_target), + (double)state_z(vtest::State::vel_target)); + PX4_INFO(" target acc: [%.3f, %.3f, %.3f]", + (double)state_x(vtest::State::acc_target), + (double)state_y(vtest::State::acc_target), + (double)state_z(vtest::State::acc_target)); +#endif // CONFIG_VTEST_MOVING + } + + PX4_INFO(" bias set: %s, averaging: %s, pre-bias reference: %s", + yes_no(_bias.set), + yes_no(_bias.averaging_active), + pre_bias_reference_name()); + PX4_INFO(" position inputs: local pos: %s age %.3f s, local vel: %s age %.3f s", + yes_no(_local_position.valid), age_s(_local_position.timestamp), + yes_no(_local_velocity.valid), age_s(_local_velocity.timestamp)); + PX4_INFO(" uav gps pos: %s age %.3f s, uav gps vel: %s age %.3f s, mission pos: %s", + yes_no(_uav_gps_position.valid), age_s(_uav_gps_position.timestamp), + yes_no(_uav_gps_vel.valid), age_s(_uav_gps_vel.timestamp), + yes_no(_mission_land_position.valid)); + PX4_INFO(" gnss rel pos: %s age %.3f s, gps pos offset: %s age %.3f s, vel offset: %s age %.3f s", + yes_no(_pos_rel_gnss.valid), age_s(_pos_rel_gnss.timestamp), + yes_no(_gps_pos_is_offset && _gps_pos_offset_ned.valid), age_s(_gps_pos_offset_ned.timestamp), + yes_no(_velocity_offset_ned.valid), age_s(_velocity_offset_ned.timestamp)); + +#if defined(CONFIG_VTEST_MOVING) + PX4_INFO(" target gps vel: %s age %.3f s", + yes_no(_target_gps_vel.valid), age_s(_target_gps_vel.timestamp)); +#endif // CONFIG_VTEST_MOVING +} + +void VTEPosition::checkMeasurementInputs() +{ + // Make sure fast topics are up to date. + _local_position.valid = _local_position.valid && isMeasUpdated(_local_position.timestamp); + _local_velocity.valid = _local_velocity.valid && isMeasUpdated(_local_velocity.timestamp); + _velocity_offset_ned.valid = _velocity_offset_ned.valid && isMeasUpdated(_velocity_offset_ned.timestamp); + _gps_pos_offset_ned.valid = _gps_pos_offset_ned.valid && isMeasUpdated(_gps_pos_offset_ned.timestamp); + + // Slower observation topics are valid if recent +#if defined(CONFIG_VTEST_MOVING) + _target_gps_vel.valid = _target_gps_vel.valid && isMeasRecent(_target_gps_vel.timestamp); +#endif // CONFIG_VTEST_MOVING + _pos_rel_gnss.valid = _pos_rel_gnss.valid && isMeasRecent(_pos_rel_gnss.timestamp); + _uav_gps_vel.valid = _uav_gps_vel.valid && isMeasRecent(_uav_gps_vel.timestamp); +} + +void VTEPosition::setGpsPosOffset(const matrix::Vector3f &xyz, const bool gps_is_offset) +{ + _gps_pos_is_offset = gps_is_offset; + _gps_pos_offset_ned.xyz = xyz; + _gps_pos_offset_ned.valid = xyz.isAllFinite(); + _gps_pos_offset_ned.timestamp = nowUs(); +} + +void VTEPosition::setVelOffset(const matrix::Vector3f &xyz) +{ + _velocity_offset_ned.xyz = xyz; + _velocity_offset_ned.valid = xyz.isAllFinite(); + _velocity_offset_ned.timestamp = nowUs(); +} + +void VTEPosition::setLocalVelocity(const matrix::Vector3f &vel_xyz, const bool vel_valid, hrt_abstime timestamp) +{ + _local_velocity.xyz = vel_xyz; + _local_velocity.valid = vel_valid && vel_xyz.isAllFinite() && isMeasUpdated(timestamp); + _local_velocity.timestamp = timestamp; +} + +void VTEPosition::setLocalPosition(const matrix::Vector3f &xyz, const bool pos_valid, hrt_abstime timestamp) +{ + _local_position.xyz = xyz; + _local_position.valid = pos_valid && xyz.isAllFinite() && isMeasUpdated(timestamp); + _local_position.timestamp = timestamp; +} + +void VTEPosition::setMissionPosition(const double lat_deg, const double lon_deg, const float alt_m) +{ + // Cache the mission waypoint independently from the current aid mask so the caller + // can provide it before mission aiding is enabled or while the mask is toggled. + _mission_land_position.lat_deg = lat_deg; + _mission_land_position.lon_deg = lon_deg; + _mission_land_position.alt_m = alt_m; + _mission_land_position.valid = isLatLonAltValid(_mission_land_position.lat_deg, _mission_land_position.lon_deg, + _mission_land_position.alt_m, "Mission position ", &_mission_pos_warn_last); + + if (_mission_land_position.valid) { + PX4_INFO("Mission position lat %.8f, lon %.8f [deg], alt %.1f [m]", lat_deg, + lon_deg, (double)(alt_m)); + + } else if (shouldEmitWarning(_mission_pos_status_warn_last)) { + PX4_WARN("Mission position not used because not valid"); + } +} + +void VTEPosition::updateParams() +{ + parameter_update_s pupdate; + _parameter_update_sub.copy(&pupdate); + + ModuleParams::updateParams(); +} + +float VTEPosition::getMinGpsVelVar() const +{ + return sq(fmaxf(_param_vte_gps_vel_noise.get(), kMinObservationNoise)); +} + +float VTEPosition::getMinGpsPosVar() const +{ + return sq(fmaxf(_param_vte_gps_pos_noise.get(), kMinObservationNoise)); +} + +float VTEPosition::getBiasAveragingThreshold() const +{ + return fmaxf(_param_vte_bias_avg_thr.get(), 0.f); +} + +hrt_abstime VTEPosition::getBiasAveragingTimeoutUs() const +{ + const float seconds = fmaxf(_param_vte_bias_avg_tout.get(), 0.f); + const float microseconds = fminf(seconds * 1e6f, static_cast(UINT32_MAX)); + return static_cast(microseconds); +} + +bool VTEPosition::isLatLonAltValid(double lat_deg, double lon_deg, float alt_m, const char *who, + hrt_abstime *warn_last) +{ + // all finite + if (!PX4_ISFINITE(lat_deg) || !PX4_ISFINITE(lon_deg) || !PX4_ISFINITE(alt_m)) { + if (who && (!warn_last || shouldEmitWarning(*warn_last))) { + PX4_WARN("%s position not finite! lat: %.8f, lon: %.8f, alt: %.1f", + who, lat_deg, lon_deg, (double)alt_m); + } + + return false; + } + + // latitude/longitude within symmetric geographic ranges + if ((fabs(lat_deg) > kLatAbsMaxDeg) || (fabs(lon_deg) > kLonAbsMaxDeg)) { + if (who && (!warn_last || shouldEmitWarning(*warn_last))) { + PX4_WARN("%s lat/lon out of range! lat: %.8f, lon: %.8f", who, lat_deg, lon_deg); + } + + return false; + } + + // (0,0) sentinel is considered invalid + if ((fabs(lat_deg) < DBL_EPSILON) && (fabs(lon_deg) < DBL_EPSILON)) { + if (who && (!warn_last || shouldEmitWarning(*warn_last))) { + PX4_WARN("%s position near (0,0)!", who); + } + + return false; + } + + // altitude window + if ((alt_m < kAltMinM) || (alt_m > kAltMaxM)) { + if (who && (!warn_last || shouldEmitWarning(*warn_last))) { + PX4_WARN("%s altitude out of range! alt: %.1f [m] (limits: %.1f;%.1f)", + who, (double)alt_m, (double)kAltMinM, (double)kAltMaxM); + } + + return false; + } + + return true; +} + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/Position/VTEPosition.h b/src/modules/vision_target_estimator/Position/VTEPosition.h new file mode 100644 index 00000000000..faf44891dc0 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/VTEPosition.h @@ -0,0 +1,466 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VTEPosition.h + * @brief Estimate the state of a target by processing and fusing sensor data in + * a Kalman Filter. + * + * @author Jonas Perolini + * + */ + +#pragma once + +#include "../common.h" +#include "KF_position.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vision_target_estimator +{ + +class VTEPosition : public ModuleParams +{ +public: + VTEPosition(); + virtual ~VTEPosition(); + + /** + * Run the predict/update cycle once. Pulls in all new sensor samples, initializes the + * filter on the first viable set, fuses them in source-priority order, and publishes the state. + * @param acc_ned Latest UAV acceleration in NED, used as prediction input. + */ + void update(const matrix::Vector3f &acc_ned); + + /** Validate generated state sizes and prepare per-axis history buffers. Call once at startup. */ + bool init(); + + /** Drop the estimator state. Cached external inputs (local pos/vel, offsets) are preserved. */ + void resetFilter(); + + /** Cache the precision-land mission waypoint used to build the mission GNSS observation. */ + void setMissionPosition(double lat_deg, double lon_deg, float alt_m); + + /** Feed the latest EKF2 local NED velocity. Used for init and to compensate GNSS latency. */ + void setLocalVelocity(const matrix::Vector3f &vel_xyz, bool valid, hrt_abstime timestamp); + + /** Feed the latest EKF2 local NED position. Used to publish the absolute target pose. */ + void setLocalPosition(const matrix::Vector3f &xyz, bool valid, hrt_abstime timestamp); + + /** Configure the antenna→CoM position offset in NED. @p gps_is_offset gates its use. */ + void setGpsPosOffset(const matrix::Vector3f &xyz, bool gps_is_offset); + + /** Configure the antenna→CoM velocity offset in NED (e.g. yaw-rate * lever-arm). */ + void setVelOffset(const matrix::Vector3f &xyz); + + /** Timeout after which the whole filter is declared stale (see @c timedOut). */ + void setVteTimeout(hrt_abstime tout) { _vte_timeout_us = tout; } + + /** Maximum age for the published relative pose to be marked valid. */ + void setTargetValidTimeout(hrt_abstime tout) + { + _target_valid_timeout_us = tout; + } + + /** Maximum age for a raw observation to still be considered for fusion. */ + void setMeasRecentTimeout(hrt_abstime tout) + { + _meas_recent_timeout_us = tout; + } + + /** Maximum age for cached inputs (offsets, local pos/vel) to remain valid. */ + void setMeasUpdatedTimeout(hrt_abstime tout) + { + _meas_updated_timeout_us = tout; + } + + /** Set the active aid-source bitmap (@see SensorFusionMaskU). */ + void setVteAidMask(uint16_t mask_value) + { + _vte_aid_mask.value = mask_value; + } + + /** True once the filter has been initialised and has not received updates within the timeout. */ + bool timedOut() const + { + return _estimator_initialized && hasTimedOut(_last_update, _vte_timeout_us); + } + + /** True when the aid mask enables at least one relative-position source (required to init). */ + bool fusionEnabled() const + { + return _vte_aid_mask.flags.use_vision_pos + || _vte_aid_mask.flags.use_target_gps_pos + || _vte_aid_mask.flags.use_mission_pos; + } + + void print_status() const; + +protected: + static constexpr double kLatAbsMaxDeg = 90.0; + static constexpr double kLonAbsMaxDeg = 180.0; + static constexpr float kAltMinM = -350.f; + static constexpr float kAltMaxM = 10000.f; + + void updateParams() override; + + uORB::Publication _target_pose_pub{ORB_ID(landing_target_pose)}; + uORB::Publication _target_estimator_state_pub{ORB_ID(vte_position)}; + + // publish innovations target_estimator_gps_pos + uORB::Publication _vte_aid_gps_pos_target_pub{ORB_ID(vte_aid_gps_pos_target)}; + uORB::Publication _vte_aid_gps_pos_mission_pub{ORB_ID(vte_aid_gps_pos_mission)}; + uORB::Publication _vte_aid_gps_vel_target_pub{ORB_ID(vte_aid_gps_vel_target)}; + uORB::Publication _vte_aid_gps_vel_uav_pub{ORB_ID(vte_aid_gps_vel_uav)}; + uORB::Publication _vte_aid_fiducial_marker_pub{ORB_ID(vte_aid_fiducial_marker)}; + uORB::Publication _vte_bias_init_status_pub{ORB_ID(vte_bias_init_status)}; + + uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; + +private: + // Observation types used by the estimator. Keep ordering stable for array indexing. + enum class ObsType : uint8_t { + kTargetGpsPos, + kMissionGpsPos, + kUavGpsVel, + kTargetGpsVel, + kFiducialMarker, + kTypeCount + }; + + enum class PreBiasReference : uint8_t { + kUnknown, + kVision, + kGnss + }; + + static constexpr size_t kObsTypeCount = static_cast(ObsType::kTypeCount); + static constexpr size_t obsIndex(ObsType type) + { + return static_cast(type); + } + + struct TargetObs { + + ObsType type; + hrt_abstime timestamp = 0; + + matrix::Vector updated{}; // Indicates if observations were updated. + matrix::Vector3f meas_xyz{}; // Measurements (meas_x, meas_y, meas_z) + matrix::Vector3f meas_unc_xyz{}; // Measurements' uncertainties + matrix::Matrix + meas_h_xyz{}; // Observation matrix where the rows correspond to the + // x,y,z observations and the columns to the state + }; + + union ObsValidMaskU { + struct { + uint8_t fuse_target_gps_pos : 1; ///< bit0: target GPS position ready to be fused + uint8_t fuse_uav_gps_vel : 1; ///< bit1: UAV GPS velocity ready to be fused + uint8_t fuse_vision : 1; ///< bit2: vision relative-position ready to be fused + uint8_t fuse_mission_pos : 1; ///< bit3: mission position ready to be fused + uint8_t fuse_target_gps_vel : 1; ///< bit4: target GPS velocity ready to be fused + uint8_t reserved : 3; ///< bits5..7: reserved for future use + } flags; + + uint8_t value{0}; + }; + + static_assert(sizeof(ObsValidMaskU) == 1, "Unexpected masking size"); + + using EstimatorState = KF_position::VectorState; + using EstimatorStateCovariance = KF_position::SquareMatrixState; + using AxisEstimatorStates = EstimatorState[vtest::Axis::size]; + + bool initEstimator(const AxisEstimatorStates &state_init); + bool performUpdateStep(const matrix::Vector3f &vehicle_acc_ned); + void predictionStep(const matrix::Vector3f &acc, float dt); + float getMinGpsVelVar() const; + float getMinGpsPosVar() const; + float getBiasAveragingThreshold() const; + hrt_abstime getBiasAveragingTimeoutUs() const; + + inline bool isMeasRecent(hrt_abstime ts) const + { + return !hasTimedOut(ts, _meas_recent_timeout_us); + } + + inline bool isMeasUpdated(hrt_abstime ts) const + { + return !hasTimedOut(ts, _meas_updated_timeout_us); + } + + inline bool hasNewPositionSensorData(const ObsValidMaskU &fusion_mask) const + { + return fusion_mask.flags.fuse_mission_pos || + fusion_mask.flags.fuse_target_gps_pos || + fusion_mask.flags.fuse_vision; + } + + inline bool isTimeDifferenceWithin(const hrt_abstime a, const hrt_abstime b, const hrt_abstime timeout_us) const + { + if ((a == 0) || (b == 0)) { + return false; + } + + const hrt_abstime diff = (a > b) ? (a - b) : (b - a); + return diff <= timeout_us; + } + + // Only estimate the GNSS bias if we have a GNSS estimate and vision. + inline bool shouldSetBias(const bool has_vision_observation) const + { + return _pos_rel_gnss.valid && isMeasRecent(_pos_rel_gnss.timestamp) && has_vision_observation; + }; + + inline bool isBiasAveragingEnabled() const + { + return getBiasAveragingThreshold() > 0.f && (getBiasAveragingTimeoutUs() > 0); + } + + /* + * Bias averaging only makes sense when we have both a vision and a valid GNSS observation, + * the current pre-bias reference is GNSS, and the averaging window is configured. + */ + inline bool shouldAverageInitialBias(const bool has_vision_observation, + const PreBiasReference reference) const + { + return shouldSetBias(has_vision_observation) && (reference == PreBiasReference::kGnss) + && isBiasAveragingEnabled(); + } + + inline bool shouldAverageInitialBias(const bool has_vision_observation) const + { + return shouldAverageInitialBias(has_vision_observation, _pre_bias_reference); + } + + inline bool shouldBlockVisionFusionUntilBiasReady() const + { + // Vision must wait until the GNSS bias is ready when the state is still + // referenced to GNSS. + return !_bias.set && (_pre_bias_reference == PreBiasReference::kGnss); + } + + inline bool shouldBlockGnssFusionUntilBiasReady() const + { + // GNSS position must wait until the GNSS bias is ready when the state is + // still referenced to vision. + return !_bias.set && (_pre_bias_reference == PreBiasReference::kVision); + } + + /** Build the first filter state once a valid mix of observations is available. */ + bool initializeEstimator(const ObsValidMaskU &fusion_mask, + const TargetObs observations[kObsTypeCount]); + /** Check whether we have a fresh UAV velocity source that can seed the state. */ + bool hasInitialVelocityEstimate() const; + /** Prefer GNSS UAV velocity, otherwise fall back to the local EKF velocity. */ + matrix::Vector3f selectInitialUavVelocity() const; + /** Seed the initial GNSS bias directly from the freshest GNSS-relative sample. */ + void selectInitialBiasFromGnss(const TargetObs observations[kObsTypeCount], + const matrix::Vector3f &initial_position, matrix::Vector3f &initial_bias); + /** Build the per-axis state vectors used by the generated Kalman filter. */ + void buildInitialStateArray(const matrix::Vector3f &initial_position, + const matrix::Vector3f &initial_uav_velocity, const matrix::Vector3f &initial_bias, + AxisEstimatorStates &state_init) const; + /** Track the GNSS/vision bias until it is ready to be activated in the state. */ + void updateBiasIfObservable(const ObsValidMaskU &fusion_mask, + const TargetObs observations[kObsTypeCount]); + /** Pick the GNSS-relative sample that best matches the requested timestamp. */ + bool selectBiasGnssSample(hrt_abstime sample_time, matrix::Vector3f &gnss_sample); + /** Decide which position source defines the pre-bias state reference. */ + PreBiasReference selectInitialPosition(const ObsValidMaskU &fusion_mask, + const TargetObs observations[kObsTypeCount], matrix::Vector3f &initial_position, + bool prefer_vision = true); + /** Fuse every ready observation in source-priority order. */ + bool fuseActiveMeasurements(const matrix::Vector3f &vehicle_acc_ned, ObsValidMaskU &fusion_mask, + const TargetObs observations[kObsTypeCount]); + /** Refresh subscriptions and populate the per-cycle observation buffer. */ + void processObservations(ObsValidMaskU &fusion_mask, + TargetObs observations[kObsTypeCount]); + bool getOffsetUavVel(hrt_abstime sample_time, matrix::Vector3f &uav_velocity_ned) const; + void startBiasAveraging(const matrix::Vector3f &bias_sample, hrt_abstime sample_time); + bool updateBiasAveraging(const matrix::Vector3f &bias_sample, hrt_abstime sample_time); + void resetBiasAveraging(); + /** Commit the final pre-bias position/bias pair and restart OOSM history. */ + void activateBiasEstimate(const matrix::Vector3f &initial_position, const matrix::Vector3f &initial_bias); + void publishBiasInitStatus(const matrix::Vector3f &raw_bias, const matrix::Vector3f &filtered_bias, + float raw_bias_delta_norm, hrt_abstime sample_time); + + /** Validate geographic coordinates before they are cached or fused. */ + bool isLatLonAltValid(double lat_deg, double lon_deg, float alt_m, const char *who = nullptr, + hrt_abstime *warn_last = nullptr); + + /* Vision data */ + bool isVisionDataValid(const fiducial_marker_pos_report_s &fiducial_marker_pose); + bool processObsVision(TargetObs &obs); + + /* UAV GPS data */ + bool updateUavGpsData(); + bool isUavGpsPositionValid(); + bool isUavGpsVelocityValid(); + bool processObsGNSSPosMission(TargetObs &obs); + bool processObsGNSSVelUav(TargetObs &obs) const; + + /* Target GPS data */ + bool isTargetGpsPositionValid(const target_gnss_s &target_gnss); + bool isTargetGpsVelocityValid(const target_gnss_s &target_gnss); + bool processObsGNSSPosTarget(const target_gnss_s &target_gnss, TargetObs &obs); +#if defined(CONFIG_VTEST_MOVING) + bool processObsGNSSVelTarget(const target_gnss_s &target_gnss, TargetObs &obs) const; + void updateTargetGpsVelocity(const target_gnss_s &target_gnss); +#endif // CONFIG_VTEST_MOVING + + bool fuseMeas(const matrix::Vector3f &vehicle_acc_ned, const TargetObs &target_pos_obs); + void publishTarget(); + void publishInnov(const vte_aid_source3d_s &target_innov, const ObsType type); + void resetObservations(); + bool shouldEmitWarning(hrt_abstime &last_warn); + + uORB::Subscription _vehicle_gps_position_sub{ORB_ID(vehicle_gps_position)}; + uORB::Subscription _fiducial_marker_pos_report_sub{ORB_ID(fiducial_marker_pos_report)}; + uORB::Subscription _target_gnss_sub{ORB_ID(target_gnss)}; + + perf_counter_t _vte_predict_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": VTE prediction")}; + perf_counter_t _vte_update_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": VTE update")}; + perf_counter_t _vte_fusion_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": VTE fusion")}; + + TargetObs _obs_buffer[kObsTypeCount] {}; + landing_target_pose_s _target_pose{}; + vte_position_s _vte_state{}; + + struct GlobalPose { + hrt_abstime timestamp = 0; + bool valid = false; + double lat_deg = 0.0; // Latitude in degrees + double lon_deg = 0.0; // Longitude in degrees + float alt_m = 0.f; // Altitude in meters AMSL + float eph = 0.f; + float epv = 0.f; + }; + + GlobalPose _mission_land_position{}; + GlobalPose _uav_gps_position{}; + + struct VelStamped { + hrt_abstime timestamp = 0; + bool valid = false; + matrix::Vector3f xyz{}; + float uncertainty = 0.f; + }; + + VelStamped _uav_gps_vel{}; + + Vector3fStamped _local_position{}; + Vector3fStamped _local_velocity{}; + Vector3fStamped _pos_rel_gnss{}; + Vector3fStamped _velocity_offset_ned{}; + Vector3fStamped _gps_pos_offset_ned{}; + +#if defined(CONFIG_VTEST_MOVING) + Vector3fStamped _target_gps_vel {}; +#endif // CONFIG_VTEST_MOVING + + static constexpr float kInitialBiasLpfTimeConstantS{0.3f}; + + struct BiasState { + bool set{false}; + bool averaging_active{false}; + uint8_t stable_delta_count{0}; + hrt_abstime averaging_start_time{0}; + hrt_abstime last_sample_time{0}; + AlphaFilter initial_lpf{kInitialBiasLpfTimeConstantS}; + }; + + bool _gps_pos_is_offset{false}; + BiasState _bias{}; + PreBiasReference _pre_bias_reference{PreBiasReference::kUnknown}; + + uint64_t _last_relative_meas_fused_time{0}; + bool _estimator_initialized{false}; + + KF_position _target_est_pos[vtest::Axis::size] {}; + + hrt_abstime _last_predict{0}; // timestamp of last filter prediction + hrt_abstime _last_update{0}; // timestamp of last filter update (used to check timeout) + hrt_abstime _uav_gps_vel_warn_last{0}; + hrt_abstime _target_gps_vel_warn_last{0}; + hrt_abstime _vision_pos_warn_last{0}; + hrt_abstime _uav_gps_pos_warn_last{0}; + hrt_abstime _target_gps_pos_warn_last{0}; + hrt_abstime _mission_pos_warn_last{0}; + hrt_abstime _mission_pos_status_warn_last{0}; + hrt_abstime _init_vel_warn_last{0}; + + /* parameters from vision_target_estimator_params.yaml */ + void checkMeasurementInputs(); + + hrt_abstime _vte_timeout_us{3_s}; + hrt_abstime _target_valid_timeout_us{2_s}; + hrt_abstime _meas_recent_timeout_us{1_s}; + hrt_abstime _meas_updated_timeout_us{100_ms}; + SensorFusionMaskU _vte_aid_mask{}; + + DEFINE_PARAMETERS( + (ParamFloat) _param_vte_acc_d_unc, + (ParamFloat) _param_vte_acc_t_unc, + (ParamFloat) _param_vte_bias_unc, + (ParamFloat) _param_vte_bias_avg_thr, + (ParamFloat) _param_vte_bias_avg_tout, + (ParamFloat) _param_vte_pos_unc_in, + (ParamFloat) _param_vte_vel_unc_in, + (ParamFloat) _param_vte_bias_unc_in, + (ParamFloat) _param_vte_acc_unc_in, + (ParamFloat) _param_vte_gps_vel_noise, + (ParamFloat) _param_vte_gps_pos_noise, + (ParamFloat) _param_vte_ev_pos_noise, + (ParamFloat) _param_vte_pos_nis_thre + ) +}; +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/derivation.py b/src/modules/vision_target_estimator/Position/vtest_derivation/derivation.py new file mode 100755 index 00000000000..52fa448f3cc --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/derivation.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" + Copyright (c) 2026 PX4 Development Team + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. Neither the name PX4 nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +File: derivation.py +Description: + Derivation of KF +""" + +import argparse + +import symforce +symforce.set_epsilon_to_symbol() + +import symforce.symbolic as sf +from symforce import typing as T +from symforce import ops +from symforce.values import Values + +import sympy as sp +from utils.derivation_utils import * + +# Initialize parser +parser = argparse.ArgumentParser() + +parser.add_argument("--moving", action='store_true', help="generate equations for moving filter") + +# Read arguments from command line +args = parser.parse_args() +moving = args.moving + +# The state vector is organized in an ordered dictionary +State = Values( + pos_rel=sf.V1(), + vel_uav=sf.V1(), + bias=sf.V1(), + acc_target=sf.V1(), + vel_target=sf.V1() +) + +if not moving: + del State["acc_target"] + del State["vel_target"] + +class IdxDof(): + def __init__(self, idx, dof): + self.idx = idx + self.dof = dof + +def BuildTangentStateIndex(): + tangent_state_index = {} + idx = 0 + for key in State.keys_recursive(): + dof = State[key].tangent_dim() + tangent_state_index[key] = IdxDof(idx, dof) + idx += dof + return tangent_state_index + +tangent_idx = BuildTangentStateIndex() + +class VState(sf.Matrix): + SHAPE = (State.storage_dim(), 1) + +class MState(sf.Matrix): + SHAPE = (State.storage_dim(), State.storage_dim()) + +class VMeas(sf.Matrix): + SHAPE = (1, State.storage_dim()) + +def symbolic_state(state_structure): + symbolic_state = Values() + for key in state_structure.keys_recursive(): + var_type = type(state_structure[key]) + if hasattr(var_type, 'symbolic'): + symbolic_state[key] = var_type.symbolic(key) + + return symbolic_state + +def get_Phi_and_G(dt: sf.Scalar, +) -> MState: + + state = symbolic_state(State) + + # Input acceleration (symbolic) + acc = sf.Symbol('acc') + + state_pred = state.copy() + state_pred["pos_rel"] = state["pos_rel"] - dt * state["vel_uav"] - 0.5 * dt**2 * acc + state_pred["vel_uav"] = state["vel_uav"] + dt * acc + state_pred["bias"] = state["bias"] + + if moving: + state_pred["pos_rel"] += dt * state["vel_target"] + 0.5 * dt**2 * state["acc_target"] + state_pred["vel_target"] = state["vel_target"] + dt * state["acc_target"] + state_pred["acc_target"] = state["acc_target"] + + # State vector + state_pred_matrix = VState(state_pred.to_storage()) + + # Compute Phi = ∂f/∂x + Phi = state_pred_matrix.jacobian([state]) + # Compute G = ∂f/∂w + G = state_pred_matrix.jacobian(acc) + + return Phi, G + +def predictState(dt: sf.Scalar, state: VState, acc: sf.Scalar) -> VState: + Phi, G = get_Phi_and_G(dt) + return Phi * state + G * acc + +def getTransitionMatrix(dt: sf.Scalar) -> MState: + Phi, _ = get_Phi_and_G(dt) + return Phi + +def integrate_continuous_noise_gain( + dt: sf.Scalar, tau: sf.Scalar, gain: sf.Matrix, spectral_density: sf.Scalar +) -> MState: + n = State.storage_dim() + Q = sf.Matrix.zeros(n, n) + + for row in range(n): + for col in range(n): + integrand = gain[row, 0] * gain[col, 0] * spectral_density + Q[row, col] = sp.integrate(integrand, (tau, 0, dt)) + + return Q + +def derive_input_noise_Q(dt: sf.Scalar, input_var: sf.Scalar) -> MState: + """Continuous-time white-noise UAV-acceleration contribution to Q. + + Treats the UAV acceleration input as continuous-time white noise with + spectral density input_var (units m^2/s^3, equivalently (m/s^2)^2/Hz) + and integrates the differential gain dG/dtau over [0, dt] to obtain the + discrete Q matrix. + """ + tau = sf.Symbol("tau") + _, G_tau = get_Phi_and_G(tau) + G_continuous = G_tau.jacobian(tau) + return integrate_continuous_noise_gain(dt, tau, G_continuous, input_var) + +def derive_target_acc_noise_Q(dt: sf.Scalar, acc_var: sf.Scalar) -> MState: + """Continuous-time white-jerk contribution driving target acceleration.""" + tau = sf.Symbol("tau") + Phi_tau, _ = get_Phi_and_G(tau) + idx_a_target = tangent_idx['acc_target'].idx + n = State.storage_dim() + G_continuous = sf.Matrix.zeros(n, 1) + + for row in range(n): + G_continuous[row, 0] = Phi_tau[row, idx_a_target] + + return integrate_continuous_noise_gain(dt, tau, G_continuous, acc_var) + +def predictCov(dt: sf.Scalar, input_var: sf.Scalar, bias_var: sf.Scalar, acc_var: sf.Scalar, covariance: MState) -> MState: + Phi, _ = get_Phi_and_G(dt) + Q = derive_input_noise_Q(dt, input_var) + + # Scale bias random walk by dt. + idx_bias = tangent_idx['bias'].idx + Q[idx_bias, idx_bias] += bias_var * dt + + if moving: + Q += derive_target_acc_noise_Q(dt, acc_var) + + return Phi * covariance * Phi.T + Q + +def computeInnovCov(meas_unc: sf.Scalar, covariance: MState, meas_matrix: VMeas) -> sf.Scalar: + return (meas_matrix * covariance * meas_matrix.T)[0, 0] + meas_unc + +# OOSM correction +def applyCorrection(state: VState, cov: MState, K: VState, innov: sf.Scalar, S: sf.Scalar) -> (VState, MState): + + # Update State + state_new = state + K * innov + + # Update Covariance + cov_update = K * S * K.T + cov_new = cov - cov_update + + # Force Symmetry + cov_new = 0.5 * (cov_new + cov_new.T) + + return state_new, cov_new + +# Generate functions +print(f"Derive VTEST equations for {'moving' if moving else 'static'} targets...") +generate_px4_function(predictState, output_names=["predict_state"]) +generate_px4_function(getTransitionMatrix, output_names=["transition_matrix"]) +generate_px4_function(predictCov, output_names=["cov_updated"]) +generate_px4_function(computeInnovCov, output_names=["innov_cov_updated"]) +generate_px4_function(applyCorrection, output_names=["state_new", "cov_new"]) + +generate_px4_state(State, tangent_idx) diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated/applyCorrection.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/applyCorrection.h new file mode 100644 index 00000000000..d0bd6dbbf87 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/applyCorrection.h @@ -0,0 +1,76 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: applyCorrection + * + * Args: + * state: Matrix31 + * cov: Matrix33 + * K: Matrix31 + * innov: Scalar + * S: Scalar + * + * Outputs: + * state_new: Matrix31 + * cov_new: Matrix33 + */ +template +void Applycorrection(const matrix::Matrix &state, + const matrix::Matrix &cov, const matrix::Matrix &K, + const Scalar innov, const Scalar S, + matrix::Matrix *const state_new = nullptr, + matrix::Matrix *const cov_new = nullptr) +{ + // Total ops: 42 + + // Input arrays + + // Intermediate terms (5) + const Scalar _tmp0 = 2 * S; + const Scalar _tmp1 = + -Scalar(0.5) * K(0, 0) * K(1, 0) * _tmp0 + Scalar(0.5) * cov(0, 1) + Scalar(0.5) * cov(1, 0); + const Scalar _tmp2 = K(2, 0) * _tmp0; + const Scalar _tmp3 = + -Scalar(0.5) * K(0, 0) * _tmp2 + Scalar(0.5) * cov(0, 2) + Scalar(0.5) * cov(2, 0); + const Scalar _tmp4 = + -Scalar(0.5) * K(1, 0) * _tmp2 + Scalar(0.5) * cov(1, 2) + Scalar(0.5) * cov(2, 1); + + // Output terms (2) + if (state_new != nullptr) { + matrix::Matrix &_state_new = (*state_new); + + _state_new(0, 0) = K(0, 0) * innov + state(0, 0); + _state_new(1, 0) = K(1, 0) * innov + state(1, 0); + _state_new(2, 0) = K(2, 0) * innov + state(2, 0); + } + + if (cov_new != nullptr) { + matrix::Matrix &_cov_new = (*cov_new); + + _cov_new(0, 0) = -Scalar(0.5) * std::pow(K(0, 0), Scalar(2)) * _tmp0 + Scalar(1.0) * cov(0, 0); + _cov_new(1, 0) = _tmp1; + _cov_new(2, 0) = _tmp3; + _cov_new(0, 1) = _tmp1; + _cov_new(1, 1) = -Scalar(0.5) * std::pow(K(1, 0), Scalar(2)) * _tmp0 + Scalar(1.0) * cov(1, 1); + _cov_new(2, 1) = _tmp4; + _cov_new(0, 2) = _tmp3; + _cov_new(1, 2) = _tmp4; + _cov_new(2, 2) = -Scalar(0.5) * std::pow(K(2, 0), Scalar(2)) * _tmp0 + Scalar(1.0) * cov(2, 2); + } +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated/computeInnovCov.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/computeInnovCov.h new file mode 100644 index 00000000000..fb44b42e5ee --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/computeInnovCov.h @@ -0,0 +1,55 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: computeInnovCov + * + * Args: + * meas_unc: Scalar + * covariance: Matrix33 + * meas_matrix: Matrix13 + * + * Outputs: + * innov_cov_updated: Scalar + */ +template +Scalar Computeinnovcov(const Scalar meas_unc, const matrix::Matrix &covariance, + const matrix::Matrix &meas_matrix) +{ + // Total ops: 21 + + // Input arrays + + // Intermediate terms (0) + + // Output terms (1) + Scalar _innov_cov_updated; + + _innov_cov_updated = meas_matrix(0, 0) * (covariance(0, 0) * meas_matrix(0, 0) + + covariance(1, 0) * meas_matrix(0, 1) + + covariance(2, 0) * meas_matrix(0, 2)) + + meas_matrix(0, 1) * (covariance(0, 1) * meas_matrix(0, 0) + + covariance(1, 1) * meas_matrix(0, 1) + + covariance(2, 1) * meas_matrix(0, 2)) + + meas_matrix(0, 2) * (covariance(0, 2) * meas_matrix(0, 0) + + covariance(1, 2) * meas_matrix(0, 1) + + covariance(2, 2) * meas_matrix(0, 2)) + + meas_unc; + + return _innov_cov_updated; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated/getTransitionMatrix.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/getTransitionMatrix.h new file mode 100644 index 00000000000..99ea68d19f0 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/getTransitionMatrix.h @@ -0,0 +1,48 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: getTransitionMatrix + * + * Args: + * dt: Scalar + * + * Outputs: + * transition_matrix: Matrix33 + */ +template +matrix::Matrix Gettransitionmatrix(const Scalar dt) +{ + // Total ops: 1 + + // Input arrays + + // Intermediate terms (0) + + // Output terms (1) + matrix::Matrix _transition_matrix; + + _transition_matrix.setZero(); + + _transition_matrix(0, 0) = 1; + _transition_matrix(0, 1) = -dt; + _transition_matrix(1, 1) = 1; + _transition_matrix(2, 2) = 1; + + return _transition_matrix; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated/predictCov.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/predictCov.h new file mode 100644 index 00000000000..4aba0d4f7a9 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/predictCov.h @@ -0,0 +1,67 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: predictCov + * + * Args: + * dt: Scalar + * input_var: Scalar + * bias_var: Scalar + * acc_var: Scalar + * covariance: Matrix33 + * + * Outputs: + * cov_updated: Matrix33 + */ +template +matrix::Matrix Predictcov(const Scalar dt, const Scalar input_var, + const Scalar bias_var, const Scalar acc_var, + const matrix::Matrix &covariance) +{ + // Total ops: 26 + + // Unused inputs + (void)acc_var; + + // Input arrays + + // Intermediate terms (3) + const Scalar _tmp0 = -covariance(1, 1) * dt; + const Scalar _tmp1 = _tmp0 + covariance(0, 1); + const Scalar _tmp2 = -Scalar(0.5) * std::pow(dt, Scalar(2)) * input_var; + + // Output terms (1) + matrix::Matrix _cov_updated; + + _cov_updated(0, 0) = + -_tmp1 * dt + covariance(0, 0) - covariance(1, 0) * dt + Scalar(0.33333333333333298) * [&]() { + const Scalar base = dt; + return base * base * base; + }() * input_var; + _cov_updated(1, 0) = _tmp0 + _tmp2 + covariance(1, 0); + _cov_updated(2, 0) = covariance(2, 0) - covariance(2, 1) * dt; + _cov_updated(0, 1) = _tmp1 + _tmp2; + _cov_updated(1, 1) = covariance(1, 1) + dt * input_var; + _cov_updated(2, 1) = covariance(2, 1); + _cov_updated(0, 2) = covariance(0, 2) - covariance(1, 2) * dt; + _cov_updated(1, 2) = covariance(1, 2); + _cov_updated(2, 2) = bias_var * dt + covariance(2, 2); + + return _cov_updated; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated/predictState.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/predictState.h new file mode 100644 index 00000000000..4783b0dc79a --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/predictState.h @@ -0,0 +1,49 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: predictState + * + * Args: + * dt: Scalar + * state: Matrix31 + * acc: Scalar + * + * Outputs: + * predict_state: Matrix31 + */ +template +matrix::Matrix Predictstate(const Scalar dt, const matrix::Matrix &state, + const Scalar acc) +{ + // Total ops: 8 + + // Input arrays + + // Intermediate terms (0) + + // Output terms (1) + matrix::Matrix _predict_state; + + _predict_state(0, 0) = + -Scalar(0.5) * acc * std::pow(dt, Scalar(2)) - dt * state(1, 0) + state(0, 0); + _predict_state(1, 0) = acc * dt + state(1, 0); + _predict_state(2, 0) = state(2, 0); + + return _predict_state; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated/state.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/state.h new file mode 100644 index 00000000000..80ba136184a --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated/state.h @@ -0,0 +1,49 @@ +// -------------------------------------------------- +// This file was autogenerated, do NOT modify by hand +// -------------------------------------------------- + +#ifndef EKF_STATE_H +#define EKF_STATE_H + +#include + +namespace vtest +{ +struct StateSample { + float pos_rel{}; + float vel_uav{}; + float bias{}; + + matrix::Vector Data() const + { + matrix::Vector state; + state.slice<1, 1>(0, 0) = pos_rel; + state.slice<1, 1>(1, 0) = vel_uav; + state.slice<1, 1>(2, 0) = bias; + return state; + }; + + const matrix::Vector &vector() const + { + return *reinterpret_cast*>(const_cast(reinterpret_cast(&pos_rel))); + }; + +}; +static_assert(sizeof(matrix::Vector) == sizeof(StateSample), "state vector doesn't match StateSample size"); +namespace Axis +{ +static constexpr uint8_t x{0}; +static constexpr uint8_t y{1}; +static constexpr uint8_t z{2}; +static constexpr uint8_t size{3}; +}; + +namespace State +{ +static constexpr uint8_t pos_rel{0}; +static constexpr uint8_t vel_uav{1}; +static constexpr uint8_t bias{2}; +static constexpr uint8_t size{3}; +}; +} +#endif // !EKF_STATE_H diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/applyCorrection.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/applyCorrection.h new file mode 100644 index 00000000000..c3243aac2d0 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/applyCorrection.h @@ -0,0 +1,110 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: applyCorrection + * + * Args: + * state: Matrix51 + * cov: Matrix55 + * K: Matrix51 + * innov: Scalar + * S: Scalar + * + * Outputs: + * state_new: Matrix51 + * cov_new: Matrix55 + */ +template +void Applycorrection(const matrix::Matrix &state, + const matrix::Matrix &cov, const matrix::Matrix &K, + const Scalar innov, const Scalar S, + matrix::Matrix *const state_new = nullptr, + matrix::Matrix *const cov_new = nullptr) +{ + // Total ops: 100 + + // Input arrays + + // Intermediate terms (14) + const Scalar _tmp0 = 2 * S; + const Scalar _tmp1 = K(0, 0) * _tmp0; + const Scalar _tmp2 = + -Scalar(0.5) * K(1, 0) * _tmp1 + Scalar(0.5) * cov(0, 1) + Scalar(0.5) * cov(1, 0); + const Scalar _tmp3 = + -Scalar(0.5) * K(2, 0) * _tmp1 + Scalar(0.5) * cov(0, 2) + Scalar(0.5) * cov(2, 0); + const Scalar _tmp4 = K(3, 0) * _tmp0; + const Scalar _tmp5 = + -Scalar(0.5) * K(0, 0) * _tmp4 + Scalar(0.5) * cov(0, 3) + Scalar(0.5) * cov(3, 0); + const Scalar _tmp6 = K(4, 0) * _tmp0; + const Scalar _tmp7 = + -Scalar(0.5) * K(0, 0) * _tmp6 + Scalar(0.5) * cov(0, 4) + Scalar(0.5) * cov(4, 0); + const Scalar _tmp8 = + -Scalar(0.5) * K(1, 0) * K(2, 0) * _tmp0 + Scalar(0.5) * cov(1, 2) + Scalar(0.5) * cov(2, 1); + const Scalar _tmp9 = + -Scalar(0.5) * K(1, 0) * _tmp4 + Scalar(0.5) * cov(1, 3) + Scalar(0.5) * cov(3, 1); + const Scalar _tmp10 = + -Scalar(0.5) * K(1, 0) * _tmp6 + Scalar(0.5) * cov(1, 4) + Scalar(0.5) * cov(4, 1); + const Scalar _tmp11 = + -Scalar(0.5) * K(2, 0) * _tmp4 + Scalar(0.5) * cov(2, 3) + Scalar(0.5) * cov(3, 2); + const Scalar _tmp12 = + -Scalar(0.5) * K(2, 0) * _tmp6 + Scalar(0.5) * cov(2, 4) + Scalar(0.5) * cov(4, 2); + const Scalar _tmp13 = + -Scalar(0.5) * K(3, 0) * _tmp6 + Scalar(0.5) * cov(3, 4) + Scalar(0.5) * cov(4, 3); + + // Output terms (2) + if (state_new != nullptr) { + matrix::Matrix &_state_new = (*state_new); + + _state_new(0, 0) = K(0, 0) * innov + state(0, 0); + _state_new(1, 0) = K(1, 0) * innov + state(1, 0); + _state_new(2, 0) = K(2, 0) * innov + state(2, 0); + _state_new(3, 0) = K(3, 0) * innov + state(3, 0); + _state_new(4, 0) = K(4, 0) * innov + state(4, 0); + } + + if (cov_new != nullptr) { + matrix::Matrix &_cov_new = (*cov_new); + + _cov_new(0, 0) = -Scalar(0.5) * std::pow(K(0, 0), Scalar(2)) * _tmp0 + Scalar(1.0) * cov(0, 0); + _cov_new(1, 0) = _tmp2; + _cov_new(2, 0) = _tmp3; + _cov_new(3, 0) = _tmp5; + _cov_new(4, 0) = _tmp7; + _cov_new(0, 1) = _tmp2; + _cov_new(1, 1) = -Scalar(0.5) * std::pow(K(1, 0), Scalar(2)) * _tmp0 + Scalar(1.0) * cov(1, 1); + _cov_new(2, 1) = _tmp8; + _cov_new(3, 1) = _tmp9; + _cov_new(4, 1) = _tmp10; + _cov_new(0, 2) = _tmp3; + _cov_new(1, 2) = _tmp8; + _cov_new(2, 2) = -Scalar(0.5) * std::pow(K(2, 0), Scalar(2)) * _tmp0 + Scalar(1.0) * cov(2, 2); + _cov_new(3, 2) = _tmp11; + _cov_new(4, 2) = _tmp12; + _cov_new(0, 3) = _tmp5; + _cov_new(1, 3) = _tmp9; + _cov_new(2, 3) = _tmp11; + _cov_new(3, 3) = -Scalar(0.5) * std::pow(K(3, 0), Scalar(2)) * _tmp0 + Scalar(1.0) * cov(3, 3); + _cov_new(4, 3) = _tmp13; + _cov_new(0, 4) = _tmp7; + _cov_new(1, 4) = _tmp10; + _cov_new(2, 4) = _tmp12; + _cov_new(3, 4) = _tmp13; + _cov_new(4, 4) = -Scalar(0.5) * std::pow(K(4, 0), Scalar(2)) * _tmp0 + Scalar(1.0) * cov(4, 4); + } +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/computeInnovCov.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/computeInnovCov.h new file mode 100644 index 00000000000..00b30b3c8eb --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/computeInnovCov.h @@ -0,0 +1,67 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: computeInnovCov + * + * Args: + * meas_unc: Scalar + * covariance: Matrix55 + * meas_matrix: Matrix15 + * + * Outputs: + * innov_cov_updated: Scalar + */ +template +Scalar Computeinnovcov(const Scalar meas_unc, const matrix::Matrix &covariance, + const matrix::Matrix &meas_matrix) +{ + // Total ops: 55 + + // Input arrays + + // Intermediate terms (0) + + // Output terms (1) + Scalar _innov_cov_updated; + + _innov_cov_updated = + meas_matrix(0, 0) * + (covariance(0, 0) * meas_matrix(0, 0) + covariance(1, 0) * meas_matrix(0, 1) + + covariance(2, 0) * meas_matrix(0, 2) + covariance(3, 0) * meas_matrix(0, 3) + + covariance(4, 0) * meas_matrix(0, 4)) + + meas_matrix(0, 1) * + (covariance(0, 1) * meas_matrix(0, 0) + covariance(1, 1) * meas_matrix(0, 1) + + covariance(2, 1) * meas_matrix(0, 2) + covariance(3, 1) * meas_matrix(0, 3) + + covariance(4, 1) * meas_matrix(0, 4)) + + meas_matrix(0, 2) * + (covariance(0, 2) * meas_matrix(0, 0) + covariance(1, 2) * meas_matrix(0, 1) + + covariance(2, 2) * meas_matrix(0, 2) + covariance(3, 2) * meas_matrix(0, 3) + + covariance(4, 2) * meas_matrix(0, 4)) + + meas_matrix(0, 3) * + (covariance(0, 3) * meas_matrix(0, 0) + covariance(1, 3) * meas_matrix(0, 1) + + covariance(2, 3) * meas_matrix(0, 2) + covariance(3, 3) * meas_matrix(0, 3) + + covariance(4, 3) * meas_matrix(0, 4)) + + meas_matrix(0, 4) * + (covariance(0, 4) * meas_matrix(0, 0) + covariance(1, 4) * meas_matrix(0, 1) + + covariance(2, 4) * meas_matrix(0, 2) + covariance(3, 4) * meas_matrix(0, 3) + + covariance(4, 4) * meas_matrix(0, 4)) + + meas_unc; + + return _innov_cov_updated; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/getTransitionMatrix.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/getTransitionMatrix.h new file mode 100644 index 00000000000..939e7519999 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/getTransitionMatrix.h @@ -0,0 +1,53 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: getTransitionMatrix + * + * Args: + * dt: Scalar + * + * Outputs: + * transition_matrix: Matrix55 + */ +template +matrix::Matrix Gettransitionmatrix(const Scalar dt) +{ + // Total ops: 3 + + // Input arrays + + // Intermediate terms (0) + + // Output terms (1) + matrix::Matrix _transition_matrix; + + _transition_matrix.setZero(); + + _transition_matrix(0, 0) = 1; + _transition_matrix(0, 1) = -dt; + _transition_matrix(1, 1) = 1; + _transition_matrix(2, 2) = 1; + _transition_matrix(0, 3) = Scalar(0.5) * std::pow(dt, Scalar(2)); + _transition_matrix(3, 3) = 1; + _transition_matrix(4, 3) = dt; + _transition_matrix(0, 4) = dt; + _transition_matrix(4, 4) = 1; + + return _transition_matrix; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/predictCov.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/predictCov.h new file mode 100644 index 00000000000..4f1429d8a38 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/predictCov.h @@ -0,0 +1,103 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: predictCov + * + * Args: + * dt: Scalar + * input_var: Scalar + * bias_var: Scalar + * acc_var: Scalar + * covariance: Matrix55 + * + * Outputs: + * cov_updated: Matrix55 + */ +template +matrix::Matrix Predictcov(const Scalar dt, const Scalar input_var, + const Scalar bias_var, const Scalar acc_var, + const matrix::Matrix &covariance) +{ + // Total ops: 109 + + // Input arrays + + // Intermediate terms (21) + const Scalar _tmp0 = covariance(1, 4) * dt; + const Scalar _tmp1 = std::pow(dt, Scalar(2)); + const Scalar _tmp2 = Scalar(0.5) * _tmp1; + const Scalar _tmp3 = -_tmp0 + _tmp2 * covariance(3, 4) + covariance(0, 4) + covariance(4, 4) * dt; + const Scalar _tmp4 = -covariance(1, 1) * dt; + const Scalar _tmp5 = _tmp2 * covariance(3, 1) + _tmp4 + covariance(0, 1) + covariance(4, 1) * dt; + const Scalar _tmp6 = covariance(1, 3) * dt; + const Scalar _tmp7 = _tmp2 * covariance(3, 3); + const Scalar _tmp8 = -_tmp6 + _tmp7 + covariance(0, 3) + covariance(4, 3) * dt; + const Scalar _tmp9 = [&]() { + const Scalar base = dt; + return base * base * base; + }(); + const Scalar _tmp10 = -_tmp2 * input_var; + const Scalar _tmp11 = covariance(3, 4) * dt; + const Scalar _tmp12 = covariance(3, 1) * dt; + const Scalar _tmp13 = _tmp9 * acc_var; + const Scalar _tmp14 = Scalar(0.16666666666666699) * _tmp13; + const Scalar _tmp15 = covariance(3, 3) * dt; + const Scalar _tmp16 = _tmp15 + covariance(4, 3); + const Scalar _tmp17 = _tmp11 + covariance(4, 4); + const Scalar _tmp18 = _tmp12 + covariance(4, 1); + const Scalar _tmp19 = Scalar(0.125) * acc_var * std::pow(dt, Scalar(4)); + const Scalar _tmp20 = (Scalar(1) / Scalar(2)) * _tmp1 * acc_var; + + // Output terms (1) + matrix::Matrix _cov_updated; + + _cov_updated(0, 0) = _tmp2 * _tmp8 + _tmp2 * covariance(3, 0) + _tmp3 * dt - _tmp5 * dt + + Scalar(0.33333333333333298) * _tmp9 * input_var + + Scalar(0.050000000000000003) * acc_var * std::pow(dt, Scalar(5)) + + covariance(0, 0) - covariance(1, 0) * dt + covariance(4, 0) * dt; + _cov_updated(1, 0) = _tmp0 + _tmp10 + _tmp2 * covariance(1, 3) + _tmp4 + covariance(1, 0); + _cov_updated(2, 0) = + _tmp2 * covariance(2, 3) + covariance(2, 0) - covariance(2, 1) * dt + covariance(2, 4) * dt; + _cov_updated(3, 0) = _tmp11 - _tmp12 + _tmp14 + _tmp7 + covariance(3, 0); + _cov_updated(4, 0) = _tmp16 * _tmp2 + _tmp17 * dt - _tmp18 * dt + _tmp19 + covariance(3, 0) * dt + + covariance(4, 0); + _cov_updated(0, 1) = _tmp10 + _tmp5; + _cov_updated(1, 1) = covariance(1, 1) + dt * input_var; + _cov_updated(2, 1) = covariance(2, 1); + _cov_updated(3, 1) = covariance(3, 1); + _cov_updated(4, 1) = _tmp18; + _cov_updated(0, 2) = + _tmp2 * covariance(3, 2) + covariance(0, 2) - covariance(1, 2) * dt + covariance(4, 2) * dt; + _cov_updated(1, 2) = covariance(1, 2); + _cov_updated(2, 2) = bias_var * dt + covariance(2, 2); + _cov_updated(3, 2) = covariance(3, 2); + _cov_updated(4, 2) = covariance(3, 2) * dt + covariance(4, 2); + _cov_updated(0, 3) = _tmp14 + _tmp8; + _cov_updated(1, 3) = covariance(1, 3); + _cov_updated(2, 3) = covariance(2, 3); + _cov_updated(3, 3) = acc_var * dt + covariance(3, 3); + _cov_updated(4, 3) = _tmp16 + _tmp20; + _cov_updated(0, 4) = _tmp19 + _tmp3 + _tmp8 * dt; + _cov_updated(1, 4) = _tmp6 + covariance(1, 4); + _cov_updated(2, 4) = covariance(2, 3) * dt + covariance(2, 4); + _cov_updated(3, 4) = _tmp15 + _tmp20 + covariance(3, 4); + _cov_updated(4, 4) = (Scalar(1) / Scalar(3)) * _tmp13 + _tmp16 * dt + _tmp17; + + return _cov_updated; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/predictState.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/predictState.h new file mode 100644 index 00000000000..85b7ad8b4a6 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/predictState.h @@ -0,0 +1,52 @@ +// ----------------------------------------------------------------------------- +// This file was autogenerated by symforce from template: +// function/FUNCTION.h.jinja +// Do NOT modify by hand. +// ----------------------------------------------------------------------------- + +#pragma once + +#include + +namespace sym +{ + +/** + * This function was autogenerated from a symbolic function. Do not modify by hand. + * + * Symbolic function: predictState + * + * Args: + * dt: Scalar + * state: Matrix51 + * acc: Scalar + * + * Outputs: + * predict_state: Matrix51 + */ +template +matrix::Matrix Predictstate(const Scalar dt, const matrix::Matrix &state, + const Scalar acc) +{ + // Total ops: 15 + + // Input arrays + + // Intermediate terms (1) + const Scalar _tmp0 = std::pow(dt, Scalar(2)); + + // Output terms (1) + matrix::Matrix _predict_state; + + _predict_state(0, 0) = -Scalar(0.5) * _tmp0 * acc + Scalar(0.5) * _tmp0 * state(3, 0) - + dt * state(1, 0) + dt * state(4, 0) + state(0, 0); + _predict_state(1, 0) = acc * dt + state(1, 0); + _predict_state(2, 0) = state(2, 0); + _predict_state(3, 0) = state(3, 0); + _predict_state(4, 0) = dt * state(3, 0) + state(4, 0); + + return _predict_state; +} // NOLINT(readability/fn_size) + +// NOLINTNEXTLINE(readability/fn_size) +} // namespace sym diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/state.h b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/state.h new file mode 100644 index 00000000000..8c26dbd522e --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/generated_moving/state.h @@ -0,0 +1,55 @@ +// -------------------------------------------------- +// This file was autogenerated, do NOT modify by hand +// -------------------------------------------------- + +#ifndef EKF_STATE_H +#define EKF_STATE_H + +#include + +namespace vtest +{ +struct StateSample { + float pos_rel{}; + float vel_uav{}; + float bias{}; + float acc_target{}; + float vel_target{}; + + matrix::Vector Data() const + { + matrix::Vector state; + state.slice<1, 1>(0, 0) = pos_rel; + state.slice<1, 1>(1, 0) = vel_uav; + state.slice<1, 1>(2, 0) = bias; + state.slice<1, 1>(3, 0) = acc_target; + state.slice<1, 1>(4, 0) = vel_target; + return state; + }; + + const matrix::Vector &vector() const + { + return *reinterpret_cast*>(const_cast(reinterpret_cast(&pos_rel))); + }; + +}; +static_assert(sizeof(matrix::Vector) == sizeof(StateSample), "state vector doesn't match StateSample size"); +namespace Axis +{ +static constexpr uint8_t x{0}; +static constexpr uint8_t y{1}; +static constexpr uint8_t z{2}; +static constexpr uint8_t size{3}; +}; + +namespace State +{ +static constexpr uint8_t pos_rel{0}; +static constexpr uint8_t vel_uav{1}; +static constexpr uint8_t bias{2}; +static constexpr uint8_t acc_target{3}; +static constexpr uint8_t vel_target{4}; +static constexpr uint8_t size{5}; +}; +} +#endif // !EKF_STATE_H diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/utils/__init__.py b/src/modules/vision_target_estimator/Position/vtest_derivation/utils/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/modules/vision_target_estimator/Position/vtest_derivation/utils/derivation_utils.py b/src/modules/vision_target_estimator/Position/vtest_derivation/utils/derivation_utils.py new file mode 100644 index 00000000000..d166dafa7c3 --- /dev/null +++ b/src/modules/vision_target_estimator/Position/vtest_derivation/utils/derivation_utils.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + Copyright (c) 2026 PX4 Development Team + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. Neither the name PX4 nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +File: derivation_utils.py +Description: + Common functions used for the derivation of most estimators +""" + +import symforce.symbolic as sf + +import re + +def sign_no_zero(x) -> sf.Scalar: + """ + Returns -1 if x is negative, 1 if x is positive, and 1 if x is zero + """ + return 2 * sf.Min(sf.sign(x), 0) + 1 + +def add_epsilon_sign(expr, var, eps): + # Avoids a singularity at 0 while keeping the derivative correct + return expr.subs(var, var + eps * sign_no_zero(var)) + +def generate_px4_function(function_name, output_names): + from symforce.codegen import Codegen, CppConfig + import os + + return_key = output_names[0] if output_names is not None and len(output_names) == 1 else None + + codegen = Codegen.function( + function_name, + output_names=output_names, + return_key=return_key, + config=CppConfig(zero_initialization_sparsity_threshold=1)) + metadata = codegen.generate_function( + output_dir="generated", + skip_directory_nesting=True) + + for f in metadata.generated_files: + print(" |- {}".format(os.path.relpath(f, metadata.output_dir))) + + generated_path = os.path.abspath(metadata.generated_files[0]) + + with open(generated_path) as generated_file: + content = generated_file.read() + + content = content.replace("std::max", "math::max") + content = content.replace("std::min", "math::min") + content = content.replace("Eigen", "matrix") + content = content.replace("matrix/Dense", "matrix/math.hpp") + + # don't allow underscore + uppercase identifier naming (always reserved for any use) + content = re.sub(r'_([A-Z])', lambda x: '_' + x.group(1).lower(), content) + + with open(generated_path, "w") as generated_file: + generated_file.write(content) + +def generate_python_function(function_name, output_names): + from symforce.codegen import Codegen, PythonConfig + codegen = Codegen.function( + function_name, + output_names=output_names, + config=PythonConfig()) + + metadata = codegen.generate_function( + output_dir="generated", + skip_directory_nesting=True) + +def build_state_struct(state, T="float"): + out = "struct StateSample {\n" + + def TypeFromLength(len): + if len == 1: + return f"{T}" + elif len == 2: + return f"matrix::Vector2<{T}>" + elif len == 3: + return f"matrix::Vector3<{T}>" + elif len == 4: + return f"matrix::Quaternion<{T}>" + else: + raise NotImplementedError + + for key, val in state.items(): + out += f"\t{TypeFromLength(val.storage_dim())} {key}{{}};\n" + + state_size = state.storage_dim() + out += f"\n\tmatrix::Vector<{T}, {state_size}> Data() const {{\n" \ + + f"\t\tmatrix::Vector<{T}, {state_size}> state;\n" + + index = state.index() + for key in index: + out += f"\t\tstate.slice<{index[key].storage_dim}, 1>({index[key].offset}, 0) = {key};\n" + + out += "\t\treturn state;\n" + out += "\t};\n" # Data + + # const ref vector access + first_field = next(iter(state)) + + out += f"\n\tconst matrix::Vector<{T}, {state_size}>& vector() const {{\n" \ + + f"\t\treturn *reinterpret_cast*>(const_cast(reinterpret_cast(&{first_field})));\n" \ + + f"\t}};\n\n" + + out += "};\n" # StateSample + + out += f"static_assert(sizeof(matrix::Vector<{T}, {state_size}>) == sizeof(StateSample), \"state vector doesn't match StateSample size\");\n" + + return out + +def build_tangent_state_struct(state, tangent_state_index): + out = "namespace State {\n" + + for key in tangent_state_index.keys(): + out += f"\tstatic constexpr uint8_t {key}{{{tangent_state_index[key].idx}}};\n" + + out += f"\tstatic constexpr uint8_t size{{{state.tangent_dim()}}};\n" + out += "};\n" # namespace State + return out + +def build_axis_struct(): + out = "namespace Axis {\n" + + out += f"\tstatic constexpr uint8_t x{{{0}}};\n" + out += f"\tstatic constexpr uint8_t y{{{1}}};\n" + out += f"\tstatic constexpr uint8_t z{{{2}}};\n" + + out += f"\tstatic constexpr uint8_t size{{{3}}};\n" + out += "};\n" # namespace State + return out + +def generate_px4_state(state, tangent_state_index): + print("Generate EKF tangent state definition") + filename = "state.h" + f = open(f"./generated/{filename}", "w") + header = ["// --------------------------------------------------\n", + "// This file was autogenerated, do NOT modify by hand\n", + "// --------------------------------------------------\n", + "\n#ifndef EKF_STATE_H", + "\n#define EKF_STATE_H\n\n", + "#include \n\n", + "namespace vtest\n{\n"] + f.writelines(header) + + f.write(build_state_struct(state)) + f.write(build_axis_struct()) + f.write("\n") + f.write(build_tangent_state_struct(state, tangent_state_index)) + + f.write("}\n") # namespace vtest + f.write("#endif // !EKF_STATE_H\n") + f.close() + print(f" |- {filename}") diff --git a/src/modules/vision_target_estimator/VTEOosm.h b/src/modules/vision_target_estimator/VTEOosm.h new file mode 100644 index 00000000000..7ec1c93468b --- /dev/null +++ b/src/modules/vision_target_estimator/VTEOosm.h @@ -0,0 +1,490 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VTEOosm.h + * @brief Generic Out-Of-Sequence Measurement (OOSM) manager for VTE filters. + * + * Implements the "projected correction" OOSM algorithm backed by a fixed-size + * ring buffer of (time, state, covariance, input) snapshots. When a delayed + * scalar measurement arrives: + * 1. Locate the floor snapshot (newest snapshot with time <= meas.time_us). + * 2. Predict the floor forward to meas.time_us to get (x_meas, P_meas). + * 3. Compute the Kalman gain K at meas.time_us from (x_meas, P_meas). + * 4. Gate with NIS; reject if the normalized innovation squared exceeds the threshold. + * 5. Apply the correction locally to obtain the posterior at meas.time_us. + * 6. Write the posterior back into the timeline (replace the floor if times match, + * otherwise insert a new snapshot). This lets a subsequent delayed measurement + * falling in the same interval replay from the corrected state instead of the + * stale pre-measurement floor. + * 7. Propagate K forward with the transition matrix Phi and apply the projected + * correction K_i = Phi * K to every later history sample and to the live state. + * + * See docs/en/advanced_features/vision_target_estimator_advanced.md + * (section "OOSM Implementation") for the derivation and approximation + * assumptions. + */ + +#pragma once + +#include + +#include +#include +#include + +#include "common.h" + +namespace vision_target_estimator +{ + +// Tag type for filters that do not store control inputs (e.g. the orientation filter). +struct EmptyInput {}; + +/** + * @class OOSMManager + * @brief Maintains the snapshot history and fuses possibly-delayed scalar measurements. + * + * @tparam FilterT Owning filter type. Must expose the methods listed in + * the "FilterT concept" block below. + * @tparam StateDim Dimension of the state vector. + * @tparam InputT Control input stored per snapshot (e.g. acceleration for + * the position filter, or EmptyInput for orientation). + * @tparam HistorySize Capacity of the ring buffer (max 255). + * + * FilterT concept (the OOSM manager never touches the filter's internal state + * directly, it drives it exclusively through this interface): + * - void predictState: + * Propagate (x, P) over dt using control input u. + * + * - StateCov getTransitionMatrix: + * Phi used to project a correction forward (u cancels out in the + * correction, so only Phi is needed here). + * + * - void computeInnovation: + * Compute innovation y = z - H x and variance S = H P H^T + R. + * + * - void applyCorrection: + * Update (x, P) with an already-computed gain vector K. + * + * ScalarMeasT concept: must expose `uint64_t time_us` and a vector `H` of + * size StateDim, plus whatever the filter's computeInnovation expects. + */ +template +class OOSMManager +{ +public: + using StateVec = matrix::Vector; + using StateCov = matrix::SquareMatrix; + + struct Sample { + uint64_t time_us{0}; + StateVec state{}; + StateCov cov{}; + InputT input{}; // Control input applied from the previous snapshot up to this one. + }; + + static_assert(HistorySize > 0, "HistorySize must be > 0"); + static_assert(HistorySize <= 255, "HistorySize must fit in uint8_t"); + static constexpr uint8_t kHistorySize = static_cast(HistorySize); + static constexpr uint64_t kOosmMinTimeUs = vision_target_estimator::kOosmMinTimeUs; + static constexpr uint64_t kOosmMaxTimeUs = vision_target_estimator::kOosmMaxTimeUs; + + /** + * @brief Flat oldest-to-newest view of the ring buffer with one extra slot. + * + * The OOSM path works on this layout rather than on the ring buffer directly so that + * the corrected posterior at t_meas can be inserted between two snapshots without + * mutating the ring mid-algorithm. The +1 slot guarantees room for that insertion + * even when history is already full. + * + * Invariants: + * - count <= kCapacity (== HistorySize + 1) + * - samples[0..count) are sorted by time_us (strictly increasing) + */ + struct LinearTimeline { + static constexpr size_t kCapacity = static_cast(HistorySize) + 1u; + Sample samples[kCapacity] {}; + size_t count{0}; + }; + + OOSMManager() = default; + + void reset() + { + if (_history.valid()) { + _history.reset(); + } + } + + /** + * @brief Add a post-update state snapshot to history. + * @param input Control input applied to propagate from the previous snapshot to this one. + */ + void push(uint64_t time_us, const StateVec &state, const StateCov &cov, const InputT &input) + { + if (!_history.valid()) { + return; + } + + Sample sample{}; + sample.time_us = time_us; + sample.state = state; + sample.cov = cov; + sample.input = input; + + _history.push(sample); + } + + /** + * @brief Fuse a scalar measurement that may be delayed. + * + * Fresh measurements take the fast path and update the live state directly. + * Delayed measurements are fused at their own timestamp and the correction + * is projected forward through history and into the live state. + * + * @param filter Filter providing prediction / correction primitives. + * @param meas The scalar measurement (must provide `time_us` and `H`). + * @param now_us Current system time. + * @param nis_threshold NIS (chi-square) threshold; <= 0 disables gating. + * @param curr_state [In/Out] Live filter state, updated with the projected correction. + * @param curr_cov [In/Out] Live filter covariance. + * @param curr_input Control input currently active (used when the floor sample is the + * newest in history, since no "next" snapshot exists to describe the + * input over [t_floor, t_meas]). + */ + template + FusionResult fuse(FilterT &filter, const ScalarMeasT &meas, uint64_t now_us, + float nis_threshold, StateVec &curr_state, + StateCov &curr_cov, const InputT &curr_input) + { + FusionResult res{}; + + const uint64_t time_diff = (now_us >= meas.time_us) + ? (now_us - meas.time_us) + : (meas.time_us - now_us); + + // Fast path: measurement is effectively current, fuse it directly into the live state. + if (time_diff < kOosmMinTimeUs) { + StateVec K; + + if (processMeasurement(filter, curr_state, curr_cov, meas, nis_threshold, res, K)) { + filter.applyCorrection(curr_state, curr_cov, K, res.innov, res.innov_var); + res.status = FusionStatus::STATUS_FUSED_CURRENT; + } + + return res; + } + + // OOSM path: reject anything we cannot safely replay. + if (!_history.valid() || (_history.entries() == 0)) { + res.status = FusionStatus::STATUS_REJECT_EMPTY; + return res; + } + + const uint64_t newest_time_us = _history.get_newest().time_us; + const uint64_t oldest_time_us = _history.get_oldest().time_us; + + // Live time moved backwards or jumped too far forward relative to history: wipe and recover. + if (now_us < newest_time_us || (now_us - newest_time_us) > kOosmMaxTimeUs) { + reset(); + res.status = FusionStatus::STATUS_REJECT_STALE; + return res; + } + + // Measurement time is in the future beyond the small tolerance used for the fast path. + if (meas.time_us > now_us + kOosmMinTimeUs) { + res.status = FusionStatus::STATUS_REJECT_TOO_NEW; + return res; + } + + // Measurement predates the buffer window: we cannot reconstruct a floor for it. + if (time_diff > kOosmMaxTimeUs || meas.time_us < oldest_time_us) { + res.status = FusionStatus::STATUS_REJECT_TOO_OLD; + return res; + } + + // Unroll history into a flat oldest->newest view so we can insert the corrected posterior + // without mutating the ring buffer mid-algorithm. + LinearTimeline linear_timeline{}; + copyHistoryToLinearTimeline(linear_timeline); + + // Floor: newest snapshot with time <= meas.time_us. Scan from newest backwards so we stop early. + bool floor_found = false; + size_t floor_pos = 0; + + for (size_t i = linear_timeline.count; i-- > 0;) { + if (linear_timeline.samples[i].time_us <= meas.time_us) { + floor_pos = i; + floor_found = true; + break; + } + } + + if (!floor_found) { + res.status = FusionStatus::STATUS_REJECT_TOO_OLD; + return res; + } + + const Sample &sample_floor = linear_timeline.samples[floor_pos]; + const uint64_t t_floor_us = sample_floor.time_us; + + // Pick the control input that was active over [t_floor, t_meas]. Each snapshot stores the + // input that drove the filter *to* that snapshot, so the active input during the interval + // starting at `floor` is the one attached to the next snapshot. If the floor is already the + // newest sample, no "next" snapshot exists and we fall back to the live input. + InputT input_interval = curr_input; + + if (floor_pos + 1 < linear_timeline.count) { + input_interval = linear_timeline.samples[floor_pos + 1].input; + } + + const float dt_meas = (meas.time_us - t_floor_us) * kMicrosecondsToSeconds; + + // Predict the floor forward to the exact measurement time. dt_meas == 0 means the floor + // snapshot is already at meas time, so the copy below is the correct state/cov at t_meas. + StateVec x_meas = sample_floor.state; + StateCov P_meas = sample_floor.cov; + + if (dt_meas > 0.f) { + filter.predictState(dt_meas, input_interval, sample_floor.state, sample_floor.cov, x_meas, P_meas); + } + + // Compute K at t_meas and gate on NIS / covariance validity. + StateVec K_meas; + + if (!processMeasurement(filter, x_meas, P_meas, meas, nis_threshold, res, K_meas)) { + return res; // STATUS_REJECT_NIS or STATUS_REJECT_COV + } + + // Apply the correction at t_meas locally. We will also write it back into the timeline so + // that any later delayed measurement falling in the same interval can use this corrected + // posterior as its floor (otherwise it would replay from the stale pre-measurement sample). + filter.applyCorrection(x_meas, P_meas, K_meas, res.innov, res.innov_var); + + // Write the corrected posterior into the timeline. If meas lands exactly on the floor + // timestamp we overwrite it, otherwise we insert a new snapshot right after the floor. + const size_t corrected_pos = + insertCorrectedPosteriorInLinearTimeline(linear_timeline, floor_pos, meas.time_us, + x_meas, P_meas, input_interval); + + // Projected correction: walk forward from t_meas, accumulate Phi across each step, and apply + // K_i = Phi_cumulative * K_meas to every later snapshot. The control-input term cancels out + // in the error dynamics, so only Phi is needed here (see docs). + StateCov Phi_step; + StateCov Phi_cumulative; + Phi_cumulative.setIdentity(); + + uint64_t prev_time_us = meas.time_us; + uint8_t steps = 0; + + // Iterate from t_meas up to the newest stored sample. + for (size_t i = corrected_pos + 1; i < linear_timeline.count; ++i) { + Sample &sample = linear_timeline.samples[i]; + + const float dt = (sample.time_us - prev_time_us) * kMicrosecondsToSeconds; + + // Get transition matrix for the error state dynamics + Phi_step = filter.getTransitionMatrix(dt); + Phi_cumulative = Phi_step * Phi_cumulative; + + // Project K: K_k = Phi * K_{k-1} + const StateVec K_proj = Phi_cumulative * K_meas; + + // Apply correction to history + filter.applyCorrection(sample.state, sample.cov, K_proj, res.innov, res.innov_var); + + prev_time_us = sample.time_us; + steps++; + } + + // Project the remaining interval [newest_history, now] and + // apply the final correction to the live state. + if (now_us > prev_time_us) { + const float dt_now = (now_us - prev_time_us) * kMicrosecondsToSeconds; + Phi_step = filter.getTransitionMatrix(dt_now); + Phi_cumulative = Phi_step * Phi_cumulative; + } + + const StateVec K_final = Phi_cumulative * K_meas; + filter.applyCorrection(curr_state, curr_cov, K_final, res.innov, res.innov_var); + + // Commit the modified timeline back into the ring buffer so the next OOSM call sees the + // corrected history. If we inserted a sample and overflowed capacity, the oldest entry is + // dropped. + rebuildHistoryFromLinearTimeline(linear_timeline); + + res.status = FusionStatus::STATUS_FUSED_OOSM; + res.history_steps = steps; + + return res; + } + +private: + // Test-only access: the companion struct is defined in the unit test translation unit and reaches + // the private helpers without needing any #ifdef or production-side wrappers. + template friend struct OOSMManagerTestAccess; + + // Run NIS / covariance gating and compute the Kalman gain K for the given (state, cov, meas). + // Returns true iff the measurement is accepted; out_res is populated with innov/innov_var/test_ratio. + template + bool processMeasurement(FilterT &filter, const StateVec &state, + const StateCov &cov, const ScalarMeasT &meas, + float nis_threshold, FusionResult &out_res, + StateVec &out_K) + { + float innov = 0.f; + float innov_var = 0.f; + + filter.computeInnovation(state, cov, meas, innov, innov_var); + + out_res.innov = innov; + out_res.innov_var = innov_var; + + // Reject degenerate or non-finite innovation variance before inverting it. + if (!PX4_ISFINITE(innov_var) || (innov_var < kMinInnovationVariance)) { + out_res.status = FusionStatus::STATUS_REJECT_COV; + out_res.test_ratio = -1.f; + return false; + } + + const float beta = (innov * innov) / innov_var; + + if (nis_threshold > 0.f) { + out_res.test_ratio = beta / nis_threshold; + + if (beta > nis_threshold) { + out_res.status = FusionStatus::STATUS_REJECT_NIS; + return false; + } + + } else { + out_res.test_ratio = -1.f; + } + + out_K = (cov * meas.H) / innov_var; + return true; + } + + /** + * @brief Copy the ring buffer into a flat oldest-to-newest array. + * + * Walking the ring via _history.next() keeps the traversal canonical and avoids any + * manual modular arithmetic on uint8_t indices (which can wrap before the bounds check + * when HistorySize approaches 255). + * + * Post-condition: out.count == _history.entries(), with out.count <= kHistorySize < kCapacity, + * so no out-of-bounds writes are possible by construction. + */ + void copyHistoryToLinearTimeline(LinearTimeline &out) + { + out.count = 0; + + if (!_history.valid()) { + return; + } + + const int history_count = _history.entries(); + + if (history_count == 0) { + return; + } + + uint8_t idx = _history.get_oldest_index(); + + for (int i = 0; i < history_count; ++i) { + out.samples[out.count] = _history[idx]; + out.count++; + idx = _history.next(idx); + } + } + + /** + * @brief Insert the corrected posterior at t_meas into the timeline. + * + * When meas time matches the floor exactly we overwrite the floor's state/cov in place, + * otherwise we shift the tail right by one slot and insert a fresh snapshot after the floor. + * The +1 capacity slot in LinearTimeline guarantees room for the insertion even when history + * was already at capacity. + * + * @return Position of the corrected posterior in the timeline. + */ + size_t insertCorrectedPosteriorInLinearTimeline(LinearTimeline &tl, size_t floor_pos, + uint64_t meas_time_us, + const StateVec &x_posterior, + const StateCov &P_posterior, + const InputT &input_interval) + { + if (tl.samples[floor_pos].time_us == meas_time_us) { + tl.samples[floor_pos].state = x_posterior; + tl.samples[floor_pos].cov = P_posterior; + return floor_pos; + } + + const size_t corrected_pos = floor_pos + 1; + + // Shift [corrected_pos .. count) one slot to the right to make room. + // tl.count <= kHistorySize at entry (copy never exceeds it), so writing tl.samples[count] + // stays within the kCapacity = HistorySize + 1 slots. + for (size_t i = tl.count; i > corrected_pos; --i) { + tl.samples[i] = tl.samples[i - 1]; + } + + tl.samples[corrected_pos].time_us = meas_time_us; + tl.samples[corrected_pos].state = x_posterior; + tl.samples[corrected_pos].cov = P_posterior; + tl.samples[corrected_pos].input = input_interval; + tl.count++; + return corrected_pos; + } + + /** + * @brief Push the (possibly augmented) timeline back into the ring buffer. + * + * If an insertion pushed the timeline past ring-buffer capacity, the oldest sample is dropped. + */ + void rebuildHistoryFromLinearTimeline(const LinearTimeline &tl) + { + _history.reset(); + + const size_t start = (tl.count > kHistorySize) ? (tl.count - kHistorySize) : 0; + + for (size_t i = start; i < tl.count; ++i) { + _history.push(tl.samples[i]); + } + } + + TimestampedRingBuffer _history; +}; + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/VisionTargetEst.cpp b/src/modules/vision_target_estimator/VisionTargetEst.cpp new file mode 100644 index 00000000000..1e066aa9d9c --- /dev/null +++ b/src/modules/vision_target_estimator/VisionTargetEst.cpp @@ -0,0 +1,780 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VisionTargetEst.cpp + * @brief Handles the position and orientation estimators. + * + * @author Jonas Perolini + * + */ + +#include + +#include + +#include "VisionTargetEst.h" + +namespace vision_target_estimator +{ + +ModuleBase::Descriptor VisionTargetEst::desc{task_spawn, custom_command, print_usage}; + +VisionTargetEst::VisionTargetEst() : + ModuleParams(nullptr), + ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::vte) +{ + _vte_input_pub.advertise(); +} + +VisionTargetEst::~VisionTargetEst() +{ + perf_free(_cycle_perf_pos); + perf_free(_cycle_perf_yaw); + perf_free(_cycle_perf); +} + +int VisionTargetEst::task_spawn(int argc, char *argv[]) +{ +#if !defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) || !CONFIG_MODULES_VISION_TARGET_ESTIMATOR + PX4_ERR("Vision Target Estimator cannot run without CONFIG_MODULES_VISION_TARGET_ESTIMATOR (missing topics)."); + return PX4_ERROR; +#endif // !CONFIG_MODULES_VISION_TARGET_ESTIMATOR + +#if defined(CONFIG_MODULES_LANDING_TARGET_ESTIMATOR) && CONFIG_MODULES_LANDING_TARGET_ESTIMATOR + PX4_ERR("Vision Target Estimator cannot run with CONFIG_MODULES_LANDING_TARGET_ESTIMATOR enabled."); + return PX4_ERROR; +#endif // CONFIG_MODULES_LANDING_TARGET_ESTIMATOR + + VisionTargetEst *instance = new VisionTargetEst(); + + if (instance) { + desc.object.store(instance); + desc.task_id = task_id_is_work_queue; + + if (instance->init()) { + return PX4_OK; + } + + } else { + PX4_ERR("alloc failed"); + } + + delete instance; + desc.object.store(nullptr); + desc.task_id = -1; + + return PX4_ERROR; +} + +void VisionTargetEst::Run() +{ + if (should_exit()) { + handleExit(); + return; + } + + updateTaskTopics(); + + if (_parameter_update_sub.updated()) { + updateParams(); + } + + // If a new task is available, stop the estimators if they were already running + if (setNewTaskIfAvailable()) { + stopAllEstimators(); + } + + // No task running: switch to a low-rate polling mode instead of waking up on every attitude update + if (noActiveTask()) { + static constexpr uint32_t kIdleUpdateIntervalUs = 200_ms; + + if (_vehicle_attitude_sub.registered()) { + _vehicle_attitude_sub.unregisterCallback(); + ScheduleOnInterval(kIdleUpdateIntervalUs); + } + + return; + } + + // Task is active: ensure we're callback-driven and not running a periodic timer + if (!_vehicle_attitude_sub.registered()) { + if (_vehicle_attitude_sub.registerCallback()) { + ScheduleClear(); + + } else { + const uint32_t estimator_update_period_us = static_cast(math::min(kPosUpdatePeriodUs, + kYawUpdatePeriodUs)); + ScheduleOnInterval(estimator_update_period_us); + } + } + + // Task is running, check if an estimator must be started or re-started + startEstIfNeeded(); + + const bool task_completed = isCurrentTaskComplete(); + + if (task_completed) { + stopAllEstimators(); + _current_task_ptr = nullptr; + return; + } + + restartTimedOutEstimators(); + + if (noEstRunning()) { + return; + } + + // Early return checks passed, start filter computations. + updateEstimators(); +} + +void VisionTargetEst::handleExit() +{ + _vehicle_attitude_sub.unregisterCallback(); + exit_and_cleanup(desc); +} + +bool VisionTargetEst::init() +{ + if (!_param_vte_pos_en.get() && !_param_vte_yaw_en.get()) { + PX4_WARN("VTE not enabled, update VTE_POS_EN or VTE_YAW_EN"); + return false; + } + + if (!_vehicle_attitude_sub.registerCallback()) { + PX4_ERR("VTE vehicle_attitude callback registration failed!"); + return false; + } + + _vte_position_enabled = false; + _vte_orientation_enabled = false; + + // Params with reboot required + if (_param_vte_pos_en.get()) { + PX4_DEBUG("VTE position estimator enabled."); + + if (_vte_position.init()) { + _vte_position_enabled = true; + + } else { + PX4_ERR("VTE position estimator initialisation failed"); + } + } + + if (_param_vte_yaw_en.get()) { + PX4_DEBUG("VTE yaw estimator enabled."); + + if (_vte_orientation.init()) { + _vte_orientation_enabled = true; + + } else { + PX4_ERR("VTE yaw estimator initialisation failed"); + } + } + + // Params that impact the estimators + updateParams(); + + return _vte_position_enabled || _vte_orientation_enabled; +} + +void VisionTargetEst::updateParams() +{ + parameter_update_s pupdate; + _parameter_update_sub.copy(&pupdate); + + ModuleParams::updateParams(); + + const uint8_t new_vte_task_mask = static_cast(_param_vte_task_mask.get()); + + if (new_vte_task_mask != _vte_task_mask) { + + _vte_task_mask = new_vte_task_mask; + + if (_vte_task_mask < 1) { + PX4_WARN("VTE no task, update VTE_TASK_MASK"); + + } else { + PX4_DEBUG("VTE VTE_TASK_MASK config: "); + + for (const VteTask *task : _task_registry) { + if (isTaskMaskBitEnabled(task->maskBit())) { + PX4_DEBUG(" %s", task->name()); + } + } + } + } + + const uint16_t requested_aid_mask = adjustAidMask(_param_vte_aid_mask.get()); + const bool aid_mask_changed = requested_aid_mask != _vte_aid_mask.value; + _vte_aid_mask.value = requested_aid_mask; + + if (_vte_position_enabled) { + _vte_position.setVteAidMask(requested_aid_mask); + } + + if (_vte_orientation_enabled) { + _vte_orientation.setVteAidMask(requested_aid_mask); + } + + if (aid_mask_changed) { + printAidMask(); + } + + const hrt_abstime vte_timeout_us = static_cast(_param_vte_btout.get() * 1_s); + _vte_position.setVteTimeout(vte_timeout_us); + _vte_orientation.setVteTimeout(vte_timeout_us); + + const hrt_abstime target_valid_timeout_us = static_cast(_param_vte_tgt_tout.get() * 1_s); + _vte_position.setTargetValidTimeout(target_valid_timeout_us); + _vte_orientation.setTargetValidTimeout(target_valid_timeout_us); + + const hrt_abstime meas_recent_timeout_us = static_cast(_param_vte_mrec_tout.get() * 1_s); + _vte_position.setMeasRecentTimeout(meas_recent_timeout_us); + _vte_orientation.setMeasRecentTimeout(meas_recent_timeout_us); + + const hrt_abstime meas_updated_timeout_us = static_cast(_param_vte_mupd_tout.get() * 1_s); + _vte_position.setMeasUpdatedTimeout(meas_updated_timeout_us); + + if (_vte_position_enabled && _position_estimator_running + && !_vte_position.fusionEnabled()) { + PX4_DEBUG("VTE position estimator stopped, no fusion source selected."); + stopPosEst(); + } + + if (_vte_orientation_enabled && _orientation_estimator_running + && !_vte_orientation.fusionEnabled()) { + PX4_DEBUG("VTE yaw estimator stopped, no fusion source selected."); + stopYawEst(); + } +} + +uint16_t VisionTargetEst::adjustAidMask(const int input_vte_aid_mask) +{ + SensorFusionMaskU new_aid_mask{}; + new_aid_mask.value = input_vte_aid_mask; + +#if defined(CONFIG_VTEST_MOVING) + + if (new_aid_mask.flags.use_mission_pos) { + PX4_WARN("VTE for moving target. Disabling mission land position data fusion."); + new_aid_mask.flags.use_mission_pos = false; + } + +#endif // CONFIG_VTEST_MOVING + + if (new_aid_mask.flags.use_target_gps_pos && new_aid_mask.flags.use_mission_pos) { + PX4_WARN("VTE invalid aid mask: both target GPS and mission land enabled."); + PX4_WARN("Disabling mission land position fusion."); + new_aid_mask.flags.use_mission_pos = false; + } + + return new_aid_mask.value; +} + +void VisionTargetEst::printAidMask() +{ + PX4_DEBUG("VTE VTE_AID_MASK config: "); + + if (_vte_aid_mask.flags.use_vision_pos) {PX4_DEBUG(" vision relative position fusion enabled");} + + if (_vte_aid_mask.flags.use_target_gps_pos) {PX4_DEBUG(" target GPS position fusion enabled");} + + if (_vte_aid_mask.flags.use_target_gps_vel) {PX4_DEBUG(" target GPS velocity fusion enabled");} + + if (_vte_aid_mask.flags.use_mission_pos) {PX4_DEBUG(" mission land position fusion enabled");} + + if (_vte_aid_mask.flags.use_uav_gps_vel) {PX4_DEBUG(" UAV GPS velocity fusion enabled");} + + if (_vte_aid_mask.value == 0) {PX4_WARN(" no data fusion. Modify VTE_AID_MASK");} +} + +void VisionTargetEst::resetAccDownsample() +{ + _vehicle_acc_ned_sum.setAll(0); + _acc_sample_count = 0; + _last_acc_reset = nowUs(); +} + +bool VisionTargetEst::startYawEst() +{ + if (!_vte_orientation_enabled) { + return false; + } + + PX4_INFO("Starting Orientation Vision Target Estimator."); + _vte_orientation.resetFilter(); + return true; +} + +bool VisionTargetEst::startPosEst() +{ + if (!_vte_position_enabled) { + return false; + } + + resetAccDownsample(); + + PX4_INFO("Starting Position Vision Target Estimator."); + _vte_position.resetFilter(); + + if (_current_task_ptr) { + _current_task_ptr->onPosEstStart(_vte_position); + } + + return true; +} + +bool VisionTargetEst::setNewTaskIfAvailable() +{ + // Registry is ordered by priority (highest first) + for (VteTask *task : _task_registry) { + if (!isTaskMaskBitEnabled(task->maskBit())) { + continue; + } + + if (!task->isReady()) { + continue; + } + + if (_current_task_ptr == task) { + return false; + } + + PX4_INFO("VTE, %s task requested.", task->name()); + task->onActivate(); + _current_task_ptr = task; + return true; + } + + return false; +} + +bool VisionTargetEst::isCurrentTaskComplete() +{ + if (!_current_task_ptr) { + return false; + } + + // Mask-bit deselection (user disabled this task in VTE_TASK_MASK). + if (!isTaskMaskBitEnabled(_current_task_ptr->maskBit())) { + PX4_DEBUG("VTE_TASK_MASK updated, %s task completed.", _current_task_ptr->name()); + return true; + } + + return _current_task_ptr->isComplete(); +} + +void VisionTargetEst::updateTaskTopics() +{ + for (VteTask *task : _task_registry) { + if (isTaskMaskBitEnabled(task->maskBit())) { + task->pollStatus(); + } + } +} + +void VisionTargetEst::stopAllEstimators() +{ + if (_vte_position_enabled && _position_estimator_running) { + stopPosEst(); + } + + if (_vte_orientation_enabled && _orientation_estimator_running) { + stopYawEst(); + } +} + +void VisionTargetEst::stopPosEst() +{ + PX4_INFO("Stopping Position Vision Target Estimator."); + + if (_vte_position_enabled) { + _vte_position.resetFilter(); + } + + _position_estimator_running = false; +} + +void VisionTargetEst::stopYawEst() +{ + PX4_INFO("Stopping Orientation Vision Target Estimator."); + + if (_vte_orientation_enabled) { + _vte_orientation.resetFilter(); + } + + _orientation_estimator_running = false; +} + +void VisionTargetEst::startEstIfNeeded() +{ + // Only start the estimator if fusion is enabled, otherwise it will timeout + if (!_position_estimator_running && _vte_position_enabled && _vte_position.fusionEnabled()) { + _position_estimator_running = startPosEst(); + } + + if (!_orientation_estimator_running && _vte_orientation_enabled && _vte_orientation.fusionEnabled()) { + _orientation_estimator_running = startYawEst(); + } +} + +void VisionTargetEst::restartTimedOutEstimators() +{ + bool restart_needed = false; + + if (_position_estimator_running && _vte_position.timedOut()) { + stopPosEst(); + PX4_WARN("Estimator TIMEOUT, position VTE stopped."); + restart_needed = true; + } + + if (_orientation_estimator_running && _vte_orientation.timedOut()) { + stopYawEst(); + PX4_WARN("Estimator TIMEOUT, orientation VTE stopped."); + restart_needed = true; + } + + if (restart_needed) { + startEstIfNeeded(); + } +} + +void VisionTargetEst::updateEstimators() +{ + perf_begin(_cycle_perf); + + if (_vte_position_enabled && _position_estimator_running) { + updateGpsAntennaOffset(); + + matrix::Vector3f vel_offset_body{}; + const bool vel_offset_updated = computeGpsVelocityOffset(vel_offset_body); + + matrix::Vector3f vehicle_acc_ned{}; + matrix::Quaternionf q_att{}; + matrix::Vector3f gps_pos_offset_ned{}; + matrix::Vector3f vel_offset_ned = vel_offset_body; + bool acc_valid = false; + + if (pollEstimatorInput(vehicle_acc_ned, q_att, gps_pos_offset_ned, vel_offset_ned, vel_offset_updated, + acc_valid)) { + _last_att = q_att; + + /* If the acceleration has been averaged for too long, reset the accumulator */ + if (hasTimedOut(_last_acc_reset, kMinAccDownsampleTimeoutUs)) { + PX4_DEBUG("Forced acc downsample reset"); + resetAccDownsample(); + } + + if (acc_valid) { + _vehicle_acc_ned_sum += vehicle_acc_ned; + _acc_sample_count++; + } + + const uint32_t acc_sample_count = _acc_sample_count; + + if ((acc_sample_count > 0) && updateWhenIntervalElapsed(_last_update_pos, kPosUpdatePeriodUs)) { + updatePosEst(gps_pos_offset_ned, vel_offset_ned, vel_offset_updated, acc_sample_count); + resetAccDownsample(); + } + } + } + + if (_vte_orientation_enabled && _orientation_estimator_running + && updateWhenIntervalElapsed(_last_update_yaw, kYawUpdatePeriodUs)) { + updateYawEst(); + } + + perf_end(_cycle_perf); +} + +void VisionTargetEst::updatePosEst(const matrix::Vector3f &gps_pos_offset_ned, + const matrix::Vector3f &vel_offset_ned, + const bool vel_offset_updated, + const uint32_t acc_sample_count) +{ + perf_begin(_cycle_perf_pos); + + if (acc_sample_count == 0) { + perf_end(_cycle_perf_pos); + return; + } + + LocalPose local_pose{}; + const bool local_pose_updated = pollLocalPose(local_pose); + + if (local_pose_updated) { + _vte_position.setLocalVelocity(local_pose.vel_xyz, local_pose.vel_valid, local_pose.timestamp); + _vte_position.setLocalPosition(local_pose.xyz, local_pose.pos_valid, local_pose.timestamp); + } + + _vte_position.setGpsPosOffset(gps_pos_offset_ned, _gps_pos_is_offset); + + if (vel_offset_updated) { + _vte_position.setVelOffset(vel_offset_ned); + } + + const matrix::Vector3f vehicle_acc_ned_sampled = _vehicle_acc_ned_sum / acc_sample_count; + + _vte_position.update(vehicle_acc_ned_sampled); + publishVteInput(vehicle_acc_ned_sampled, _last_att, acc_sample_count); + + perf_end(_cycle_perf_pos); +} + +void VisionTargetEst::updateYawEst() +{ + perf_begin(_cycle_perf_yaw); + _vte_orientation.update(); + perf_end(_cycle_perf_yaw); +} + +void VisionTargetEst::publishVteInput(const matrix::Vector3f &vehicle_acc_ned_sampled, + const matrix::Quaternionf &q_att_sampled, + uint32_t acc_sample_count) +{ + vte_input_s vte_input_report{}; + vte_input_report.timestamp = nowUs(); + vte_input_report.timestamp_sample = _vehicle_acc_body.timestamp; + + vehicle_acc_ned_sampled.copyTo(vte_input_report.acc_xyz); + q_att_sampled.copyTo(vte_input_report.q_att); + vte_input_report.acc_sample_count = acc_sample_count; + + _vte_input_pub.publish(vte_input_report); +} + +bool VisionTargetEst::computeGpsVelocityOffset(matrix::Vector3f &vel_offset_body) +{ + if (!_gps_pos_is_offset) { + return false; + } + + vehicle_angular_velocity_s vehicle_angular_velocity; + + if (!_vehicle_angular_velocity_sub.update(&vehicle_angular_velocity)) { + return false; + } + + // If the GPS antenna is not at the center of mass, when the drone rotates around the center of mass, the GPS will record a velocity. + const matrix::Vector3f ang_vel = matrix::Vector3f(vehicle_angular_velocity.xyz); + vel_offset_body = ang_vel % _gps_pos_offset_xyz; // Get extra velocity from drone's rotation + + return true; +} + +bool VisionTargetEst::updateGpsAntennaOffset() +{ + sensor_gps_s vehicle_gps_position{}; + + if (!_vehicle_gps_position_sub.update(&vehicle_gps_position)) { + return false; + } + + _gps_pos_offset_xyz = matrix::Vector3f(vehicle_gps_position.antenna_offset_x, + vehicle_gps_position.antenna_offset_y, + vehicle_gps_position.antenna_offset_z); + + static constexpr float kMinGpsOffsetM = 0.01f; // Consider GNSS not offset below 1cm + _gps_pos_is_offset = (fabsf(_gps_pos_offset_xyz(0)) > kMinGpsOffsetM) + || (fabsf(_gps_pos_offset_xyz(1)) > kMinGpsOffsetM) + || (fabsf(_gps_pos_offset_xyz(2)) > kMinGpsOffsetM); + + return true; +} + +bool VisionTargetEst::pollLocalPose(LocalPose &local_pose) +{ + vehicle_local_position_s vehicle_local_position; + + if (!_vehicle_local_position_sub.update(&vehicle_local_position)) { + return false; + } + + local_pose.xyz(0) = vehicle_local_position.x; + local_pose.xyz(1) = vehicle_local_position.y; + local_pose.xyz(2) = vehicle_local_position.z; + local_pose.pos_valid = vehicle_local_position.xy_valid && vehicle_local_position.z_valid; + + local_pose.vel_xyz(0) = vehicle_local_position.vx; + local_pose.vel_xyz(1) = vehicle_local_position.vy; + local_pose.vel_xyz(2) = vehicle_local_position.vz; + local_pose.vel_valid = vehicle_local_position.v_xy_valid && vehicle_local_position.v_z_valid; + + local_pose.timestamp = vehicle_local_position.timestamp; + + return true; +} + +bool VisionTargetEst::pollEstimatorInput(matrix::Vector3f &vehicle_acc_ned, matrix::Quaternionf &quat_att, + matrix::Vector3f &gps_pos_offset_ned, matrix::Vector3f &vel_offset_ned, + const bool vel_offset_updated, bool &acc_valid) +{ + vehicle_attitude_s vehicle_attitude{}; + vehicle_acceleration_s vehicle_acceleration{}; + + const bool vehicle_attitude_updated = _vehicle_attitude_sub.update(&vehicle_attitude); + const bool vehicle_acceleration_updated = _vehicle_acceleration_sub.update(&vehicle_acceleration); + + if (!vehicle_attitude_updated) { + return false; + } + + if (vehicle_acceleration_updated) { + _vehicle_acc_body.xyz = matrix::Vector3f(vehicle_acceleration.xyz); + _vehicle_acc_body.timestamp = vehicle_acceleration.timestamp; + } + + _vehicle_acc_body.valid = (_vehicle_acc_body.timestamp != 0) + && !hasTimedOut(_vehicle_acc_body.timestamp, kAccUpdatedTimeoutUs); + acc_valid = _vehicle_acc_body.valid; + + /* Transform FRD body acc to NED */ + const matrix::Quaternionf q_att(&vehicle_attitude.q[0]); // (w,x,y,z) + quat_att = q_att; + + if (acc_valid) { + /* Compensate for gravity. */ + const matrix::Vector3f gravity_ned(0.f, 0.f, kGravityMps2); + vehicle_acc_ned = quat_att.rotateVector(_vehicle_acc_body.xyz) + gravity_ned; + + } else { + vehicle_acc_ned.setAll(0.f); + } + + /* Rotate position and velocity offset into ned frame */ + if (_gps_pos_is_offset) { + gps_pos_offset_ned = quat_att.rotateVector(_gps_pos_offset_xyz); + + if (vel_offset_updated) { + vel_offset_ned = quat_att.rotateVector(vel_offset_ned); + } + + } else { + gps_pos_offset_ned.setAll(0.f); + vel_offset_ned.setAll(0.f); + } + + return true; +} + +bool VisionTargetEst::updateWhenIntervalElapsed(hrt_abstime &last_time, const hrt_abstime interval) const +{ + const hrt_abstime now = nowUs(); + + if (hasTimedOutAt(now, last_time, interval)) { + last_time = now; + return true; + } + + return false; +} + +int VisionTargetEst::print_status() +{ + const auto yes_no = [](const bool value) { return value ? "yes" : "no"; }; + + PX4_INFO("VTE running"); +#if defined(CONFIG_VTEST_MOVING) + PX4_INFO("target model: moving"); + PX4_WARN("Caution: VTE for moving targets is a beta feature"); +#else + PX4_INFO("target model: static"); +#endif // CONFIG_VTEST_MOVING + PX4_INFO("work queue: %s", px4::wq_configurations::vte.name); + PX4_INFO("current task: %s", _current_task_ptr ? _current_task_ptr->name() : "none"); + PX4_INFO("task mask: 0x%02x (prec_land: %s, debug: %s)", + static_cast(_vte_task_mask), + yes_no(isTaskMaskBitEnabled(task_bits::kPrecLand)), + yes_no(isTaskMaskBitEnabled(task_bits::kDebug))); + PX4_INFO("aid mask: 0x%04x", static_cast(_vte_aid_mask.value)); + PX4_INFO(" vision pos: %s, target gps pos: %s, mission pos: %s", + yes_no(_vte_aid_mask.flags.use_vision_pos), + yes_no(_vte_aid_mask.flags.use_target_gps_pos), + yes_no(_vte_aid_mask.flags.use_mission_pos)); + PX4_INFO(" uav gps vel: %s, target gps vel: %s", + yes_no(_vte_aid_mask.flags.use_uav_gps_vel), + yes_no(_vte_aid_mask.flags.use_target_gps_vel)); + + PX4_INFO("position vte: enabled: %s, available: %s, running: %s, fusing: %s, timed out: %s", + yes_no(_param_vte_pos_en.get()), + yes_no(_vte_position_enabled), + yes_no(_position_estimator_running), + yes_no(_vte_position.fusionEnabled()), + yes_no(_vte_position.timedOut())); + + if (_position_estimator_running) { + _vte_position.print_status(); + } + + PX4_INFO("orientation vte: enabled: %s, available: %s, running: %s, fusing: %s, timed out: %s", + yes_no(_param_vte_yaw_en.get()), + yes_no(_vte_orientation_enabled), + yes_no(_orientation_estimator_running), + yes_no(_vte_orientation.fusionEnabled()), + yes_no(_vte_orientation.timedOut())); + + if (_orientation_estimator_running) { + _vte_orientation.print_status(); + } + + return 0; +} +int VisionTargetEst::print_usage(const char *reason) +{ + if (reason != nullptr) { + PX4_ERR("%s\n", reason); + } + + PRINT_MODULE_DESCRIPTION( + R"DESCR_STR( +### Description +Module to estimate the position and orientation of a target using relative sensors. + +The module runs periodically on the px4::wq_configurations::vte queue. +)DESCR_STR"); + + PRINT_MODULE_USAGE_NAME("vision_target_estimator", "system"); + PRINT_MODULE_USAGE_COMMAND_DESCR("start", "Start the background task"); + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); + return 0; +} + +extern "C" __EXPORT int vision_target_estimator_main(int argc, char *argv[]) +{ + return ModuleBase::main(VisionTargetEst::desc, argc, argv); +} + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/VisionTargetEst.h b/src/modules/vision_target_estimator/VisionTargetEst.h new file mode 100644 index 00000000000..825727874f3 --- /dev/null +++ b/src/modules/vision_target_estimator/VisionTargetEst.h @@ -0,0 +1,237 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VisionTargetEst.h + * @brief Handles the position and orientation estimators. + * + * @author Jonas Perolini + * + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Orientation/VTEOrientation.h" +#include "Position/VTEPosition.h" +#include "common.h" +#include "tasks/PrecLandTask.h" +#include "tasks/VteTask.h" + +class VisionTargetEstTest; +class VisionTargetEstTestable; + +namespace vision_target_estimator +{ + +class VisionTargetEst : public ModuleBase, public ModuleParams, public px4::ScheduledWorkItem +{ +public: + static Descriptor desc; + + VisionTargetEst(); + virtual ~VisionTargetEst(); + + /** @see ModuleBase */ + static int custom_command(int argc, char *argv[]) + { + return print_usage("unknown command"); + } + + /** @see ModuleBase */ + static int print_usage(const char *reason = nullptr); + + /** @see ModuleBase::print_status() */ + int print_status() override; + + bool init(); + + static int task_spawn(int argc, char *argv[]); + + friend class ::VisionTargetEstTest; + friend class ::VisionTargetEstTestable; + +protected: + static constexpr hrt_abstime kPosUpdatePeriodUs{kEstimatorUpdatePeriodUs}; // 50 Hz position filter cadence. + static constexpr hrt_abstime kYawUpdatePeriodUs{kEstimatorUpdatePeriodUs}; // 50 Hz yaw filter cadence. + static constexpr hrt_abstime kMinAccDownsampleTimeoutUs{2 * kPosUpdatePeriodUs}; // Reset the acc averager if it's been collecting >=40 ms (<25 Hz). + static constexpr hrt_abstime kAccUpdatedTimeoutUs{kEstimatorUpdatePeriodUs}; // Max age for a fresh acceleration sample. + + struct LocalPose { + bool pos_valid = false; + matrix::Vector3f xyz{}; + + bool vel_valid = false; + matrix::Vector3f vel_xyz{}; + + hrt_abstime timestamp{0}; + }; + + // One work-item cycle: handle task lifecycle, start/stop estimators, and drive fusion when active. + void Run() override; + void updateParams() override; + // Cancel the attitude callback and signal ModuleBase to tear the instance down. + void handleExit(); + void stopAllEstimators(); + // Start any enabled estimator that is currently stopped and has at least one fusion source ready. + void startEstIfNeeded(); + // Reset timed-out estimators and immediately re-arm those that still have an enabled fusion source. + void restartTimedOutEstimators(); + // Collect inputs, downsample acceleration, and tick the enabled estimators once per cycle. + void updateEstimators(); + void updatePosEst(const matrix::Vector3f &gps_pos_offset_ned, + const matrix::Vector3f &vel_offset_ned, + const bool vel_offset_updated, + uint32_t acc_sample_count); + void updateYawEst(); + void publishVteInput(const matrix::Vector3f &vehicle_acc_ned_sampled, const matrix::Quaternionf &q_att, + uint32_t acc_sample_count); + + inline bool noActiveTask() const { return _current_task_ptr == nullptr; } + inline bool noEstRunning() const + { + return (!_vte_orientation_enabled || !_orientation_estimator_running) && + (!_vte_position_enabled || !_position_estimator_running); + } + inline bool isTaskMaskBitEnabled(const uint8_t mask_bit) const + { + return (_vte_task_mask & mask_bit) != 0; + } + + // Refresh uORB msgs from the latest status topics, for every task whose mask bit is set. + void updateTaskTopics(); + // Set the highest-priority task with a mask bit is set and whose preconditions are met; returns true on transition. + bool setNewTaskIfAvailable(); + // Returns true when the active task has finished (self-signalled, or deselected via VTE_TASK_MASK). + bool isCurrentTaskComplete(); + bool startPosEst(); + void stopPosEst(); + bool startYawEst(); + void stopYawEst(); + // Reads the latest attitude (required) and acceleration (optional) and rotates body-frame inputs to NED. + bool pollEstimatorInput(matrix::Vector3f &acc_ned, matrix::Quaternionf &q_att, + matrix::Vector3f &gps_pos_offset, + matrix::Vector3f &vel_offset_ned, + bool vel_offset_updated, bool &acc_valid); + + perf_counter_t _cycle_perf_pos{perf_alloc(PC_ELAPSED, MODULE_NAME": VTE cycle pos")}; + perf_counter_t _cycle_perf_yaw{perf_alloc(PC_ELAPSED, MODULE_NAME": VTE cycle yaw")}; + perf_counter_t _cycle_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": VTE cycle ")}; + + Vector3fStamped _vehicle_acc_body{}; + matrix::Quaternionf _last_att{1.f, 0.f, 0.f, 0.f}; + + uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; + + uORB::SubscriptionCallbackWorkItem _vehicle_attitude_sub{this, ORB_ID(vehicle_attitude)}; + + uORB::Subscription _vehicle_gps_position_sub{ORB_ID(vehicle_gps_position)}; + uORB::Subscription _vehicle_local_position_sub{ORB_ID(vehicle_local_position)}; + uORB::Subscription _vehicle_acceleration_sub{ORB_ID(vehicle_acceleration)}; + uORB::Subscription _vehicle_angular_velocity_sub{ORB_ID(vehicle_angular_velocity)}; + + uORB::Publication _vte_input_pub{ORB_ID(vte_input)}; + + uint8_t _vte_task_mask{0}; + + // Registry of supported tasks, ordered by priority (highest first). The Run() loop + // selects the first entry whose mask bit is set and whose isReady() is true. + PrecLandTask _prec_land_task{}; + DebugTask _debug_task{}; + VteTask *_task_registry[2] {&_prec_land_task, &_debug_task}; + VteTask *_current_task_ptr{nullptr}; + + bool _position_estimator_running{false}; + bool _orientation_estimator_running{false}; + + SensorFusionMaskU _vte_aid_mask{}; + uint16_t adjustAidMask(const int input_mask); + void printAidMask(); + + bool _vte_orientation_enabled{false}; + VTEOrientation _vte_orientation{}; + hrt_abstime _last_update_yaw{0}; + + VTEPosition _vte_position{}; + bool _vte_position_enabled{false}; + hrt_abstime _last_update_pos{0}; + + matrix::Vector3f _gps_pos_offset_xyz{}; + bool _gps_pos_is_offset{false}; + + bool updateGpsAntennaOffset(); + // Compute the body-frame velocity bias caused by the GNSS antenna lever arm during rotation. + bool computeGpsVelocityOffset(matrix::Vector3f &vel_offset_body); + bool pollLocalPose(LocalPose &local_pose); + + // Returns true once per `interval`, advancing `last_time` to now on each successful gate. + bool updateWhenIntervalElapsed(hrt_abstime &last_time, const hrt_abstime interval) const; + + /* Down sample acceleration data */ + matrix::Vector3f _vehicle_acc_ned_sum{}; + uint32_t _acc_sample_count{0}; + hrt_abstime _last_acc_reset{0}; + void resetAccDownsample(); + +private: + DEFINE_PARAMETERS( + (ParamInt) _param_vte_yaw_en, + (ParamInt) _param_vte_pos_en, + (ParamInt) _param_vte_task_mask, + (ParamFloat) _param_vte_btout, + (ParamFloat) _param_vte_tgt_tout, + (ParamFloat) _param_vte_mrec_tout, + (ParamFloat) _param_vte_mupd_tout, + (ParamInt) _param_vte_aid_mask + ) +}; +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/common.h b/src/modules/vision_target_estimator/common.h new file mode 100644 index 00000000000..d2c90f446fd --- /dev/null +++ b/src/modules/vision_target_estimator/common.h @@ -0,0 +1,174 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file common.h + * @brief Definitions common to the position and orientation filters. + * + * @author Jonas Perolini + * + */ + +#pragma once + +#include + +#include +#include +#include +#include + +namespace vision_target_estimator +{ + +using namespace time_literals; + +static constexpr float kMicrosecondsToSeconds = 1e-6f; +static constexpr float kMicrosecondsToMilliseconds = 1e-3f; +static constexpr float kMinVariance = 1e-6f; +static constexpr float kMinObservationNoise = 1e-2f; +static constexpr float kMinNisThreshold = 0.1f; +static constexpr float kDefaultNisThreshold = 3.84f; +static constexpr float kGravityMps2 = 9.80665f; +static constexpr float kMinInnovationVariance = kMinVariance; + +constexpr hrt_abstime kWarnThrottleIntervalUs = 20_s; +constexpr hrt_abstime kEstimatorUpdatePeriodUs = 20_ms; +constexpr hrt_abstime kOosmMinTimeUs = kEstimatorUpdatePeriodUs; +constexpr hrt_abstime kOosmMaxTimeUs = 500_ms; +constexpr int kOosmHistorySize = static_cast(kOosmMaxTimeUs / kEstimatorUpdatePeriodUs); +constexpr int kExpectedAxisCount = 3; +constexpr int kExpectedStaticPositionStateCount = 3; +constexpr int kExpectedMovingPositionStateCount = 5; + +// Fusion status values are defined as message constants in VteAidSource1d.msg / VteAidSource3d.msg +// (both messages declare the same STATUS_* values). Using vte_aid_source1d_s here keeps a single +// source of truth for the enum values shared between the filters and the logged uORB topics. +using FusionStatus = vte_aid_source1d_s; + +using TimeSource = hrt_abstime(*)(); + +inline hrt_abstime defaultNowUs() +{ + return hrt_absolute_time(); +} + +class TimeSourceProvider +{ +public: + static hrt_abstime nowUs() + { + return timeSourceStorage()(); + } + +#if defined(VTE_ENABLE_TEST_HOOKS) + static void setTimeSourceForTest(TimeSource newTimeSource) + { + timeSourceStorage() = newTimeSource ? newTimeSource : defaultNowUs; + } + + static void resetTimeSourceForTest() + { + timeSourceStorage() = defaultNowUs; + } +#endif + +private: + static TimeSource &timeSourceStorage() + { + static TimeSource activeTimeSource = defaultNowUs; + return activeTimeSource; + } +}; + +inline hrt_abstime nowUs() +{ + return TimeSourceProvider::nowUs(); +} + +struct FusionResult { + uint8_t status{FusionStatus::STATUS_IDLE}; + float innov{0.f}; + float innov_var{0.f}; + float test_ratio{-1.f}; // Normalized NIS (beta / threshold) + uint8_t history_steps{0}; +}; + +static inline bool hasTimedOutAt(const hrt_abstime now, const hrt_abstime ts, const hrt_abstime timeout_us) +{ + // Zero timestamps are treated as invalid / timed out. + if (ts == 0) { + return true; + } + + // Future timestamps are considered invalid -> timed out + if (ts > now) { + return true; + } + + return (now - ts) >= timeout_us; +} + +static inline bool hasTimedOut(const hrt_abstime ts, const hrt_abstime timeout_us) +{ + return hasTimedOutAt(nowUs(), ts, timeout_us); +} + +constexpr inline int64_t signedTimeDiffUs(const hrt_abstime newer, const hrt_abstime older) +{ + return static_cast(newer) - static_cast(older); +} + +static constexpr float sq(float var) { return var * var; } + +union SensorFusionMaskU { + struct { + uint16_t use_target_gps_pos : 1; ///< bit 0 + uint16_t use_uav_gps_vel : 1; ///< bit 1 + uint16_t use_vision_pos : 1; ///< bit 2 + uint16_t use_mission_pos : 1; ///< bit 3 + uint16_t use_target_gps_vel : 1; ///< bit 4 + uint16_t reserved : 11; ///< bits 5..15 (future use) + } flags; + + uint16_t value; +}; +static_assert(sizeof(SensorFusionMaskU) == 2, "Unexpected packing"); + +struct Vector3fStamped { + hrt_abstime timestamp = 0; + bool valid = false; + matrix::Vector3f xyz{}; +}; + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/tasks/PrecLandTask.cpp b/src/modules/vision_target_estimator/tasks/PrecLandTask.cpp new file mode 100644 index 00000000000..dc95e0c8497 --- /dev/null +++ b/src/modules/vision_target_estimator/tasks/PrecLandTask.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PrecLandTask.cpp + * @brief Implements the precision-landing VTE task. + * + * This task owns the precland-specific subscriptions and per-task cache used by + * VisionTargetEst. It tracks when precision landing is active, resolves the + * landing waypoint from Navigator, and seeds the position estimator with that + * mission landing point whenever the estimator starts or restarts inside the + * same precision-landing run. + * + * @author Jonas Perolini + */ + +#include "PrecLandTask.h" + +#include + +#include +#include + +#include "../../navigator/navigation.h" +#include "../Position/VTEPosition.h" + +namespace vision_target_estimator +{ + +void PrecLandTask::pollStatus() +{ + prec_land_status_s prec_land_status; + + if (_prec_land_status_sub.update(&prec_land_status)) { + _is_in_prec_land = prec_land_status.state != prec_land_status_s::PREC_LAND_STATE_STOPPED + && prec_land_status.state != prec_land_status_s::PREC_LAND_STATE_DONE; + } + + if (_is_in_prec_land) { + updateMissionSetpoint(); + } +} + +bool PrecLandTask::isComplete() +{ + vehicle_land_detected_s vehicle_land_detected; + + // Stop computations once the drone has landed. + if (_vehicle_land_detected_sub.update(&vehicle_land_detected) && vehicle_land_detected.landed) { + PX4_DEBUG("Land detected, precision landing task completed."); + _is_in_prec_land = false; + return true; + } + + // Stop computations once precision landing is over. + if (!_is_in_prec_land) { + PX4_DEBUG("Precision landing task completed."); + return true; + } + + return false; +} + +void PrecLandTask::onActivate() +{ + resetMissionSetpoint(); +} + +void PrecLandTask::onPosEstStart(VTEPosition &pos) +{ + if (updateMissionSetpoint()) { + pos.setMissionPosition(_cached_mission_setpoint.lat, _cached_mission_setpoint.lon, + _cached_mission_setpoint.alt); + + } else { + PX4_WARN("VTE for precision landing, land position cannot be used."); + pos.setMissionPosition(0.0, 0.0, NAN); + } +} + +const position_setpoint_s *PrecLandTask::findLandSetpoint() +{ + (void)_pos_sp_triplet_sub.update(&_pos_sp_triplet_buffer); + + if (_pos_sp_triplet_buffer.next.valid && _pos_sp_triplet_buffer.next.type == position_setpoint_s::SETPOINT_TYPE_LAND) { + PX4_DEBUG("VTE for precision landing, next sp is land."); + return &_pos_sp_triplet_buffer.next; + } + + if (_pos_sp_triplet_buffer.current.valid + && _pos_sp_triplet_buffer.current.type == position_setpoint_s::SETPOINT_TYPE_LAND) { + PX4_DEBUG("VTE for precision landing, current sp is land."); + return &_pos_sp_triplet_buffer.current; + } + + return nullptr; +} + +bool PrecLandTask::updateMissionSetpoint() +{ + if (_cached_mission_setpoint.valid) { + return true; + } + + navigator_mission_item_s navigator_mission_item{}; + + // The live triplet is rewritten by precland once the task starts, while navigator_mission_item + // keeps publishing the logical land item selected by mission or RTL. Prefer that stable source + // and keep the triplet as a fallback for paths that do not publish navigator mission items. + if (_navigator_mission_item_sub.copy(&navigator_mission_item) && cacheMissionSetpoint(navigator_mission_item)) { + return true; + } + + if (const position_setpoint_s *land_setpoint = findLandSetpoint()) { + _cached_mission_setpoint = *land_setpoint; + return true; + } + + return false; +} + +bool PrecLandTask::cacheMissionSetpoint(const navigator_mission_item_s &mission_item) +{ + if (mission_item.nav_cmd != NAV_CMD_LAND && mission_item.nav_cmd != NAV_CMD_VTOL_LAND) { + return false; + } + + if (!PX4_ISFINITE(mission_item.latitude) || !PX4_ISFINITE(mission_item.longitude) || !PX4_ISFINITE(mission_item.altitude)) { + return false; + } + + float altitude_amsl = mission_item.altitude; + + if (mission_item.altitude_is_relative) { + home_position_s home_position{}; + + if (!_home_position_sub.copy(&home_position) || !PX4_ISFINITE(home_position.alt)) { + return false; + } + + altitude_amsl += home_position.alt; + } + + _cached_mission_setpoint = {}; + _cached_mission_setpoint.valid = true; + _cached_mission_setpoint.type = position_setpoint_s::SETPOINT_TYPE_LAND; + _cached_mission_setpoint.lat = static_cast(mission_item.latitude); + _cached_mission_setpoint.lon = static_cast(mission_item.longitude); + _cached_mission_setpoint.alt = altitude_amsl; + return true; +} + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/tasks/PrecLandTask.h b/src/modules/vision_target_estimator/tasks/PrecLandTask.h new file mode 100644 index 00000000000..ef5b239e0b0 --- /dev/null +++ b/src/modules/vision_target_estimator/tasks/PrecLandTask.h @@ -0,0 +1,97 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file PrecLandTask.h + * @brief Precision-landing VteTask: owns precland-specific uORB state and the + * cached mission land setpoint used to seed the position estimator. + * + * @author Jonas Perolini + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "VteTask.h" + +class VisionTargetEstTest; +class VisionTargetEstTestable; + +namespace vision_target_estimator +{ + +class VTEPosition; + +class PrecLandTask final : public VteTask +{ +public: + /* VteTask interface */ + uint8_t maskBit() const override { return task_bits::kPrecLand; } + const char *name() const override { return "prec_land"; } + void pollStatus() override; + bool isReady() const override { return _is_in_prec_land; } + bool isComplete() override; + void onActivate() override; + void onPosEstStart(VTEPosition &pos) override; + + /* Helpers used by tests and by VisionTargetEst logging */ + // Select the first valid LAND setpoint in the live triplet (next preferred over current). + const position_setpoint_s *findLandSetpoint(); + // Resolve and cache the precision-landing target from navigator_mission_item + // (preferred) or the triplet; re-used across estimator restarts in the same task. + bool updateMissionSetpoint(); + bool cacheMissionSetpoint(const navigator_mission_item_s &mission_item); + void resetMissionSetpoint() { _cached_mission_setpoint = {}; } + +private: + friend class ::VisionTargetEstTest; + friend class ::VisionTargetEstTestable; + + uORB::Subscription _home_position_sub{ORB_ID(home_position)}; + uORB::Subscription _navigator_mission_item_sub{ORB_ID(navigator_mission_item)}; + uORB::Subscription _pos_sp_triplet_sub{ORB_ID(position_setpoint_triplet)}; + uORB::Subscription _vehicle_land_detected_sub{ORB_ID(vehicle_land_detected)}; + uORB::Subscription _prec_land_status_sub{ORB_ID(prec_land_status)}; + + position_setpoint_triplet_s _pos_sp_triplet_buffer{}; + position_setpoint_s _cached_mission_setpoint{}; + bool _is_in_prec_land{false}; +}; + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/tasks/VteTask.h b/src/modules/vision_target_estimator/tasks/VteTask.h new file mode 100644 index 00000000000..8704a5d078b --- /dev/null +++ b/src/modules/vision_target_estimator/tasks/VteTask.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VteTask.h + * @brief Abstract interface for tasks that drive the Vision Target Estimator. + * + * A task owns all state that only exists for the duration of a particular VTE use-case + * (subscriptions, setpoint caches, external status flags). VisionTargetEst keeps a + * priority-ordered registry and drives every task through this interface, which + * replaces the parallel if/else-if branches that used to dispatch on the task mask. + * + * @author Jonas Perolini + */ + +#pragma once + +#include + +namespace vision_target_estimator +{ + +class VTEPosition; + +// Single source of truth for VTE_TASK_MASK bit values. +namespace task_bits +{ +static constexpr uint8_t kPrecLand = 1u << 0; +static constexpr uint8_t kDebug = 1u << 1; +} // namespace task_bits + +class VteTask +{ +public: + virtual ~VteTask() = default; + + /// VTE_TASK_MASK bit that enables this task (e.g. task_bits::kPrecLand). + virtual uint8_t maskBit() const = 0; + + /// Short, stable name for log messages. Must be a stable string literal. + virtual const char *name() const = 0; + + /// Poll external status topics. Called every cycle while the task's mask bit is set. + virtual void pollStatus() {} + + /// True once the task's external preconditions are met and it can become active. + virtual bool isReady() const = 0; + + /// True when the task has reached its end state by its own signals (e.g. landed). + /// Mask-bit deselection is handled by the registry, not here. + virtual bool isComplete() { return false; } + + /// Called on the inactive → active transition, before the estimator is (re)started. + virtual void onActivate() {} + + /// Called right after VTEPosition::resetFilter() on start; lets the task seed the filter. + virtual void onPosEstStart(VTEPosition & /*pos*/) {} +}; + +/** + * Debug task: runs as soon as the mask bit is set and never self-terminates. + * Useful for forcing the estimator to run on the bench without any precland. + */ +class DebugTask final : public VteTask +{ +public: + uint8_t maskBit() const override { return task_bits::kDebug; } + const char *name() const override { return "debug"; } + bool isReady() const override { return true; } +}; + +} // namespace vision_target_estimator diff --git a/src/modules/vision_target_estimator/test/CMakeLists.txt b/src/modules/vision_target_estimator/test/CMakeLists.txt new file mode 100644 index 00000000000..953be45b8cf --- /dev/null +++ b/src/modules/vision_target_estimator/test/CMakeLists.txt @@ -0,0 +1,94 @@ +############################################################################ +# +# Copyright (c) 2026 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +set(VTEST_TEST_COMMON_INCLUDES + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +px4_add_unit_gtest( + SRC TEST_VTEOosm.cpp + INCLUDES ${VTEST_TEST_COMMON_INCLUDES} +) + +px4_add_unit_gtest( + SRC TEST_VTE_KF_position.cpp + INCLUDES ${VTEST_TEST_COMMON_INCLUDES} + LINKLIBS modules__vision_target_estimator +) + +px4_add_unit_gtest( + SRC TEST_VTE_KF_orientation.cpp + INCLUDES ${VTEST_TEST_COMMON_INCLUDES} + LINKLIBS modules__vision_target_estimator +) + +px4_add_functional_gtest( + SRC TEST_VTEPosition.cpp + INCLUDES ${VTEST_TEST_COMMON_INCLUDES} + LINKLIBS modules__vision_target_estimator + geo +) + +px4_add_functional_gtest( + SRC TEST_VTEOrientation.cpp + INCLUDES ${VTEST_TEST_COMMON_INCLUDES} + LINKLIBS modules__vision_target_estimator +) + +px4_add_functional_gtest( + SRC TEST_VTE_VisionTargetEst.cpp + INCLUDES ${VTEST_TEST_COMMON_INCLUDES} + LINKLIBS modules__vision_target_estimator + geo +) + +foreach(vtest_target + unit-TEST_VTEOosm + unit-TEST_VTE_KF_position + unit-TEST_VTE_KF_orientation + functional-TEST_VTEPosition + functional-TEST_VTEOrientation + functional-TEST_VTE_VisionTargetEst +) + add_dependencies(${vtest_target} uorb_headers) + target_compile_definitions(${vtest_target} PRIVATE VTE_ENABLE_TEST_HOOKS=1) +endforeach() + +# These tests include headers that pull in the generated position state directly. +foreach(vtest_target + unit-TEST_VTE_KF_position + functional-TEST_VTEPosition + functional-TEST_VTE_VisionTargetEst +) + add_dependencies(${vtest_target} ${VTEST_GENERATED_TARGET}) +endforeach() diff --git a/src/modules/vision_target_estimator/test/TEST_VTEOosm.cpp b/src/modules/vision_target_estimator/test/TEST_VTEOosm.cpp new file mode 100644 index 00000000000..71f30205700 --- /dev/null +++ b/src/modules/vision_target_estimator/test/TEST_VTEOosm.cpp @@ -0,0 +1,1115 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file TEST_VTEOosm.cpp + * @brief Unit test VTEOosm.h + * + * @author Jonas Perolini + * + */ + +#include + +#include +#include + +#include "VTEOosm.h" +#include "common.h" + +namespace vte = vision_target_estimator; + +namespace vision_target_estimator +{ + +// Access into OOSMManager's private helpers for unit tests. +template +struct OOSMManagerTestAccess { + using LinearTimeline = typename Manager::LinearTimeline; + + static void copyHistoryToLinearTimeline(Manager &m, LinearTimeline &out) + { + m.copyHistoryToLinearTimeline(out); + } + + static void rebuildHistoryFromLinearTimeline(Manager &m, const LinearTimeline &tl) + { + m.rebuildHistoryFromLinearTimeline(tl); + } + + static int historyEntries(const Manager &m) { return m._history.entries(); } + static uint64_t historyOldestTime(const Manager &m) { return m._history.get_oldest().time_us; } + static uint64_t historyNewestTime(const Manager &m) { return m._history.get_newest().time_us; } +}; + +} // namespace vision_target_estimator + +namespace +{ +using namespace time_literals; + +static constexpr int kStateDim = 1; +static constexpr float kTolerance = 1e-4f; +static constexpr int kStateDim2 = 2; +using StateVec2 = matrix::Vector; +using StateCov2 = matrix::SquareMatrix; + +struct ScalarMeas { + uint64_t time_us{0}; + float val{0.f}; + float unc{0.f}; + matrix::Vector H{}; +}; + +struct ScalarMeas2 { + uint64_t time_us{0}; + float val{0.f}; + float unc{0.f}; + StateVec2 H{}; +}; + +class TestFilter +{ +public: + float last_predict_input{NAN}; + matrix::Vector last_H{}; + std::vector applied_k; + std::vector applied_state_before; + std::vector applied_state_after; + + void resetTracking() + { + last_predict_input = NAN; + last_H.setZero(); + applied_k.clear(); + applied_state_before.clear(); + applied_state_after.clear(); + } + + // Scalar constant-velocity model with small process-noise growth. + void predictState(float dt, float input, const matrix::Vector &x_in, + const matrix::SquareMatrix &P_in, + matrix::Vector &x_out, + matrix::SquareMatrix &P_out) + { + last_predict_input = input; + + x_out = x_in; + x_out(0) += input * dt; + + P_out = P_in; + P_out(0, 0) += 0.1f * dt; + } + + matrix::SquareMatrix getTransitionMatrix(float dt) const + { + (void)dt; + matrix::SquareMatrix phi{}; + phi.setIdentity(); + return phi; + } + + void computeInnovation(const matrix::Vector &state, + const matrix::SquareMatrix &cov, + const ScalarMeas &meas, float &innov, float &innov_var) + { + last_H = meas.H; + innov = meas.val - (meas.H.transpose() * state)(0, 0); + innov_var = (meas.H.transpose() * cov * meas.H)(0, 0) + meas.unc; + } + + void applyCorrection(matrix::Vector &state, + matrix::SquareMatrix &cov, + const matrix::Vector &K, float innov, float innov_var) + { + (void)innov_var; + applied_k.push_back(K(0)); + applied_state_before.push_back(state(0)); + state(0) += K(0) * innov; + applied_state_after.push_back(state(0)); + cov(0, 0) = (1.f - K(0) * last_H(0)) * cov(0, 0); + } +}; + +class TestFilter2d +{ +public: + float last_predict_input{NAN}; + StateVec2 last_H{}; + std::vector applied_k; + std::vector applied_state_before; + std::vector applied_state_after; + + void resetTracking() + { + last_predict_input = NAN; + applied_k.clear(); + applied_state_before.clear(); + applied_state_after.clear(); + } + + void predictState(float dt, float input, const StateVec2 &x_in, + const StateCov2 &P_in, + StateVec2 &x_out, StateCov2 &P_out) + { + last_predict_input = input; + + const StateCov2 phi = getTransitionMatrix(dt); + StateVec2 control{}; + control(0) = 0.5f * input * dt * dt; + control(1) = input * dt; + + x_out = phi * x_in + control; + P_out = phi * P_in * phi.transpose(); + } + + StateCov2 getTransitionMatrix(float dt) const + { + StateCov2 phi{}; + phi.setIdentity(); + phi(0, 1) = dt; + return phi; + } + + void computeInnovation(const StateVec2 &state, const StateCov2 &cov, + const ScalarMeas2 &meas, float &innov, float &innov_var) + { + last_H = meas.H; + innov = meas.val - (meas.H.transpose() * state)(0, 0); + innov_var = (meas.H.transpose() * cov * meas.H)(0, 0) + meas.unc; + } + + void applyCorrection(StateVec2 &state, StateCov2 &cov, + const StateVec2 &K, float innov, float innov_var) + { + applied_k.push_back(K); + applied_state_before.push_back(state); + state = state + K * innov; + applied_state_after.push_back(state); + + const matrix::Matrix &K_mat = K; + + cov = cov - (K_mat * K.transpose()) * innov_var; + } +}; + +class VTEOosmTest : public ::testing::Test +{ +protected: + using Manager = vte::OOSMManager; + + Manager oosm{}; + TestFilter filter{}; + float state{0.f}; + float cov{0.f}; + float curr_input{0.f}; + + void SetUp() override + { + state = 0.f; + cov = 4.f; + curr_input = 0.f; + filter.resetTracking(); + } + + static matrix::Vector makeVec(float value) + { + matrix::Vector v{}; + v(0) = value; + return v; + } + + static matrix::SquareMatrix makeCov(float variance) + { + matrix::SquareMatrix P{}; + P.setZero(); + P(0, 0) = variance; + return P; + } + + static ScalarMeas makeMeas(uint64_t time_us, float val, float unc, float h_val = 1.f) + { + ScalarMeas meas{}; + meas.time_us = time_us; + meas.val = val; + meas.unc = unc; + meas.H(0) = h_val; + return meas; + } + + void pushSample(uint64_t time_us, float state_val, float cov_val, float input) + { + oosm.push(time_us, makeVec(state_val), makeCov(cov_val), input); + } + + vte::FusionResult fuseMeas(const ScalarMeas &meas, uint64_t now_us, float nis_threshold) + { + auto state_vec = makeVec(state); + auto cov_mat = makeCov(cov); + + const vte::FusionResult res = oosm.fuse(filter, meas, now_us, nis_threshold, state_vec, cov_mat, curr_input); + + state = state_vec(0); + cov = cov_mat(0, 0); + return res; + } +}; + +class VTEOosmTest2d : public ::testing::Test +{ +protected: + using Manager = vte::OOSMManager; + + Manager oosm{}; + TestFilter2d filter{}; + StateVec2 state{}; + StateCov2 cov{}; + float curr_input{0.f}; + + void SetUp() override + { + state = makeVec(0.f, 1.f); + cov = makeCov(4.f, 1.f, 0.5f); + curr_input = 0.f; + filter.resetTracking(); + } + + static StateVec2 makeVec(float pos, float vel) + { + StateVec2 v{}; + v(0) = pos; + v(1) = vel; + return v; + } + + static StateCov2 makeCov(float p00, float p11, float p01) + { + StateCov2 P{}; + P.setZero(); + P(0, 0) = p00; + P(1, 1) = p11; + P(0, 1) = p01; + P(1, 0) = p01; + return P; + } + + static ScalarMeas2 makeMeas(uint64_t time_us, float val, float unc, float h_pos = 1.f, float h_vel = 0.f) + { + ScalarMeas2 meas{}; + meas.time_us = time_us; + meas.val = val; + meas.unc = unc; + meas.H = makeVec(h_pos, h_vel); + return meas; + } + + void pushSample(uint64_t time_us, const StateVec2 &state_in, + const StateCov2 &cov_in, float input) + { + oosm.push(time_us, state_in, cov_in, input); + } + + vte::FusionResult fuseMeas(const ScalarMeas2 &meas, uint64_t now_us, float nis_threshold) + { + StateVec2 state_vec = state; + StateCov2 cov_mat = cov; + + const vte::FusionResult res = oosm.fuse(filter, meas, now_us, nis_threshold, state_vec, cov_mat, curr_input); + + state = state_vec; + cov = cov_mat; + return res; + } + +}; + +// WHY: The OOSM manager must use the fast path for fresh measurements. +// WHAT: Ensure a current measurement updates state/covariance and returns FUSED_CURRENT. +TEST_F(VTEOosmTest, FusesCurrentMeasurement) +{ + // GIVEN: a fresh measurement that is newer than the OOSM cutoff. + const uint64_t now_us = 1_s; + const uint64_t current_offset = Manager::kOosmMinTimeUs - 1_ms; + const ScalarMeas meas = makeMeas(now_us - current_offset, 2.f, 1.f); + + // WHEN: the measurement is fused. + const vte::FusionResult res = fuseMeas(meas, now_us, 10.f); + + // THEN: the current-fusion path updates the live state once. + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_NEAR(state, 1.6f, kTolerance); + EXPECT_NEAR(cov, 0.8f, kTolerance); + EXPECT_EQ(filter.applied_k.size(), 1u); +} + +// WHY: Near-zero innovation variance should never result in a correction. +// WHAT: Verify REJECT_COV and that the live state stays unchanged. +TEST_F(VTEOosmTest, RejectsInvalidInnovationVariance) +{ + // GIVEN: a zero-variance prior and a zero-uncertainty measurement. + const uint64_t now_us = 2_s; + state = 1.f; + cov = 0.f; + const uint64_t current_offset = Manager::kOosmMinTimeUs - 1_ms; + const ScalarMeas meas = makeMeas(now_us - current_offset, 1.f, 0.f); + + // WHEN: the measurement is fused. + const vte::FusionResult res = fuseMeas(meas, now_us, 10.f); + + // THEN: the correction is rejected before any gain is applied. + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_REJECT_COV); + EXPECT_EQ(filter.applied_k.size(), 0u); + EXPECT_NEAR(state, 1.f, kTolerance); + EXPECT_NEAR(cov, 0.f, kTolerance); +} + +// WHY: NIS gating is the primary protection against outlier measurements. +// WHAT: Ensure large innovation triggers REJECT_NIS without changing state. +TEST_F(VTEOosmTest, RejectsNisForCurrentMeasurement) +{ + // GIVEN: a current measurement with a large residual and a small innovation variance. + const uint64_t now_us = 3_s; + state = 0.f; + cov = 0.1f; + const uint64_t current_offset = Manager::kOosmMinTimeUs - 1_ms; + const ScalarMeas meas = makeMeas(now_us - current_offset, 10.f, 0.1f); + + // WHEN: the measurement is fused with a tight NIS threshold. + const vte::FusionResult res = fuseMeas(meas, now_us, 1.f); + + // THEN: the measurement is rejected and the live state is unchanged. + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_REJECT_NIS); + EXPECT_EQ(filter.applied_k.size(), 0u); + EXPECT_NEAR(state, 0.f, kTolerance); + EXPECT_NEAR(cov, 0.1f, kTolerance); +} + +// WHY: OOSM fusion must protect against empty or inconsistent history. +// WHAT: Validate REJECT_EMPTY and REJECT_STALE behavior with history reset. +TEST_F(VTEOosmTest, RejectsOosmHistoryGuards) +{ + // GIVEN: a delayed measurement, first with no history and then with stale history timing. + const uint64_t meas_time_us = 900_ms; + const ScalarMeas meas = makeMeas(meas_time_us, 0.f, 1.f); + + // WHEN: we fuse without history, then with a now timestamp older than the newest stored sample. + const vte::FusionResult empty_res = fuseMeas(meas, 1_s, 10.f); + EXPECT_EQ(empty_res.status, vte::FusionStatus::STATUS_REJECT_EMPTY); + + pushSample(980_ms, 0.5f, 4.f, 1.f); + + const vte::FusionResult stale_res = fuseMeas(meas, 800_ms, 10.f); + EXPECT_EQ(stale_res.status, vte::FusionStatus::STATUS_REJECT_STALE); + + // THEN: the stale path resets history and the next attempt is empty again. + const vte::FusionResult post_reset_res = fuseMeas(meas, 1_s, 10.f); + EXPECT_EQ(post_reset_res.status, vte::FusionStatus::STATUS_REJECT_EMPTY); +} + +// WHY: OOSM fusion must reject timestamps outside the valid window. +// WHAT: Check REJECT_TOO_NEW and REJECT_TOO_OLD for valid history. +TEST_F(VTEOosmTest, RejectsOosmOutOfRangeTimestamps) +{ + // GIVEN: a populated history window and delayed measurements just outside both ends. + pushSample(100_ms, 0.f, 4.f, 0.f); + pushSample(200_ms, 1.f, 4.f, 0.f); + pushSample(250_ms, 2.f, 4.f, 0.f); + + const uint64_t now_us = 300_ms; + const uint64_t too_new_time = now_us + Manager::kOosmMinTimeUs + 1_us; + const ScalarMeas meas_too_new = makeMeas(too_new_time, 0.f, 1.f); + + // WHEN: the timestamps lie just beyond the allowed future/past bounds. + const vte::FusionResult too_new_res = fuseMeas(meas_too_new, now_us, 10.f); + EXPECT_EQ(too_new_res.status, vte::FusionStatus::STATUS_REJECT_TOO_NEW); + + const uint64_t oldest_time = 100_ms; + const uint64_t too_old_time = oldest_time - 10_ms; + const ScalarMeas meas_too_old = makeMeas(too_old_time, 0.f, 1.f); + const vte::FusionResult too_old_res = fuseMeas(meas_too_old, now_us, 10.f); + + // THEN: both samples are rejected for being out of range. + EXPECT_EQ(too_old_res.status, vte::FusionStatus::STATUS_REJECT_TOO_OLD); +} + +// WHY: When the floor sample is the newest, OOSM should use current input. +// WHAT: Provide a measurement between newest sample and now and verify curr_input was used. +TEST_F(VTEOosmTest, UsesCurrentInputWhenFloorIsNewest) +{ + // GIVEN: history whose newest sample is still older than the delayed measurement. + const uint64_t t0 = 1_s; + pushSample(t0, 0.f, 4.f, 1.f); + + curr_input = 5.f; + + const ScalarMeas meas = makeMeas(t0 + 30_ms, 1.f, 1.f); + + // WHEN: the delayed measurement falls between the newest sample and now. + const vte::FusionResult res = fuseMeas(meas, t0 + 60_ms, 10.f); + + // THEN: the projection uses the live input rather than stale history input. + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_OOSM); + EXPECT_FLOAT_EQ(filter.last_predict_input, curr_input); +} + +// WHY: Large time gaps between history and now should reset the buffer. +// WHAT: Force now to exceed the max OOSM window and verify REJECT_STALE with reset. +TEST_F(VTEOosmTest, RejectsStaleWhenNowExceedsHistoryWindow) +{ + // GIVEN: history that is older than the maximum supported OOSM window. + const uint64_t t0 = 1_s; + pushSample(t0, 0.f, 4.f, 0.f); + + const ScalarMeas meas = makeMeas(t0 + 50_ms, 1.f, 1.f); + const uint64_t stale_now = t0 + Manager::kOosmMaxTimeUs + 1_ms; + + // WHEN: we fuse with a now timestamp outside the allowed live/history span. + const vte::FusionResult stale_res = fuseMeas(meas, stale_now, 10.f); + EXPECT_EQ(stale_res.status, vte::FusionStatus::STATUS_REJECT_STALE); + + // THEN: history is cleared and the next call sees an empty buffer. + const vte::FusionResult empty_res = fuseMeas(meas, stale_now, 10.f); + EXPECT_EQ(empty_res.status, vte::FusionStatus::STATUS_REJECT_EMPTY); +} + +// WHY: Ensure OOSM (delayed fusion) yields a result equivalent to +// fusing the measurement sequentially at the correct time. +// WHAT: Run a filter in which the measurement comes on time and compare it with +// a filter with the same measurement but delayed +TEST_F(VTEOosmTest, FusesOosmBetweenSamplesSimplified) +{ + // GIVEN: a scalar linear system with history at t0, t1, and t2 plus a delayed sample at t_meas. + + static constexpr uint64_t t0 = 100_ms; + static constexpr uint64_t t_meas = 150_ms; + static constexpr uint64_t t1 = 200_ms; + static constexpr uint64_t t2 = 300_ms; + + static constexpr float kInput = 2.f; + static constexpr float kDtStep = 0.1f; // 100ms steps for history + + // Initial Conditions + const auto x0 = makeVec(0.f); + const auto P0 = makeCov(1.f); + const ScalarMeas meas = makeMeas(t_meas, 10.f, 1.f); + + // Build history: t0 -> t1 -> t2 + // We simulate the filter running normally without the measurement first. + matrix::Vector x1, x2; + matrix::SquareMatrix P1, P2; + + // t0 -> t1 + filter.predictState(kDtStep, kInput, x0, P0, x1, P1); + // t1 -> t2 + filter.predictState(kDtStep, kInput, x1, P1, x2, P2); + + // Setup OOSM Manager + oosm.reset(); + filter.resetTracking(); // Reset the helper's internal tracking logs + + oosm.push(t0, x0, P0, kInput); + oosm.push(t1, x1, P1, kInput); + oosm.push(t2, x2, P2, kInput); + + // Now is t2 + state = x2(0); + cov = P2(0, 0); + + // WHEN: we fuse the delayed sample through OOSM and compare it with chronological truth. + const vte::FusionResult oosm_res = fuseMeas(meas, t2, 100.f); + + EXPECT_EQ(oosm_res.status, vte::FusionStatus::STATUS_FUSED_OOSM); + EXPECT_EQ(oosm_res.history_steps, 2); // Should update t1 and t2 (t0 is floor, not updated) + + const float val_oosm_state = state; + const float val_oosm_cov = cov; + + // The truth path fuses the same sample exactly at t_meas. + TestFilter truth_filter; + matrix::Vector x_truth = x0; + matrix::SquareMatrix P_truth = P0; + + // Predict t0 -> t_meas (100ms -> 150ms = 0.05s) + float dt_1 = (t_meas - t0) * 1e-6f; + truth_filter.predictState(dt_1, kInput, x_truth, P_truth, x_truth, P_truth); + + // Fuse Measurement exactly at t_meas + float innov, innov_var; + truth_filter.computeInnovation(x_truth, P_truth, meas, innov, innov_var); + + // Calculate K and Apply (Manually calling apply to mimic update step) + // K = PH' / S + matrix::Vector K = (P_truth * meas.H) / innov_var; + truth_filter.applyCorrection(x_truth, P_truth, K, innov, innov_var); + + // Predict t_meas -> t2 (150ms -> 300ms = 0.15s) + float dt_2 = (t2 - t_meas) * 1e-6f; + truth_filter.predictState(dt_2, kInput, x_truth, P_truth, x_truth, P_truth); + + // THEN: state matches the chronological result and covariance stays within approximation tolerance. + EXPECT_NEAR(val_oosm_state, x_truth(0), kTolerance) << "State mismatch: OOSM vs Truth"; + + // Covariance: Will differ slightly. + // OOSM uses an approximation for covariance propagation (Projected P). + // Truth uses exact sequential P propagation. + // We increase tolerance to ~1-2% of the value to account for this approximation. + EXPECT_NEAR(val_oosm_cov, P_truth(0, 0), 0.01f) << "Covariance mismatch exceeds approximation tolerance"; +} + +// WHY: A second delayed measurement in the same history interval must use the first delayed posterior as its floor. +// WHAT: Fuse delayed samples at 150 ms and 175 ms into history at 100/200/300 ms and compare with chronological truth. +TEST_F(VTEOosmTest, FusesSequentialDelayedMeasurementsInSameInterval) +{ + // GIVEN: history sampled at 100/200/300 ms and two delayed measurements in the same interval. + static constexpr uint64_t t0 = 100_ms; + static constexpr uint64_t t_meas_1 = 150_ms; + static constexpr uint64_t t_meas_2 = 175_ms; + static constexpr uint64_t t1 = 200_ms; + static constexpr uint64_t t2 = 300_ms; + static constexpr float kInput = 2.f; + + const auto x0 = makeVec(0.f); + const auto P0 = makeCov(1.f); + const ScalarMeas meas_1 = makeMeas(t_meas_1, 10.f, 1.f); + const ScalarMeas meas_2 = makeMeas(t_meas_2, 8.f, 1.f); + + matrix::Vector x1{}; + matrix::Vector x2{}; + matrix::SquareMatrix P1{}; + matrix::SquareMatrix P2{}; + + filter.predictState((t1 - t0) * 1e-6f, kInput, x0, P0, x1, P1); + filter.predictState((t2 - t1) * 1e-6f, kInput, x1, P1, x2, P2); + + oosm.reset(); + filter.resetTracking(); + oosm.push(t0, x0, P0, kInput); + oosm.push(t1, x1, P1, kInput); + oosm.push(t2, x2, P2, kInput); + + state = x2(0); + cov = P2(0, 0); + curr_input = kInput; + + // WHEN: both delayed samples are fused in arrival order at t2. + const vte::FusionResult res_1 = fuseMeas(meas_1, t2, 100.f); + const vte::FusionResult res_2 = fuseMeas(meas_2, t2, 100.f); + + // THEN: each delayed fusion succeeds and the second replay still updates the later stored samples. + EXPECT_EQ(res_1.status, vte::FusionStatus::STATUS_FUSED_OOSM); + EXPECT_EQ(res_2.status, vte::FusionStatus::STATUS_FUSED_OOSM); + EXPECT_EQ(res_2.history_steps, 2); + + TestFilter truth_filter; + matrix::Vector x_truth = x0; + matrix::SquareMatrix P_truth = P0; + + auto fuseTruth = [&](const ScalarMeas & meas) { + float innov = 0.f; + float innov_var = 0.f; + truth_filter.computeInnovation(x_truth, P_truth, meas, innov, innov_var); + const matrix::Vector K = (P_truth * meas.H) / innov_var; + truth_filter.applyCorrection(x_truth, P_truth, K, innov, innov_var); + }; + + truth_filter.predictState((t_meas_1 - t0) * 1e-6f, kInput, x_truth, P_truth, x_truth, P_truth); + fuseTruth(meas_1); + truth_filter.predictState((t_meas_2 - t_meas_1) * 1e-6f, kInput, x_truth, P_truth, x_truth, P_truth); + fuseTruth(meas_2); + truth_filter.predictState((t2 - t_meas_2) * 1e-6f, kInput, x_truth, P_truth, x_truth, P_truth); + + EXPECT_NEAR(state, x_truth(0), kTolerance); + EXPECT_NEAR(cov, P_truth(0, 0), 0.01f); +} + +// WHY: Delayed samples that both land after the newest stored sample still need an inserted posterior for the next fusion. +// WHAT: Fuse delayed samples at 130 ms and 145 ms when history only contains 100 ms, then compare with chronological truth at 170 ms. +TEST_F(VTEOosmTest, FusesSequentialDelayedMeasurementsAfterNewestHistorySample) +{ + // GIVEN: only the 100 ms sample is stored, while both delayed measurements fall between that sample and now. + static constexpr uint64_t t0 = 100_ms; + static constexpr uint64_t t_meas_1 = 130_ms; + static constexpr uint64_t t_meas_2 = 145_ms; + static constexpr uint64_t now_us = 170_ms; + static constexpr float kInput = 3.f; + + const auto x0 = makeVec(0.f); + const auto P0 = makeCov(1.f); + const ScalarMeas meas_1 = makeMeas(t_meas_1, 5.f, 1.f); + const ScalarMeas meas_2 = makeMeas(t_meas_2, 4.f, 1.f); + + matrix::Vector x_now{}; + matrix::SquareMatrix P_now{}; + filter.predictState((now_us - t0) * 1e-6f, kInput, x0, P0, x_now, P_now); + + oosm.reset(); + filter.resetTracking(); + oosm.push(t0, x0, P0, kInput); + + state = x_now(0); + cov = P_now(0, 0); + curr_input = kInput; + + // WHEN: both delayed samples are fused before the next live sample is pushed. + const vte::FusionResult res_1 = fuseMeas(meas_1, now_us, 100.f); + const vte::FusionResult res_2 = fuseMeas(meas_2, now_us, 100.f); + + // THEN: both delayed fusions succeed using the live input branch and still match chronological truth. + EXPECT_EQ(res_1.status, vte::FusionStatus::STATUS_FUSED_OOSM); + EXPECT_EQ(res_2.status, vte::FusionStatus::STATUS_FUSED_OOSM); + EXPECT_EQ(res_2.history_steps, 0); + EXPECT_FLOAT_EQ(filter.last_predict_input, curr_input); + + TestFilter truth_filter; + matrix::Vector x_truth = x0; + matrix::SquareMatrix P_truth = P0; + + auto fuseTruth = [&](const ScalarMeas & meas) { + float innov = 0.f; + float innov_var = 0.f; + truth_filter.computeInnovation(x_truth, P_truth, meas, innov, innov_var); + const matrix::Vector K = (P_truth * meas.H) / innov_var; + truth_filter.applyCorrection(x_truth, P_truth, K, innov, innov_var); + }; + + truth_filter.predictState((t_meas_1 - t0) * 1e-6f, kInput, x_truth, P_truth, x_truth, P_truth); + fuseTruth(meas_1); + truth_filter.predictState((t_meas_2 - t_meas_1) * 1e-6f, kInput, x_truth, P_truth, x_truth, P_truth); + fuseTruth(meas_2); + truth_filter.predictState((now_us - t_meas_2) * 1e-6f, kInput, x_truth, P_truth, x_truth, P_truth); + + EXPECT_NEAR(state, x_truth(0), kTolerance); + EXPECT_NEAR(cov, P_truth(0, 0), 0.01f); +} + +// WHY: 2D OOSM must project corrections through the full transition matrix. +// WHAT: Compare delayed fusion against chronological replay with non-zero control input. +TEST_F(VTEOosmTest2d, FusesOosm2dTruthComparison) +{ + // GIVEN: a 2D linear system with delayed position measurement and stored history. + + static constexpr uint64_t t0 = 100_ms; + static constexpr uint64_t t_meas = 150_ms; + static constexpr uint64_t t1 = 200_ms; + static constexpr uint64_t t2 = 300_ms; + + static constexpr float kInput = 0.5f; + static constexpr float kDtStep = 0.1f; + + // Initial Conditions + const StateVec2 x0 = makeVec(0.f, 5.f); + const StateCov2 P0 = makeCov(1.f, 1.f, 0.f); + + // Measurement: Position only (H=[1,0]), Value=0.2 + const ScalarMeas2 meas = makeMeas(t_meas, 0.2f, 1.f, 1.f, 0.f); + + matrix::Vector x1, x2; + matrix::SquareMatrix P1, P2; + + // Predict t0 -> t1 -> t2 + filter.predictState(kDtStep, kInput, x0, P0, x1, P1); + filter.predictState(kDtStep, kInput, x1, P1, x2, P2); + + oosm.reset(); + filter.resetTracking(); + oosm.push(t0, x0, P0, kInput); + oosm.push(t1, x1, P1, kInput); + oosm.push(t2, x2, P2, kInput); + + // Current State is t2 + state = x2; + cov = P2; + curr_input = kInput; + + // WHEN: we fuse the delayed sample through OOSM and through perfect chronological replay. + const vte::FusionResult oosm_res = fuseMeas(meas, t2, 100.f); + EXPECT_EQ(oosm_res.status, vte::FusionStatus::STATUS_FUSED_OOSM); + + const StateVec2 oosm_state = state; + const StateCov2 oosm_cov = cov; + + // We run a separate filter instance in perfect chronological order. + TestFilter2d truth_filter; + StateVec2 x_truth = x0; + StateCov2 P_truth = P0; + + // Predict t0 -> t_meas + float dt_1 = (t_meas - t0) * 1e-6f; + truth_filter.predictState(dt_1, kInput, x_truth, P_truth, x_truth, P_truth); + + // Fuse at t_meas + float innov, innov_var; + truth_filter.computeInnovation(x_truth, P_truth, meas, innov, innov_var); + StateVec2 K = P_truth * meas.H / innov_var; // Simple K calculation for this scope + + // Manual correction + const matrix::Matrix &K_mat = K; + x_truth = x_truth + K * innov; + P_truth = P_truth - (K_mat * K.transpose()) * innov_var; + + // Predict t_meas -> t2 + float dt_2 = (t2 - t_meas) * 1e-6f; + truth_filter.predictState(dt_2, kInput, x_truth, P_truth, x_truth, P_truth); + + // THEN: both state components and covariance remain close to the truth model. + EXPECT_NEAR(oosm_state(0), x_truth(0), kTolerance) << "Position Mismatch"; + EXPECT_NEAR(oosm_state(1), x_truth(1), kTolerance) << "Velocity Mismatch"; + + // Covariance approx tolerance (~1-2%) + EXPECT_NEAR(oosm_cov(0, 0), P_truth(0, 0), 0.05f) << "Cov(0,0) Mismatch"; + EXPECT_NEAR(oosm_cov(1, 1), P_truth(1, 1), 0.05f) << "Cov(1,1) Mismatch"; +} + +// WHY: The OOSM manager relies on a ring buffer. Indices must wrap correctly. +// WHAT: Push enough samples to wrap the buffer (Size=8), then perform OOSM +// on a sample that is technically "older" in memory index but "newer" in time +// than the wrapped limit, ensuring the iterator logic holds. +TEST_F(VTEOosmTest, HandlesRingBufferWrapAroundAndBoundaries) +{ + // GIVEN: a history buffer that wraps around and then a second history with 1 ms spacing. + + // Standard Wrap-Around (Wide Timestamps) + // Fill buffer (0 to 7) + for (int i = 0; i < 8; ++i) { + pushSample(100_ms * (i + 1), (float)i, 1.f, 0.f); + } + + // Buffer: [100 ms, 200 ms, ..., 800 ms] + // Push 9th sample (wraps to index 0, overwrites 100 ms) + pushSample(900_ms, 9.f, 1.f, 0.f); + + // State: + // Newest: 900 ms (Index 0) + // Oldest: 200 ms (Index 1) + // Now: 950 ms + // Max OOSM Lag: kOosmMaxTimeUs -> Cutoff: (Now - kOosmMaxTimeUs) + const uint64_t now_us = 950_ms; + const uint64_t max_oosm_lag = Manager::kOosmMaxTimeUs; + const uint64_t cutoff_time = now_us - max_oosm_lag; + + // Verify Valid Fusion in the middle + // This forces the search to traverse from Index 0 backwards to Index 4 + // And the correction loop to traverse Index 4 -> 5 -> 6 -> 7 -> 0 + const uint64_t mid_offset = 100_ms; + const ScalarMeas meas_mid = makeMeas(cutoff_time + mid_offset, 5.5f, 1.f); + + // WHEN: we fuse delayed samples in the middle of the wrapped buffer and at the time-window edges. + EXPECT_EQ(fuseMeas(meas_mid, now_us, 10.f).status, + vte::FusionStatus::STATUS_FUSED_OOSM) << "Failed mid-buffer fusion"; + + // Verify Time Window Boundaries (Max OOSM Timeout) + + // Case A: Just inside the window (cutoff time) -> Should Fuse (floor is 400 ms) + // Note: now - cutoff_time = kOosmMaxTimeUs. Code uses `if (diff > max)`, so equal is OK. + const ScalarMeas meas_edge_valid = makeMeas(cutoff_time, 4.5f, 1.f); + EXPECT_EQ(fuseMeas(meas_edge_valid, now_us, 10.f).status, + vte::FusionStatus::STATUS_FUSED_OOSM) << "Failed valid edge case (cutoff time)"; + + // Case B: Just outside the window (cutoff - 10 us) -> Reject Too Old + const uint64_t edge_invalid_time = cutoff_time - 10_us; + const ScalarMeas meas_edge_invalid = makeMeas(edge_invalid_time, 4.5f, 1.f); + EXPECT_EQ(fuseMeas(meas_edge_invalid, now_us, 10.f).status, + vte::FusionStatus::STATUS_REJECT_TOO_OLD) << "Failed invalid edge case (cutoff - 10 us)"; + + // Tight Timestamp Verification + // We reset and use tiny time steps to prove that data is rejected + // because it fell off the ring buffer, NOT because of the max OOSM timeout. + oosm.reset(); + filter.resetTracking(); + state = 0.f; + cov = 4.f; + + // We need time_diff > kOosmMinTimeUs to force OOSM logic. + // We use 1ms steps. + // Buffer: [10ms, 11ms, ..., 17ms] (Size 8) + const uint64_t base_t = 10_ms; + const uint64_t step_t = 1_ms; + + for (int i = 0; i < 8; ++i) { + pushSample(base_t + step_t *i, (float)i, 1.f, 0.f); + } + + // Buffer: [10 ms, 11 ms, ..., 17 ms] + + // Push 9th sample (wraps to index 0, overwrites 10 ms) + // Timestamp: 18 ms + pushSample(base_t + step_t * 8, 9.f, 1.f, 0.f); + + // Buffer State: + // Newest: 18 ms + // Oldest: 11 ms (Index 1) + + // Set 'now' such that (now - meas) > kOosmMinTimeUs to avoid FUSED_CURRENT. + const uint64_t extra_margin = 10_ms; + const uint64_t tight_now = base_t + Manager::kOosmMinTimeUs + extra_margin; + + // Case C: Try to fuse time=base_t + 500 us. + // Time diff = tight_now - meas_overwritten_time (> kOosmMinTimeUs). + // History Check: 10.5 ms < Oldest (11 ms). + // MUST return REJECT_TOO_OLD (buffer overwritten). + const uint64_t meas_overwritten_time = base_t + 500_us; + const ScalarMeas meas_overwritten = makeMeas(meas_overwritten_time, 0.f, 1.f); + vte::FusionResult res_over = fuseMeas(meas_overwritten, tight_now, 10.f); + + EXPECT_EQ(res_over.status, vte::FusionStatus::STATUS_REJECT_TOO_OLD) + << "Expected REJECT_TOO_OLD for overwritten sample. Got: " << (int)res_over.status; + + // Case D: Verify boundary of new oldest (11 ms) + const uint64_t oldest_time = base_t + step_t; + const ScalarMeas meas_oldest_valid = makeMeas(oldest_time, 0.f, 1.f); + vte::FusionResult res_valid = fuseMeas(meas_oldest_valid, tight_now, 10.f); + + // THEN: wrapped-but-valid samples still fuse, while overwritten samples are rejected as too old. + EXPECT_EQ(res_valid.status, vte::FusionStatus::STATUS_FUSED_OOSM) + << "Expected FUSED_OOSM for oldest valid sample. Got: " << (int)res_valid.status; +} + +// WHY: OOSM logic has a specific optimization when t_meas == t_history. +// WHAT: Verify fusion works when measurement time aligns exactly with a sample. +TEST_F(VTEOosmTest, FusesOosmExactTimeMatch) +{ + // GIVEN: history containing a sample with the exact same timestamp as the delayed measurement. + pushSample(100_ms, 0.f, 4.f, 0.f); + pushSample(200_ms, 2.f, 4.f, 0.f); + + // Measurement matches the sample at 100 ms exactly + const ScalarMeas meas = makeMeas(100_ms, 0.5f, 1.f); + + // WHEN: the exact-match delayed sample is fused. + const vte::FusionResult res = fuseMeas(meas, 250_ms, 10.f); + + // THEN: the OOSM path corrects history and projects it forward. + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_OOSM); + // Should update 100 ms (floor) and project to 200 ms, then Live. + EXPECT_GT(filter.applied_k.size(), 0u); +} + +// WHY: A delayed measurement might look valid now, but was an outlier at the time it occurred. +// WHAT: Provide a measurement that contradicts the history state at t_meas. +TEST_F(VTEOosmTest, RejectsNisDuringOosmPrediction) +{ + // GIVEN: a delayed measurement whose residual is large at its own timestamp. + pushSample(100_ms, 0.f, 0.1f, 0.f); + pushSample(200_ms, 0.f, 0.1f, 0.f); + + // State at 150 ms is ~0.0. Meas is 10.0. Variance small. Should fail NIS. + const ScalarMeas meas = makeMeas(150_ms, 10.f, 0.1f); + + // WHEN: the OOSM logic evaluates that historical innovation. + const vte::FusionResult res = fuseMeas(meas, 250_ms, 1.f); + + // THEN: the delayed sample is rejected before any projected correction is applied. + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_REJECT_NIS); + // Ensure no history corrections were applied + EXPECT_EQ(filter.applied_k.size(), 0u); +} + +// WHY: The flat timeline view is the foundation the OOSM path builds on; verify it against an empty buffer. +// WHAT: copyHistoryToLinearTimeline must return count==0 when no samples have been pushed. +TEST_F(VTEOosmTest, LinearTimelineCopyFromEmptyHistory) +{ + using Access = vte::OOSMManagerTestAccess; + + // GIVEN: a fresh manager with no pushed samples. + Manager::LinearTimeline tl{}; + + // WHEN: we snapshot the history into a linear timeline. + Access::copyHistoryToLinearTimeline(oosm, tl); + + // THEN: the linear timeline is empty. + EXPECT_EQ(tl.count, 0u); +} + +// WHY: Basic sanity that samples come out oldest->newest with all fields preserved. +// WHAT: Push three samples and inspect time/state/input ordering in the linear timeline. +TEST_F(VTEOosmTest, LinearTimelineCopyPartialHistoryPreservesOrderAndFields) +{ + using Access = vte::OOSMManagerTestAccess; + + // GIVEN: three chronologically pushed samples with distinct state and input values. + pushSample(100_ms, 1.f, 2.f, 0.5f); + pushSample(200_ms, 2.f, 3.f, 1.0f); + pushSample(300_ms, 3.f, 4.f, 1.5f); + + // WHEN: we snapshot the history into a linear timeline. + Manager::LinearTimeline tl{}; + Access::copyHistoryToLinearTimeline(oosm, tl); + + // THEN: the timeline is oldest->newest and every field matches what was pushed. + ASSERT_EQ(tl.count, 3u); + EXPECT_EQ(tl.samples[0].time_us, 100_ms); + EXPECT_EQ(tl.samples[1].time_us, 200_ms); + EXPECT_EQ(tl.samples[2].time_us, 300_ms); + EXPECT_FLOAT_EQ(tl.samples[0].state(0), 1.f); + EXPECT_FLOAT_EQ(tl.samples[1].state(0), 2.f); + EXPECT_FLOAT_EQ(tl.samples[2].state(0), 3.f); + EXPECT_FLOAT_EQ(tl.samples[0].cov(0, 0), 2.f); + EXPECT_FLOAT_EQ(tl.samples[2].cov(0, 0), 4.f); + EXPECT_FLOAT_EQ(tl.samples[0].input, 0.5f); + EXPECT_FLOAT_EQ(tl.samples[1].input, 1.0f); + EXPECT_FLOAT_EQ(tl.samples[2].input, 1.5f); +} + +// WHY: After wrap-around, the ring-buffer layout no longer matches chronological order; +// the linear timeline must still return samples oldest->newest. +// WHAT: Push more samples than buffer capacity (8) and verify the oldest ones were dropped +// while the remaining ones come out in chronological order. +TEST_F(VTEOosmTest, LinearTimelineCopyAfterRingBufferWrap) +{ + using Access = vte::OOSMManagerTestAccess; + + // GIVEN: 10 pushed samples in a buffer of capacity 8 (the two oldest are overwritten). + for (int i = 0; i < 10; ++i) { + pushSample(100_ms * (i + 1), static_cast(i), 1.f, static_cast(i)); + } + + // WHEN: we snapshot the wrapped history into a linear timeline. + Manager::LinearTimeline tl{}; + Access::copyHistoryToLinearTimeline(oosm, tl); + + // THEN: only the 8 most recent samples remain, in chronological order. + ASSERT_EQ(tl.count, 8u); + + for (size_t i = 0; i < tl.count; ++i) { + const uint64_t expected_time = 100_ms * (i + 3); // first two (i=0,1) got overwritten + EXPECT_EQ(tl.samples[i].time_us, expected_time); + EXPECT_FLOAT_EQ(tl.samples[i].state(0), static_cast(i + 2)); + EXPECT_FLOAT_EQ(tl.samples[i].input, static_cast(i + 2)); + } +} + +// WHY: rebuildHistoryFromLinearTimeline is the commit step for OOSM; it must produce a history +// that round-trips back to the same timeline. +// WHAT: Rebuild from a 3-sample timeline and verify entry count, bounds, and round-trip equality. +TEST_F(VTEOosmTest, LinearTimelineRebuildWithinCapacityRoundTrips) +{ + using Access = vte::OOSMManagerTestAccess; + + // GIVEN: a three-entry linear timeline built by hand. + Manager::LinearTimeline tl{}; + tl.samples[0].time_us = 100_ms; + tl.samples[0].state(0) = 1.f; + tl.samples[0].cov(0, 0) = 2.f; + tl.samples[0].input = 0.5f; + tl.samples[1].time_us = 200_ms; + tl.samples[1].state(0) = 2.f; + tl.samples[1].cov(0, 0) = 3.f; + tl.samples[1].input = 1.0f; + tl.samples[2].time_us = 300_ms; + tl.samples[2].state(0) = 3.f; + tl.samples[2].cov(0, 0) = 4.f; + tl.samples[2].input = 1.5f; + tl.count = 3; + + // WHEN: we commit the timeline into the ring buffer. + Access::rebuildHistoryFromLinearTimeline(oosm, tl); + + // THEN: the ring buffer exposes the same number of entries with matching bounds. + EXPECT_EQ(Access::historyEntries(oosm), 3); + EXPECT_EQ(Access::historyOldestTime(oosm), 100_ms); + EXPECT_EQ(Access::historyNewestTime(oosm), 300_ms); + + // AND: copying it back yields the original timeline. + Manager::LinearTimeline tl_round_trip{}; + Access::copyHistoryToLinearTimeline(oosm, tl_round_trip); + ASSERT_EQ(tl_round_trip.count, tl.count); + + for (size_t i = 0; i < tl.count; ++i) { + EXPECT_EQ(tl_round_trip.samples[i].time_us, tl.samples[i].time_us); + EXPECT_FLOAT_EQ(tl_round_trip.samples[i].state(0), tl.samples[i].state(0)); + EXPECT_FLOAT_EQ(tl_round_trip.samples[i].cov(0, 0), tl.samples[i].cov(0, 0)); + EXPECT_FLOAT_EQ(tl_round_trip.samples[i].input, tl.samples[i].input); + } +} + +// WHY: When fuse() inserts a posterior and overflows capacity, rebuild must drop only the oldest +// sample so the buffer stays at exactly kHistorySize entries. +// WHAT: Rebuild from a 9-sample timeline (capacity is 8) and check that the oldest is dropped. +TEST_F(VTEOosmTest, LinearTimelineRebuildOverflowDropsOldest) +{ + using Access = vte::OOSMManagerTestAccess; + + // GIVEN: 9 chronologically ordered samples (one more than the buffer can hold). + Manager::LinearTimeline tl{}; + + for (size_t i = 0; i < 9; ++i) { + tl.samples[i].time_us = 100_ms * (i + 1); + tl.samples[i].state(0) = static_cast(i); + tl.samples[i].cov(0, 0) = 1.f; + tl.samples[i].input = 0.f; + } + + tl.count = 9; + + // WHEN: we commit the oversized timeline into the ring buffer. + Access::rebuildHistoryFromLinearTimeline(oosm, tl); + + // THEN: the buffer holds exactly kHistorySize entries and the oldest sample was dropped. + EXPECT_EQ(Access::historyEntries(oosm), 8); + EXPECT_EQ(Access::historyOldestTime(oosm), 200_ms); + EXPECT_EQ(Access::historyNewestTime(oosm), 900_ms); +} + +// WHY: A no-op round trip (copy -> rebuild -> copy) must preserve all samples exactly, +// ensuring the helpers do not introduce ordering or content drift. +// WHAT: Push samples through the ring (including wrap), round-trip them, and verify equality. +TEST_F(VTEOosmTest, LinearTimelineRoundTripIsIdentity) +{ + using Access = vte::OOSMManagerTestAccess; + + // GIVEN: a wrapped ring buffer populated via push(). + for (int i = 0; i < 10; ++i) { + pushSample(100_ms * (i + 1), static_cast(i), 1.f + i * 0.1f, static_cast(i)); + } + + Manager::LinearTimeline tl_before{}; + Access::copyHistoryToLinearTimeline(oosm, tl_before); + + // WHEN: we rebuild from the snapshot and re-read it. + Access::rebuildHistoryFromLinearTimeline(oosm, tl_before); + + Manager::LinearTimeline tl_after{}; + Access::copyHistoryToLinearTimeline(oosm, tl_after); + + // THEN: both linear timelines are element-wise identical. + ASSERT_EQ(tl_before.count, tl_after.count); + + for (size_t i = 0; i < tl_before.count; ++i) { + EXPECT_EQ(tl_before.samples[i].time_us, tl_after.samples[i].time_us); + EXPECT_FLOAT_EQ(tl_before.samples[i].state(0), tl_after.samples[i].state(0)); + EXPECT_FLOAT_EQ(tl_before.samples[i].cov(0, 0), tl_after.samples[i].cov(0, 0)); + EXPECT_FLOAT_EQ(tl_before.samples[i].input, tl_after.samples[i].input); + } +} + +} // namespace diff --git a/src/modules/vision_target_estimator/test/TEST_VTEOrientation.cpp b/src/modules/vision_target_estimator/test/TEST_VTEOrientation.cpp new file mode 100644 index 00000000000..4ba6e241345 --- /dev/null +++ b/src/modules/vision_target_estimator/test/TEST_VTEOrientation.cpp @@ -0,0 +1,435 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file TEST_VTEOrientation.cpp + * @brief Unit test VTEOrientation.cpp + * + * @author Jonas Perolini + * + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Orientation/VTEOrientation.h" +#include "VTETestHelper.hpp" + +namespace vte = vision_target_estimator; + +namespace +{ +using namespace time_literals; + +static constexpr float kTolerance = 1e-4f; +static constexpr float kPi = static_cast(M_PI); +static constexpr float kTwoPi = 2.f * kPi; +static constexpr hrt_abstime kStepUs = 1_ms; + +// Default EV noise parameter and the corresponding variance (params are configured as std-dev). +static constexpr float kDefaultEvYawNoise = 0.5f; +static constexpr float kDefaultEvYawVar = kDefaultEvYawNoise * kDefaultEvYawNoise; +// Typical reported variance of a clean yaw measurement; smaller than the floor so the floor applies. +static constexpr float kMeasVar = 0.01f; +// Initial state uncertainty used by the test parameter VTE_YAW_UNC_IN. +static constexpr float kInitialYawUnc = 0.2f; +// NIS threshold permissive enough to accept any realistic innovation. +static constexpr float kPermissiveNis = 100.f; +// NIS threshold low enough to reject everything but tiny innovations. +static constexpr float kRestrictiveNis = 0.2f; +// The estimator rejects prediction gaps longer than 100 ms — see kMaxPredictionDeltaTimeUs. +static constexpr hrt_abstime kStaleGapUs = 120_ms; + +class VTEOrientationTestable : public vte::VTEOrientation +{ +public: + void updateParamsPublic() { updateParams(); } +}; + +} // namespace + +class VTEOrientationTest : public ::testing::Test +{ +protected: + static void SetUpTestSuite() { uORB::Manager::initialize(); } + + void SetUp() override + { + param_control_autosave(false); + vte_test::useFakeTime(); + + setParamFloat("VTE_YAW_UNC_IN", kInitialYawUnc); + setParamFloat("VTE_EVA_NOISE", kDefaultEvYawNoise); + setParamFloat("VTE_YAW_NIS_THRE", vte::kDefaultNisThreshold); + + _vte = std::make_unique(); + ASSERT_TRUE(_vte->init()); + _vte->updateParamsPublic(); + + _vision_pub = std::make_unique>(ORB_ID(fiducial_marker_yaw_report)); + _aid_sub = std::make_unique>(ORB_ID(vte_aid_ev_yaw)); + _state_sub = std::make_unique>(ORB_ID(vte_orientation)); + + vte_test::flushSubscription(_aid_sub); + vte_test::flushSubscription(_state_sub); + } + + void TearDown() override + { + _param_guard.restore(); + param_control_autosave(true); + _state_sub.reset(); + _aid_sub.reset(); + _vision_pub.reset(); + + _vte.reset(); + vte_test::useRealTime(); + // Keep the uORB manager alive; parameters retain uORB handles across tests. + } + + void setParamFloat(const char *name, float value) + { + ASSERT_TRUE(_param_guard.setFloat(name, value)); + } + + void publishVisionYaw(float yaw, float yaw_var, hrt_abstime timestamp) + { + ASSERT_TRUE(vte_test::publishVisionYaw(*_vision_pub, yaw, yaw_var, timestamp)); + } + + void enableVisionFusion() + { + vte::SensorFusionMaskU mask{}; + mask.flags.use_vision_pos = 1; + _vte->setVteAidMask(mask.value); + } + + /** + * Publish a valid yaw sample timestamped kStepUs in the future and drive one update tick. + * Returns the published timestamp so tests can reference it (e.g. for OOSM replays). + */ + hrt_abstime pushValidYawSample(float yaw, float yaw_var = kMeasVar) + { + const hrt_abstime sample_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionYaw(yaw, yaw_var, sample_time); + _vte->update(); + return sample_time; + } + + std::unique_ptr _vte; + std::unique_ptr> _vision_pub; + std::unique_ptr> _aid_sub; + std::unique_ptr> _state_sub; + + vte_test::ParamGuard _param_guard{}; +}; + +// WHY: The estimator must initialize from the first valid yaw measurement. +// WHAT: Publish a valid yaw and verify state and innovation messages. +TEST_F(VTEOrientationTest, InitFromVisionYawPublishesOrientation) +{ + // GIVEN: vision fusion is enabled and the first measurement has finite yaw and variance. + enableVisionFusion(); + + // WHEN: the estimator processes the first yaw observation. + const float yaw_meas = 0.5f; + pushValidYawSample(yaw_meas); + + // THEN: the state initializes from that sample and publishes a fused innovation report. + ASSERT_TRUE(_state_sub->update()); + const auto state = _state_sub->get(); + EXPECT_NEAR(state.yaw, yaw_meas, kTolerance); + EXPECT_NEAR(state.yaw_rate, 0.f, kTolerance); + // Reported variance is clamped to the configured floor (EVA_NOISE^2) before fusion. + const float meas_var = fmaxf(kMeasVar, kDefaultEvYawVar); + const float expected_cov = (kInitialYawUnc * meas_var) / (kInitialYawUnc + meas_var); + EXPECT_NEAR(state.cov_yaw, expected_cov, kTolerance); + + ASSERT_TRUE(_aid_sub->update()); + const auto aid = _aid_sub->get(); + EXPECT_NEAR(aid.observation_variance, kDefaultEvYawVar, kTolerance); + EXPECT_EQ(aid.fusion_status, static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); +} + +// WHY: Fusion should be disabled when the aid mask is empty. +// WHAT: Publish a valid yaw without enabling vision fusion and expect no +// output. +TEST_F(VTEOrientationTest, DoesNotFuseWhenVisionDisabled) +{ + // GIVEN: a valid yaw report but no enabled aid source. + publishVisionYaw(0.2f, kMeasVar, vte_test::advanceMicroseconds(kStepUs)); + + // WHEN: the estimator updates. + _vte->update(); + + // THEN: no state or innovation message is published. + EXPECT_FALSE(_aid_sub->update()); + EXPECT_FALSE(_state_sub->update()); +} + +// Parametrized rejection tests: each row describes one way a sample can be invalid and must not fuse. +struct BadVisionSample { + const char *label; + float yaw; + float yaw_var; + bool stale; // true: timestamp older than the measurement-recent timeout +}; + +class VTEOrientationBadSampleTest : public VTEOrientationTest, + public ::testing::WithParamInterface {}; + +// WHY: Corrupt or stale yaw measurements must not initialize or fuse the filter. +// WHAT: Publish an invalid sample and ensure no outputs are produced. +TEST_P(VTEOrientationBadSampleTest, RejectsBadSample) +{ + const auto param = GetParam(); + + // GIVEN: vision fusion is enabled with a tight recency timeout used only by the stale variant. + enableVisionFusion(); + static constexpr hrt_abstime kMeasTimeoutUs = 1_ms; + _vte->setMeasRecentTimeout(kMeasTimeoutUs); + + const hrt_abstime timestamp = param.stale + ? vte_test::nowUs() - (kMeasTimeoutUs + 1_ms) + : vte_test::advanceMicroseconds(kStepUs); + publishVisionYaw(param.yaw, param.yaw_var, timestamp); + + // WHEN: the estimator processes the sample. + _vte->update(); + + // THEN: the sample is ignored. + EXPECT_FALSE(_aid_sub->update()) << param.label; + EXPECT_FALSE(_state_sub->update()) << param.label; +} + +INSTANTIATE_TEST_SUITE_P( + InvalidSamples, + VTEOrientationBadSampleTest, + ::testing::Values( + BadVisionSample{"NanYaw", NAN, kMeasVar, false}, + BadVisionSample{"NanVariance", 0.1f, NAN, false}, + BadVisionSample{"StaleTimestamp", 0.1f, kMeasVar, true} + ), +[](const testing::TestParamInfo &p) { return std::string(p.param.label); }); + +// WHY: Measurement variance must never drop below the configured floor. +// WHAT: Provide a tiny variance and verify the floor is applied. +TEST_F(VTEOrientationTest, YawNoiseFloor) +{ + // GIVEN: vision fusion is enabled and the configured floor is above the reported variance. + enableVisionFusion(); + + static constexpr float kEvNoise = 0.2f; + setParamFloat("VTE_EVA_NOISE", kEvNoise); + _vte->updateParamsPublic(); + + // WHEN: a sample with zero variance is fused. + pushValidYawSample(0.3f, /* yaw_var = */ 0.0f); + + // THEN: the innovation log uses the configured floor instead of zero variance. + ASSERT_TRUE(_aid_sub->update()); + const auto aid = _aid_sub->get(); + EXPECT_NEAR(aid.observation_variance, kEvNoise * kEvNoise, kTolerance); +} + +// WHY: NIS gating protects against yaw outliers. +// WHAT: Initialize at yaw 0, then fuse a far measurement and expect +// rejection. +TEST_F(VTEOrientationTest, RejectsOutlierNis) +{ + // GIVEN: an initialized estimator with a very small NIS threshold. + enableVisionFusion(); + setParamFloat("VTE_YAW_NIS_THRE", kRestrictiveNis); + _vte->updateParamsPublic(); + + pushValidYawSample(0.f); + ASSERT_TRUE(_state_sub->update()); + vte_test::flushSubscription(_aid_sub); + + // WHEN: a far-away yaw sample is fused. + pushValidYawSample(kPi); + + // THEN: the innovation is rejected and the state stays near the initialized yaw. + ASSERT_TRUE(_aid_sub->update()); + EXPECT_EQ(_aid_sub->get().fusion_status, + static_cast(vte::FusionStatus::STATUS_REJECT_NIS)); + + ASSERT_TRUE(_state_sub->update()); + EXPECT_NEAR(_state_sub->get().yaw, 0.f, 0.1f); +} + +// WHY: Wrap handling should not average 0 and 2pi to pi. +// WHAT: Toggle measurements near 0 and 2pi and verify yaw stays near zero. +TEST_F(VTEOrientationTest, WrapsAcrossZeroAndTwoPi) +{ + // GIVEN: an initialized estimator with two measurements straddling the wrap boundary. + enableVisionFusion(); + + const float yaw_near_zero = 0.01f; + const float yaw_near_two_pi = kTwoPi - 0.013f; + + pushValidYawSample(yaw_near_zero); + + // WHEN: both measurements are fused in sequence. + pushValidYawSample(yaw_near_two_pi); + + // THEN: the estimate stays close to zero instead of jumping toward pi. + ASSERT_TRUE(_state_sub->update()); + const float expected = matrix::wrap_pi(yaw_near_two_pi); + EXPECT_NEAR(_state_sub->get().yaw, expected, 0.1f); + EXPECT_LT(fabsf(_state_sub->get().yaw), 0.2f); +} + +// WHY: Initial yaw uncertainty is only meant to seed a new estimator instance. +// WHAT: Change VTE_YAW_UNC_IN while the filter is running and verify the active estimator is not reset. +TEST_F(VTEOrientationTest, DoesNotResetOnYawUncChangeWhileRunning) +{ + // GIVEN: an already running estimator with a fused yaw state. + enableVisionFusion(); + + pushValidYawSample(0.2f); + ASSERT_TRUE(_state_sub->update()); + const float cov_before = _state_sub->get().cov_yaw; + + // WHEN: the initial-uncertainty parameter changes while the estimator keeps running. + setParamFloat("VTE_YAW_UNC_IN", 10.f * kInitialYawUnc); + _vte->updateParamsPublic(); + pushValidYawSample(0.2f); + + // THEN: the live state keeps converging instead of being reinitialized (covariance must keep shrinking). + ASSERT_TRUE(_state_sub->update()); + const auto state = _state_sub->get(); + EXPECT_NEAR(state.yaw, 0.2f, 0.1f); + EXPECT_LT(state.cov_yaw, cov_before); +} + +// WHY: Delayed yaw measurements should follow the OOSM fusion path. +// WHAT: Populate history, then fuse a delayed measurement and expect FUSED_OOSM. +TEST_F(VTEOrientationTest, FusesOosmYawMeasurement) +{ + // GIVEN: an estimator with enough history for a delayed yaw sample. + enableVisionFusion(); + setParamFloat("VTE_YAW_NIS_THRE", kPermissiveNis); + _vte->updateParamsPublic(); + + // Seed the OOSM history with a few recent samples and capture the first predict timestamp. + hrt_abstime first_predict_time = 0; + + for (int i = 0; i < 3; ++i) { + pushValidYawSample(0.1f); + + if (_aid_sub->update() && (first_predict_time == 0)) { + first_predict_time = _aid_sub->get().time_last_predict; + } + + (void)_state_sub->update(); + } + + ASSERT_GT(first_predict_time, 0u); + + // Publish a sample stamped back at the first predict time, after advancing the clock. + vte_test::advanceMicroseconds(30_ms); + publishVisionYaw(0.12f, kMeasVar, first_predict_time); + + // WHEN: a measurement arrives delayed but still inside the OOSM window. + _vte->update(); + + // THEN: the OOSM path is taken and reports replayed history steps. + ASSERT_TRUE(_aid_sub->update()); + const auto aid = _aid_sub->get(); + EXPECT_EQ(aid.fusion_status, static_cast(vte::FusionStatus::STATUS_FUSED_OOSM)); + EXPECT_GT(aid.history_steps, 0u); +} + +// WHY: A long scheduling gap should reset the filter instead of predicting across stale time. +// WHAT: Initialize once, wait past the allowed prediction gap, then verify a fresh measurement re-initializes cleanly. +TEST_F(VTEOrientationTest, ResetsFilterOnStalePredictionGap) +{ + // GIVEN: an initialized estimator that then experiences a gap longer than the allowed prediction horizon. + enableVisionFusion(); + + pushValidYawSample(0.1f); + ASSERT_TRUE(_state_sub->update()); + EXPECT_NEAR(_state_sub->get().yaw, 0.1f, kTolerance); + + vte_test::flushSubscription(_aid_sub); + vte_test::flushSubscription(_state_sub); + + vte_test::advanceMicroseconds(kStaleGapUs); + + // WHEN: the estimator updates after the stale gap and then sees a fresh measurement. + _vte->update(); + EXPECT_FALSE(_aid_sub->update()); + EXPECT_FALSE(_state_sub->update()); + + pushValidYawSample(-0.25f); + + // THEN: the stale state is dropped and the fresh sample initializes a new current fusion. + ASSERT_TRUE(_aid_sub->update()); + EXPECT_EQ(_aid_sub->get().fusion_status, + static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); + + ASSERT_TRUE(_state_sub->update()); + const auto state = _state_sub->get(); + EXPECT_NEAR(state.yaw, -0.25f, kTolerance); + EXPECT_NEAR(state.yaw_rate, 0.f, kTolerance); +} + +// WHY: Orientation validity must reflect the configured timeout. +// WHAT: Set timeout to zero and confirm orientation_valid is false. +TEST_F(VTEOrientationTest, TargetValidityTimeout) +{ + // GIVEN: an estimator with zero target-valid timeout. + enableVisionFusion(); + _vte->setTargetValidTimeout(0); + + // WHEN: a valid sample is fused. + pushValidYawSample(0.1f); + + // THEN: the published state is immediately marked invalid. + ASSERT_TRUE(_state_sub->update()); + EXPECT_FALSE(_state_sub->get().orientation_valid); +} diff --git a/src/modules/vision_target_estimator/test/TEST_VTEPosition.cpp b/src/modules/vision_target_estimator/test/TEST_VTEPosition.cpp new file mode 100644 index 00000000000..6e1c134dc86 --- /dev/null +++ b/src/modules/vision_target_estimator/test/TEST_VTEPosition.cpp @@ -0,0 +1,1840 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file TEST_VTEPosition.cpp + * @brief Unit test VTEPosition.cpp + * + * @author Jonas Perolini + * + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Position/VTEPosition.h" +#include "VTETestHelper.hpp" + +namespace vte = vision_target_estimator; + +namespace +{ +using namespace time_literals; + +static constexpr float kTolerance = 1e-3f; +static constexpr hrt_abstime kStepUs = 1_ms; +static constexpr float kDefaultEvPosNoise = 0.2f; +static constexpr float kDefaultGpsPosNoise = 0.1f; +static constexpr float kDefaultGpsVelNoise = 0.2f; +static constexpr float kDefaultBiasUnc = 0.5f; +static constexpr float kDefaultEvPosVar = kDefaultEvPosNoise * kDefaultEvPosNoise; +static constexpr float kDefaultGpsPosVar = kDefaultGpsPosNoise * kDefaultGpsPosNoise; +static constexpr float kDefaultGpsVelVar = kDefaultGpsVelNoise * kDefaultGpsVelNoise; +static constexpr double kUavLat = 47.3977419; +static constexpr double kUavLon = 8.5455938; +static constexpr float kUavAltM = 100.f; +static constexpr float kTargetAltM = 90.f; + +// NIS threshold high enough to accept any realistic innovation (used when a test is +// not exercising the gating logic itself). +static constexpr float kPermissiveNisThreshold = 100.f; +// NIS threshold tight enough to reject everything but zero innovations. +static constexpr float kRestrictiveNisThreshold = 0.11f; +// Approximate meters per degree of latitude. +static constexpr double kMetersPerDegLat = 1.11111e5; +// Keep-alive period between synthetic update ticks while vision is withheld. +static constexpr hrt_abstime kKeepAliveStepUs = 50_ms; + +static const matrix::Vector3f kSmallVisionCov{0.01f, 0.01f, 0.01f}; +static const matrix::Vector3f kZeroVec{0.f, 0.f, 0.f}; + +enum class FusionMaskOption { + kVisionPos, + kMissionPos, + kTargetGpsPos, + kUavGpsVel, + kTargetGpsVel +}; + +class VTEPositionTestable : public vte::VTEPosition +{ +public: + using vte::VTEPosition::kAltMaxM; + using vte::VTEPosition::kLatAbsMaxDeg; + using vte::VTEPosition::kLonAbsMaxDeg; + void updateParamsPublic() { updateParams(); } +}; + +} // namespace + +class VTEPositionTest : public ::testing::Test +{ +protected: + static void SetUpTestSuite() { uORB::Manager::initialize(); } + + void SetUp() override + { + param_control_autosave(false); + vte_test::useFakeTime(); + + setParamFloat("VTE_POS_UNC_IN", 1.f); + setParamFloat("VTE_VEL_UNC_IN", 1.f); + setParamFloat("VTE_BIA_UNC_IN", kDefaultBiasUnc); + setParamFloat("VTE_EVP_NOISE", kDefaultEvPosNoise); + setParamFloat("VTE_GPS_P_NOISE", kDefaultGpsPosNoise); + setParamFloat("VTE_GPS_V_NOISE", kDefaultGpsVelNoise); + setParamFloat("VTE_POS_NIS_THRE", 3.84f); + setParamFloat("VTE_BIA_AVG_THR", 0.3f); + setParamFloat("VTE_BIA_AVG_TOUT", 1.0f); + + _vte = std::make_unique(); + ASSERT_TRUE(_vte->init()); + _vte->updateParamsPublic(); + + _vision_pub = std::make_unique>(ORB_ID(fiducial_marker_pos_report)); + _uav_gps_pub = std::make_unique>(ORB_ID(vehicle_gps_position)); + _target_gps_pub = std::make_unique>(ORB_ID(target_gnss)); + + _aid_fiducial_sub = std::make_unique>(ORB_ID(vte_aid_fiducial_marker)); + _aid_gps_mission_sub = std::make_unique>(ORB_ID(vte_aid_gps_pos_mission)); + _aid_gps_target_sub = std::make_unique>(ORB_ID(vte_aid_gps_pos_target)); + _aid_gps_vel_uav_sub = std::make_unique>(ORB_ID(vte_aid_gps_vel_uav)); + _aid_gps_vel_target_sub = std::make_unique>(ORB_ID(vte_aid_gps_vel_target)); + _bias_init_status_sub = std::make_unique>(ORB_ID(vte_bias_init_status)); + _vte_state_sub = std::make_unique>(ORB_ID(vte_position)); + _target_pose_sub = std::make_unique>(ORB_ID(landing_target_pose)); + + vte_test::flushSubscription(_aid_fiducial_sub); + vte_test::flushSubscription(_aid_gps_mission_sub); + vte_test::flushSubscription(_aid_gps_target_sub); + vte_test::flushSubscription(_aid_gps_vel_uav_sub); + vte_test::flushSubscription(_aid_gps_vel_target_sub); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + vte_test::flushSubscription(_target_pose_sub); + } + + void TearDown() override + { + _param_guard.restore(); + param_control_autosave(true); + _target_pose_sub.reset(); + _vte_state_sub.reset(); + _aid_gps_vel_target_sub.reset(); + _aid_gps_vel_uav_sub.reset(); + _aid_gps_target_sub.reset(); + _aid_gps_mission_sub.reset(); + _aid_fiducial_sub.reset(); + _bias_init_status_sub.reset(); + _target_gps_pub.reset(); + _uav_gps_pub.reset(); + _vision_pub.reset(); + + _vte.reset(); + vte_test::useRealTime(); + // Keep the uORB manager alive; parameters retain uORB handles across tests. + } + + void setParamFloat(const char *name, float value) + { + ASSERT_TRUE(_param_guard.setFloat(name, value)); + } + + void enableMask(std::initializer_list sources) + { + vte::SensorFusionMaskU mask{}; + + for (const FusionMaskOption source : sources) { + switch (source) { + case FusionMaskOption::kVisionPos: + mask.flags.use_vision_pos = 1; + break; + + case FusionMaskOption::kMissionPos: + mask.flags.use_mission_pos = 1; + break; + + case FusionMaskOption::kTargetGpsPos: + mask.flags.use_target_gps_pos = 1; + break; + + case FusionMaskOption::kUavGpsVel: + mask.flags.use_uav_gps_vel = 1; + break; + + case FusionMaskOption::kTargetGpsVel: + mask.flags.use_target_gps_vel = 1; + break; + } + } + + _vte->setVteAidMask(mask.value); + } + + void publishVisionPos(const matrix::Vector3f &rel_pos, const matrix::Quaternionf &q, + const matrix::Vector3f &cov, hrt_abstime timestamp) + { + ASSERT_TRUE(vte_test::publishVisionPos(*_vision_pub, rel_pos, q, cov, timestamp)); + } + + void publishUavGps(double lat, double lon, float alt, float eph, float epv, + const matrix::Vector3f &vel_ned, float vel_var, bool vel_valid, hrt_abstime timestamp) + { + ASSERT_TRUE(vte_test::publishUavGps(*_uav_gps_pub, lat, lon, alt, eph, epv, vel_ned, vel_var, vel_valid, timestamp)); + } + + void publishTargetGnss(double lat, double lon, float alt, float eph, float epv, + hrt_abstime timestamp, bool abs_pos_updated, bool vel_ned_updated = false, + const matrix::Vector3f &vel_ned = matrix::Vector3f{}, float vel_acc = NAN) + { + ASSERT_TRUE(vte_test::publishTargetGnss(*_target_gps_pub, lat, lon, alt, eph, epv, timestamp, + abs_pos_updated, vel_ned_updated, vel_ned, vel_acc)); + } + + void setLocalVelocity(const matrix::Vector3f &vel_ned, hrt_abstime timestamp) + { + _vte->setLocalVelocity(vel_ned, true, timestamp); + } + + void setLocalPosition(const matrix::Vector3f &pos_ned, hrt_abstime timestamp) + { + _vte->setLocalPosition(pos_ned, true, timestamp); + } + + void publishNominalUavGps(const matrix::Vector3f &vel_ned, hrt_abstime timestamp) + { + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.2f, 0.2f, vel_ned, 0.1f, true, timestamp); + } + + void initializeFromMissionGnss(const matrix::Vector3f &vel_ned, double mission_lat = kUavLat, + double mission_lon = kUavLon, float mission_alt = kTargetAltM) + { + const hrt_abstime gps_time = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_time); + _vte->setMissionPosition(mission_lat, mission_lon, mission_alt); + _vte->update(matrix::Vector3f{}); + ASSERT_TRUE(_vte_state_sub->update()); + } + + void flushVisionAndMissionOutputs() + { + vte_test::flushSubscription(_aid_fiducial_sub); + vte_test::flushSubscription(_aid_gps_mission_sub); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + } + + void flushMissionOutputs() + { + vte_test::flushSubscription(_vte_state_sub); + vte_test::flushSubscription(_aid_gps_mission_sub); + } + + void expectBiasNear(const vte_position_s &state, const matrix::Vector3f &expected_bias, + float tolerance) + { + EXPECT_NEAR(state.bias[0], expected_bias(0), tolerance); + EXPECT_NEAR(state.bias[1], expected_bias(1), tolerance); + EXPECT_NEAR(state.bias[2], expected_bias(2), tolerance); + } + + /** + * Advance the filter by roughly @p duration_us while keeping the UAV GPS stream alive + * so bias averaging keeps ticking. Optionally refresh local velocity as we tick so the + * local-velocity timestamp stays fresh (required by some bias-averaging paths). + */ + void advanceEstimatorWithGps(hrt_abstime duration_us, const matrix::Vector3f &vel_ned, + bool refresh_local_velocity = false) + { + hrt_abstime elapsed = 0; + + while (elapsed < duration_us) { + const hrt_abstime remaining = duration_us - elapsed; + const hrt_abstime step = (remaining < kKeepAliveStepUs) ? remaining : kKeepAliveStepUs; + const hrt_abstime now = vte_test::advanceMicroseconds(step); + + if (refresh_local_velocity) { + setLocalVelocity(vel_ned, now); + } + + publishNominalUavGps(vel_ned, now); + _vte->update(matrix::Vector3f{}); + flushMissionOutputs(); + elapsed += step; + } + } + + std::unique_ptr _vte; + std::unique_ptr> _vision_pub; + std::unique_ptr> _uav_gps_pub; + std::unique_ptr> _target_gps_pub; + + std::unique_ptr> _aid_fiducial_sub; + std::unique_ptr> _aid_gps_mission_sub; + std::unique_ptr> _aid_gps_target_sub; + std::unique_ptr> _aid_gps_vel_uav_sub; + std::unique_ptr> _aid_gps_vel_target_sub; + std::unique_ptr> _bias_init_status_sub; + std::unique_ptr> _vte_state_sub; + std::unique_ptr> _target_pose_sub; + + vte_test::ParamGuard _param_guard{}; +}; + +// WHY: Fusion must stay off when the vision bit is not enabled in the aid mask. +// WHAT: Publish a valid vision sample with an empty aid mask and expect no estimator output. +TEST_F(VTEPositionTest, DoesNotFuseWhenVisionDisabled) +{ + // GIVEN: vision data arrives while the aid mask disables vision fusion. + publishVisionPos(matrix::Vector3f(1.f, -2.f, 3.f), vte_test::identityQuat(), + kSmallVisionCov, vte_test::advanceMicroseconds(kStepUs)); + + // WHEN: the estimator processes that sample. + _vte->update(matrix::Vector3f{}); + + // THEN: no vision aid or state output is published. + EXPECT_FALSE(_aid_fiducial_sub->update()); + EXPECT_FALSE(_vte_state_sub->update()); +} + +// WHY: Velocity-only aiding cannot initialize the position estimator. +// WHAT: Enable only velocity sources and verify fusionEnabled() stays false. +TEST_F(VTEPositionTest, FusionRequiresPositionAidSource) +{ + // GIVEN: a position estimator with no relative-position aid source selected. + enableMask({FusionMaskOption::kUavGpsVel}); + + // WHEN: we query whether the estimator has enough aiding to run. + const bool fusion_enabled = _vte->fusionEnabled(); + + // THEN: the estimator reports fusion disabled instead of starting a filter that can never initialize. + EXPECT_FALSE(fusion_enabled); +} + +// WHY: Estimator must not initialize without a velocity estimate. +// WHAT: Provide a position measurement only and expect no output. +TEST_F(VTEPositionTest, InitRequiresVelocityEstimate) +{ + // GIVEN: vision aiding is enabled but the vehicle velocity estimate is still missing. + enableMask({FusionMaskOption::kVisionPos}); + + const matrix::Vector3f rel_pos(1.f, 2.f, -3.f); + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kZeroVec, vision_time); + + // WHEN: the estimator receives the first vision position sample. + _vte->update(matrix::Vector3f{}); + + // THEN: initialization is deferred until a velocity estimate exists. + EXPECT_FALSE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); +} + +// WHY: Vision + velocity should be sufficient to start the filter. +// WHAT: Verify initial state matches the vision position and local velocity. +TEST_F(VTEPositionTest, InitWithVisionAndLocalVelocity) +{ + // GIVEN: both the required vision position and local velocity inputs are available. + enableMask({FusionMaskOption::kVisionPos}); + + const matrix::Vector3f rel_pos(4.f, -2.f, 1.f); + const matrix::Vector3f vel_ned(1.f, 2.f, 3.f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kZeroVec, vision_time); + + // WHEN: the estimator performs its first update. + _vte->update(matrix::Vector3f{}); + + // THEN: the state initializes directly from those measurements. + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + + EXPECT_NEAR(state.rel_pos[0], rel_pos(0), kTolerance); + EXPECT_NEAR(state.rel_pos[1], rel_pos(1), kTolerance); + EXPECT_NEAR(state.rel_pos[2], rel_pos(2), kTolerance); + EXPECT_TRUE(state.rel_pos_valid); + EXPECT_TRUE(state.rel_vel_valid); + EXPECT_NEAR(state.vel_uav[0], vel_ned(0), kTolerance); + EXPECT_NEAR(state.vel_uav[1], vel_ned(1), kTolerance); + EXPECT_NEAR(state.vel_uav[2], vel_ned(2), kTolerance); + + ASSERT_TRUE(_aid_fiducial_sub->update()); + const auto aid = _aid_fiducial_sub->get(); + EXPECT_NEAR(aid.observation_variance[0], kDefaultEvPosVar, kTolerance); + EXPECT_NEAR(aid.observation_variance[1], kDefaultEvPosVar, kTolerance); + EXPECT_NEAR(aid.observation_variance[2], kDefaultEvPosVar, kTolerance); +} + +// WHY: Bias averaging can be disabled when the first relative source is already trusted. +// WHAT: Disable bias averaging, provide vision and GNSS together, and check vision +// initialization remains the active path. +TEST_F(VTEPositionTest, InitialPositionUsesVisionFirstWhenBiasAveragingDisabled) +{ + // GIVEN: vision and target GNSS are enabled, but bias averaging is disabled. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kTargetGpsPos}); + + const matrix::Vector3f vel_ned(0.1f, 0.2f, 0.3f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + setParamFloat("VTE_POS_NIS_THRE", kPermissiveNisThreshold); + setParamFloat("VTE_BIA_AVG_TOUT", 0.f); + _vte->updateParamsPublic(); + + static constexpr hrt_abstime kBaseAgeUs = 10_ms; + static constexpr hrt_abstime kGpsLagUs = 4_ms; + const hrt_abstime base_time = vte_test::nowUs() - kBaseAgeUs; + const hrt_abstime vision_time = base_time; + const hrt_abstime gps_time = base_time + kGpsLagUs; + + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.5f, 0.5f, vel_ned, 0.1f, true, gps_time); + publishTargetGnss(kUavLat, kUavLon, kTargetAltM, 0.5f, 0.5f, gps_time, true); + + const matrix::Vector3f rel_pos(5.f, 6.f, 7.f); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time); + + // WHEN: both inputs are processed in the same update cycle. + _vte->update(matrix::Vector3f{}); + + // THEN: vision remains the initialization source. GNSS is fused before vision in source order, + // so the vision innovation reflects the preceding GNSS correction. + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + ASSERT_TRUE(_aid_fiducial_sub->update()); + const auto aid = _aid_fiducial_sub->get(); + EXPECT_NEAR(aid.observation[0], rel_pos(0), kTolerance); + EXPECT_NEAR(aid.observation[1], rel_pos(1), kTolerance); + EXPECT_NEAR(aid.observation[2], rel_pos(2), kTolerance); + EXPECT_GT(fabsf(aid.innovation[0]), 1.f); + EXPECT_GT(fabsf(aid.innovation[1]), 1.f); + EXPECT_GT(fabsf(aid.innovation[2]), 1.f); + const matrix::Vector3f expected_bias(-rel_pos(0), -rel_pos(1), (kUavAltM - kTargetAltM) - rel_pos(2)); + const matrix::Vector3f expected_gnss_rel(0.f, 0.f, kUavAltM - kTargetAltM); + expectBiasNear(state, expected_bias, 0.1f); + EXPECT_NEAR(state.rel_pos[0] + state.bias[0], expected_gnss_rel(0), 0.5f); + EXPECT_NEAR(state.rel_pos[1] + state.bias[1], expected_gnss_rel(1), 0.5f); + EXPECT_NEAR(state.rel_pos[2] + state.bias[2], expected_gnss_rel(2), 0.5f); + + ASSERT_TRUE(_aid_gps_target_sub->update()); + const auto aid_gps = _aid_gps_target_sub->get(); + EXPECT_EQ(aid_gps.fusion_status[0], static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); +} + +// WHY: NIS gating should reject large innovations. +// WHAT: Initialize with vision, then feed an outlier and expect REJECT_NIS. +TEST_F(VTEPositionTest, RejectsOutlierNis) +{ + vte_position_s state_before{}; + + // GIVEN: the filter is already initialized from a nominal vision measurement. + enableMask({FusionMaskOption::kVisionPos}); + setLocalVelocity(matrix::Vector3f(0.1f, 0.1f, 0.1f), vte_test::advanceMicroseconds(kStepUs)); + + publishVisionPos(matrix::Vector3f(0.f, 0.f, 0.f), vte_test::identityQuat(), + kSmallVisionCov, vte_test::advanceMicroseconds(kStepUs)); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + state_before = _vte_state_sub->get(); + vte_test::flushSubscription(_aid_fiducial_sub); + + setParamFloat("VTE_POS_NIS_THRE", kRestrictiveNisThreshold); + _vte->updateParamsPublic(); + + publishVisionPos(matrix::Vector3f(100.f, -100.f, 50.f), vte_test::identityQuat(), + kSmallVisionCov, vte_test::advanceMicroseconds(kStepUs)); + + // WHEN: a large outlier exceeds the tightened NIS threshold. + _vte->update(matrix::Vector3f{}); + + // THEN: the measurement is rejected and the state stays near the previous estimate. + ASSERT_TRUE(_aid_fiducial_sub->update()); + const auto aid = _aid_fiducial_sub->get(); + EXPECT_EQ(aid.fusion_status[0], static_cast(vte::FusionStatus::STATUS_REJECT_NIS)); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto state_after = _vte_state_sub->get(); + EXPECT_NEAR(state_after.rel_pos[0], state_before.rel_pos[0], 0.1f); + EXPECT_NEAR(state_after.rel_pos[1], state_before.rel_pos[1], 0.1f); + EXPECT_NEAR(state_after.rel_pos[2], state_before.rel_pos[2], 0.1f); +} + +struct InvalidTargetGnssCase { + const char *name; + double lat; + double lon; + float alt; + float eph{0.2f}; + float epv{0.2f}; +}; + +class VTEPositionInvalidTargetGnssTest : public VTEPositionTest, + public ::testing::WithParamInterface {}; + +// WHY: Invalid GNSS data should be rejected before fusion. +// WHAT: Feed out-of-range, sentinel, and altitude-invalid measurements and +// expect no aid update. +TEST_P(VTEPositionInvalidTargetGnssTest, RejectsInvalidTargetGnssSample) +{ + // GIVEN: target GNSS position fusion is enabled and the estimator has vehicle velocity. + enableMask({FusionMaskOption::kTargetGpsPos}); + + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(matrix::Vector3f(0.1f, 0.1f, 0.1f), vel_time); + + const matrix::Vector3f vel_ned(0.1f, 0.1f, 0.1f); + const auto ¶m = GetParam(); + + // WHEN: the estimator receives an invalid target GNSS sample. + const hrt_abstime uav_time = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, uav_time); + const hrt_abstime target_time = vte_test::advanceMicroseconds(kStepUs); + publishTargetGnss(param.lat, param.lon, param.alt, param.eph, param.epv, target_time, true); + _vte->update(matrix::Vector3f{}); + + // THEN: the invalid sample does not produce a target-GNSS aid update or initialize the filter. + EXPECT_FALSE(_aid_gps_target_sub->update()); + EXPECT_FALSE(_vte_state_sub->update()); +} + +static InvalidTargetGnssCase makeInvalidTargetLatCase() +{ + InvalidTargetGnssCase c{}; + c.name = "LatitudeOutOfRange"; + c.lat = VTEPositionTestable::kLatAbsMaxDeg + 1.0; + c.lon = kUavLon; + c.alt = kTargetAltM; + return c; +} + +static InvalidTargetGnssCase makeInvalidTargetLonCase() +{ + InvalidTargetGnssCase c{}; + c.name = "LongitudeOutOfRange"; + c.lat = kUavLat; + c.lon = VTEPositionTestable::kLonAbsMaxDeg + 1.0; + c.alt = kTargetAltM; + return c; +} + +static InvalidTargetGnssCase makeSentinelTargetLatLonCase() +{ + InvalidTargetGnssCase c{}; + c.name = "ZeroZeroSentinel"; + c.lat = 0.0; + c.lon = 0.0; + c.alt = kTargetAltM; + return c; +} + +static InvalidTargetGnssCase makeInvalidTargetAltCase() +{ + InvalidTargetGnssCase c{}; + c.name = "AltitudeOutOfRange"; + c.lat = kUavLat; + c.lon = kUavLon; + c.alt = VTEPositionTestable::kAltMaxM + 1.f; + return c; +} + +static InvalidTargetGnssCase makeInvalidTargetHorizontalAccuracyCase() +{ + InvalidTargetGnssCase c{}; + c.name = "HorizontalAccuracyInfinite"; + c.lat = kUavLat; + c.lon = kUavLon; + c.alt = kTargetAltM; + c.eph = INFINITY; + return c; +} + +static InvalidTargetGnssCase makeInvalidTargetVerticalAccuracyCase() +{ + InvalidTargetGnssCase c{}; + c.name = "VerticalAccuracyInfinite"; + c.lat = kUavLat; + c.lon = kUavLon; + c.alt = kTargetAltM; + c.epv = INFINITY; + return c; +} + +INSTANTIATE_TEST_SUITE_P( + InvalidInputs, + VTEPositionInvalidTargetGnssTest, + ::testing::Values( + makeInvalidTargetLatCase(), + makeInvalidTargetLonCase(), + makeSentinelTargetLatLonCase(), + makeInvalidTargetAltCase(), + makeInvalidTargetHorizontalAccuracyCase(), + makeInvalidTargetVerticalAccuracyCase()), +[](const ::testing::TestParamInfo ¶m_info) { return param_info.param.name; }); + +// WHY: Position fusions follow source order; delayed samples still go through OOSM individually. +// WHAT: Apply non-zero vision then GNSS updates and verify source ordering in the innovations. +TEST_F(VTEPositionTest, FusesMeasurementsInSourceOrder) +{ + // GIVEN: mission and vision position aiding use matching process noise and no bias initialization delay. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + static constexpr float kPosNoise = 1.f; + static constexpr float kPosVar = kPosNoise * kPosNoise; + setParamFloat("VTE_EVP_NOISE", kPosNoise); + setParamFloat("VTE_GPS_P_NOISE", kPosNoise); + setParamFloat("VTE_BIA_UNC_IN", 0.f); + setParamFloat("VTE_BIA_AVG_TOUT", 0.f); + setParamFloat("VTE_POS_NIS_THRE", kPermissiveNisThreshold); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(0.f, 0.f, 0.f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + static constexpr double kTargetNorthMeters = 20.0; + + const hrt_abstime init_time = vte_test::advanceMicroseconds(kStepUs); + _vte->setMissionPosition(kUavLat, kUavLon, kUavAltM); + publishUavGps(kUavLat, kUavLon, kUavAltM, kPosNoise, kPosNoise, vel_ned, 0.1f, true, init_time); + publishVisionPos(matrix::Vector3f{}, vte_test::identityQuat(), + matrix::Vector3f(kPosVar, kPosVar, kPosVar), init_time); + + // WHEN: the filter is initialized with aligned mission and vision samples. + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + vte_test::flushSubscription(_aid_fiducial_sub); + vte_test::flushSubscription(_aid_gps_mission_sub); + vte_test::flushSubscription(_vte_state_sub); + + static constexpr hrt_abstime kBaseAgeUs = 10_ms; + static constexpr hrt_abstime kGpsLagUs = 5_ms; + const hrt_abstime base_time = vte_test::nowUs() - kBaseAgeUs; + const hrt_abstime vision_time = base_time; + const hrt_abstime gps_time = base_time + kGpsLagUs; + + const double mission_lat = kUavLat + (kTargetNorthMeters / kMetersPerDegLat); + _vte->setMissionPosition(mission_lat, kUavLon, kUavAltM); + + publishUavGps(kUavLat, kUavLon, kUavAltM, kPosNoise, kPosNoise, vel_ned, 0.1f, true, gps_time); + + const matrix::Vector3f rel_pos(10.f, 0.f, 0.f); + publishVisionPos(rel_pos, vte_test::identityQuat(), + matrix::Vector3f(kPosVar, kPosVar, kPosVar), vision_time); + + // WHEN: an older vision sample and a newer GNSS sample arrive together. + _vte->update(matrix::Vector3f{}); + + // THEN: each delayed same-cycle measurement replays from the previous history snapshot. + // Without per-cycle serialization, the older vision OOSM does not use the newer + // GNSS correction as its replay floor until the post-cycle history sample is pushed. + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_aid_gps_mission_sub->update()); + + const auto aid_vision = _aid_fiducial_sub->get(); + const auto aid_gps = _aid_gps_mission_sub->get(); + + EXPECT_GT(fabsf(aid_vision.innovation[0]), 1.f); + EXPECT_NEAR(aid_vision.observation[0], rel_pos(0), 0.1f); + EXPECT_NEAR(aid_gps.observation[0], kTargetNorthMeters, 0.6f); + + const float pred_state_gps = aid_gps.observation[0] - aid_gps.innovation[0]; + const float pred_state_vision = aid_vision.observation[0] - aid_vision.innovation[0]; + + EXPECT_NEAR(pred_state_gps, 0.f, 0.5f); + EXPECT_NEAR(pred_state_vision, 0.f, 0.5f); +} + +// WHY: A zero averaging timeout should immediately activate the bias. +// WHAT: Initialize from GNSS, then provide the first vision sample with averaging disabled and verify that +// the same update sets the bias and fuses vision. +TEST_F(VTEPositionTest, BiasAveragingTimeoutZeroActivatesBiasImmediately) +{ + // GIVEN: mission GNSS initializes the filter and bias averaging is disabled. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + setParamFloat("VTE_BIA_AVG_TOUT", 0.f); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(0.5f, -0.5f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + initializeFromMissionGnss(vel_ned); + flushVisionAndMissionOutputs(); + + const matrix::Vector3f rel_pos(1.f, 2.f, 3.f); + const hrt_abstime gps_time = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_time); + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time); + + // WHEN: the first post-init vision sample arrives alongside fresh GNSS. + _vte->update(matrix::Vector3f{}); + + // THEN: that same update activates the bias and fuses the vision measurement. + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_bias_init_status_sub->update()); + + const auto state = _vte_state_sub->get(); + + EXPECT_LT(state.bias[0], -0.5f); + EXPECT_LT(state.bias[1], -1.0f); + EXPECT_GT(state.bias[2], 5.0f); +} + +// WHY: The first vision sample after GNSS can be noisy and should not set the GNSS bias immediately. +// WHAT: Initialize from GNSS, provide one vision sample to start averaging, +// then require the raw bias to stay close to the LPF for a minimum averaging time before activating the bias. +TEST_F(VTEPositionTest, BiasAveragingDelaysVisionFusionUntilStable) +{ + // GIVEN: mission GNSS initializes first and bias averaging requires the raw bias to settle around the LPF. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + setParamFloat("VTE_BIA_AVG_THR", 0.05f); + setParamFloat("VTE_BIA_AVG_TOUT", 2.0f); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(0.5f, -0.5f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + initializeFromMissionGnss(vel_ned); + flushVisionAndMissionOutputs(); + + const matrix::Vector3f rel_pos(1.f, 2.f, 3.f); + const hrt_abstime gps_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_time_1); + const hrt_abstime vision_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time_1); + + // WHEN: the first vision sample starts bias averaging. + _vte->update(matrix::Vector3f{}); + + // THEN: the raw bias is tracked, but the active state keeps the pre-bias GNSS-relative position. + ASSERT_TRUE(_vte_state_sub->update()); + ASSERT_TRUE(_bias_init_status_sub->update()); + const auto initial_bias_status = _bias_init_status_sub->get(); + const auto pending_state = _vte_state_sub->get(); + EXPECT_FALSE(_aid_fiducial_sub->update()); + const float altitude_bias = (kUavAltM - kTargetAltM) - rel_pos(2); + const matrix::Vector3f expected_bias(-rel_pos(0), -rel_pos(1), altitude_bias); + EXPECT_NEAR(initial_bias_status.raw_bias[0], expected_bias(0), kTolerance); + EXPECT_NEAR(initial_bias_status.raw_bias[1], expected_bias(1), kTolerance); + EXPECT_NEAR(initial_bias_status.raw_bias[2], expected_bias(2), kTolerance); + EXPECT_NEAR(initial_bias_status.filtered_bias[0], expected_bias(0), kTolerance); + EXPECT_NEAR(initial_bias_status.filtered_bias[1], expected_bias(1), kTolerance); + EXPECT_NEAR(initial_bias_status.filtered_bias[2], expected_bias(2), kTolerance); + EXPECT_NEAR(initial_bias_status.delta_norm, 0.f, kTolerance); + expectBiasNear(pending_state, kZeroVec, kTolerance); + EXPECT_NEAR(pending_state.rel_pos[0], 0.f, 0.1f); + EXPECT_NEAR(pending_state.rel_pos[1], 0.f, 0.1f); + EXPECT_NEAR(pending_state.rel_pos[2], kUavAltM - kTargetAltM, 0.1f); + + // Each of the advance blocks below drives 200 ms of keep-alive GPS without refreshing + // local velocity. This exercises the min-time / stable-delta parts of the averaging path. + static constexpr hrt_abstime kAdvanceStepUs = 4 * kKeepAliveStepUs; + + advanceEstimatorWithGps(kAdvanceStepUs, vel_ned); + const hrt_abstime vision_time_2 = vte_test::nowUs(); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time_2); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto still_pending_state = _vte_state_sub->get(); + EXPECT_FALSE(_aid_fiducial_sub->update()); + expectBiasNear(still_pending_state, kZeroVec, kTolerance); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimatorWithGps(kAdvanceStepUs, vel_ned); + const hrt_abstime vision_time_3 = vte_test::nowUs(); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time_3); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto min_time_not_reached_state = _vte_state_sub->get(); + EXPECT_FALSE(_aid_fiducial_sub->update()); + expectBiasNear(min_time_not_reached_state, kZeroVec, kTolerance); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimatorWithGps(kAdvanceStepUs, vel_ned); + const hrt_abstime vision_time_4 = vte_test::nowUs(); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time_4); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto still_waiting_for_lpf_settle_state = _vte_state_sub->get(); + EXPECT_FALSE(_aid_fiducial_sub->update()); + expectBiasNear(still_waiting_for_lpf_settle_state, kZeroVec, kTolerance); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimatorWithGps(kAdvanceStepUs, vel_ned); + const hrt_abstime vision_time_5 = vte_test::nowUs(); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time_5); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto still_waiting_for_final_lpf_delta_state = _vte_state_sub->get(); + EXPECT_FALSE(_aid_fiducial_sub->update()); + expectBiasNear(still_waiting_for_final_lpf_delta_state, kZeroVec, kTolerance); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimatorWithGps(kAdvanceStepUs, vel_ned); + const hrt_abstime vision_time_6 = vte_test::nowUs(); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time_6); + + // WHEN: the minimum time and raw-to-LPF delta requirements are finally both satisfied. + _vte->update(matrix::Vector3f{}); + + // THEN: bias averaging completes and vision starts fusing with the initialized bias. + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + expectBiasNear(state, expected_bias, 0.1f); + EXPECT_NEAR(state.cov_bias[0], kDefaultBiasUnc, kTolerance); + EXPECT_NEAR(state.cov_bias[1], kDefaultBiasUnc, kTolerance); + EXPECT_NEAR(state.cov_bias[2], kDefaultBiasUnc, kTolerance); +} + +// WHY: Bias averaging should stay pending until the raw bias stays close to the LPF for long enough. +// WHAT: Feed changing vision samples and verify averaging remains active until the raw-to-LPF delta +// and minimum-time conditions are both satisfied. +TEST_F(VTEPositionTest, BiasAveragingWaitsForRawToLpfDeltaAndMinTime) +{ + // GIVEN: mission GNSS initializes first and bias averaging needs time to settle. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + setParamFloat("VTE_BIA_AVG_THR", 0.05f); + setParamFloat("VTE_BIA_AVG_TOUT", 1.0f); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(0.5f, -0.5f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + initializeFromMissionGnss(vel_ned); + flushVisionAndMissionOutputs(); + + const matrix::Vector3f rel_pos_first(1.00f, 2.f, 3.f); + const matrix::Vector3f rel_pos_second(1.04f, 2.f, 3.f); + const matrix::Vector3f rel_pos_third(0.96f, 2.f, 3.f); + + const hrt_abstime gps_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_time_1); + const hrt_abstime vision_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos_first, vte_test::identityQuat(), kSmallVisionCov, vision_time_1); + + // WHEN: the first vision sample starts averaging. + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + // Tick GPS and local velocity forward so the bias-averaging LPF keeps running between + // the staggered vision samples below. + auto advanceEstimator = [&](hrt_abstime duration_us) { + advanceEstimatorWithGps(duration_us, vel_ned, /*refresh_local_velocity=*/true); + }; + + advanceEstimator(300_ms); + const hrt_abstime vision_time_2 = vte_test::nowUs(); + publishVisionPos(rel_pos_second, vte_test::identityQuat(), kSmallVisionCov, vision_time_2); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimator(310_ms); + const hrt_abstime vision_time_3 = vte_test::nowUs(); + publishVisionPos(rel_pos_third, vte_test::identityQuat(), kSmallVisionCov, vision_time_3); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto still_averaging_state = _vte_state_sub->get(); + EXPECT_FALSE(_aid_fiducial_sub->update()); + expectBiasNear(still_averaging_state, kZeroVec, kTolerance); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimator(50_ms); + const hrt_abstime vision_time_4 = vte_test::nowUs(); + publishVisionPos(rel_pos_third, vte_test::identityQuat(), kSmallVisionCov, vision_time_4); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimator(50_ms); + const hrt_abstime vision_time_5 = vte_test::nowUs(); + publishVisionPos(rel_pos_third, vte_test::identityQuat(), kSmallVisionCov, vision_time_5); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimator(50_ms); + const hrt_abstime vision_time_6 = vte_test::nowUs(); + publishVisionPos(rel_pos_third, vte_test::identityQuat(), kSmallVisionCov, vision_time_6); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimator(50_ms); + const hrt_abstime vision_time_7 = vte_test::nowUs(); + publishVisionPos(rel_pos_third, vte_test::identityQuat(), kSmallVisionCov, vision_time_7); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + advanceEstimator(50_ms); + const hrt_abstime vision_time_8 = vte_test::nowUs(); + publishVisionPos(rel_pos_third, vte_test::identityQuat(), kSmallVisionCov, vision_time_8); + + // WHEN: the raw bias has stayed close to the LPF long enough to satisfy the timeout. + _vte->update(matrix::Vector3f{}); + + // THEN: the bias activates once the raw-to-LPF delta and minimum-time conditions are both satisfied. + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + const float altitude_bias = (kUavAltM - kTargetAltM) - rel_pos_third(2); + const matrix::Vector3f expected_bias(-rel_pos_third(0), -rel_pos_third(1), altitude_bias); + expectBiasNear(state, expected_bias, 0.1f); +} + +// WHY: When the vision timestamp is newer than a still-valid GNSS-relative sample, the bias logic should +// propagate that GNSS measurement with the UAV velocity estimate before comparing it to vision. +// WHAT: Keep the second vision sample inside the GNSS validity window, force a timeout exit, and verify +// the resulting bias matches the velocity-compensated GNSS/vision difference. +TEST_F(VTEPositionTest, BiasAveragingPropagatesValidGnssUsingVelocity) +{ + // GIVEN: mission GNSS initializes the filter and bias averaging waits long enough to compare a propagated GNSS sample. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + setParamFloat("VTE_BIA_AVG_THR", 0.05f); + setParamFloat("VTE_BIA_AVG_TOUT", 0.06f); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(5.0f, -3.0f, 1.5f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + initializeFromMissionGnss(vel_ned); + flushVisionAndMissionOutputs(); + + const matrix::Vector3f initial_gnss_rel(0.f, 0.f, kUavAltM - kTargetAltM); + const matrix::Vector3f expected_bias(0.6f, -0.4f, 1.2f); + + const hrt_abstime vision_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(initial_gnss_rel - expected_bias, vte_test::identityQuat(), kSmallVisionCov, vision_time_1); + + // WHEN: the first vision sample begins bias averaging. + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + const hrt_abstime vision_time_2 = vte_test::advanceMicroseconds(60_ms); + setLocalVelocity(vel_ned, vision_time_2); + const matrix::Vector3f propagated_gnss = initial_gnss_rel - vel_ned * 0.06f; + publishVisionPos(propagated_gnss - expected_bias, vte_test::identityQuat(), kSmallVisionCov, vision_time_2); + + // WHEN: the next vision sample arrives while the earlier GNSS-relative sample is still valid. + _vte->update(matrix::Vector3f{}); + + // THEN: the bias is computed from the velocity-propagated GNSS sample rather than the stale raw position. + ASSERT_TRUE(_bias_init_status_sub->update()); + const auto propagated_bias_status = _bias_init_status_sub->get(); + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + EXPECT_NEAR(propagated_bias_status.raw_bias[0], expected_bias(0), 0.05f); + EXPECT_NEAR(propagated_bias_status.raw_bias[1], expected_bias(1), 0.05f); + EXPECT_NEAR(propagated_bias_status.raw_bias[2], expected_bias(2), 0.05f); + EXPECT_LT(propagated_bias_status.delta_norm, 0.05f); + expectBiasNear(state, expected_bias, 0.05f); +} + +// WHY: The vision sample can be older than the latest GNSS sample. +// WHAT: Publish a newer mission/GNSS relative position from a moved UAV and verify the bias setup +// back-propagates that GNSS sample before initializing the bias, even if the state then advances +// to the newer GNSS observation in the same update. +TEST_F(VTEPositionTest, BiasInitializationBackPropagatesNewerGnssSampleToOlderVision) +{ + // GIVEN: vision is timestamped earlier than the GNSS-relative mission sample. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + setParamFloat("VTE_BIA_AVG_TOUT", 0.f); + setParamFloat("VTE_POS_NIS_THRE", kPermissiveNisThreshold); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(5.f, -3.f, 0.f); + _vte->setMissionPosition(kUavLat, kUavLon, kUavAltM); + + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + const hrt_abstime gps_time = vte_test::advanceMicroseconds(50_ms); + + double moved_lat = kUavLat; + double moved_lon = kUavLon; + add_vector_to_global_position(kUavLat, kUavLon, vel_ned(0) * 0.05f, vel_ned(1) * 0.05f, &moved_lat, &moved_lon); + + setLocalVelocity(vel_ned, gps_time); + publishUavGps(moved_lat, moved_lon, kUavAltM, 0.2f, 0.2f, vel_ned, 0.1f, true, gps_time); + publishVisionPos(kZeroVec, vte_test::identityQuat(), kSmallVisionCov, vision_time); + + // WHEN: both samples are processed together. + _vte->update(matrix::Vector3f{}); + + // THEN: bias initialization back-propagates GNSS to the older vision time, leaving zero bias here. + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + + expectBiasNear(state, kZeroVec, 0.1f); +} + +// WHY: Bias averaging must not wait forever when GNSS/vision agreement stays poor. +// WHAT: Force a tiny timeout with inconsistent vision samples and expect the LPF bias to activate once the timeout expires. +TEST_F(VTEPositionTest, BiasAveragingUsesTimeoutWhenSamplesDoNotStabilize) +{ + // GIVEN: mission GNSS initializes first, but the incoming vision samples never stabilize. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + setParamFloat("VTE_BIA_AVG_THR", 0.001f); + setParamFloat("VTE_BIA_AVG_TOUT", 0.002f); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(0.5f, -0.5f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + initializeFromMissionGnss(vel_ned); + flushVisionAndMissionOutputs(); + + const matrix::Vector3f rel_pos_first(1.f, 0.f, 3.f); + const hrt_abstime gps_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_time_1); + const hrt_abstime vision_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos_first, vte_test::identityQuat(), kSmallVisionCov, vision_time_1); + + // WHEN: the first vision sample starts averaging. + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_vte_state_sub); + + vte_test::advanceMicroseconds(3_ms); + setParamFloat("VTE_POS_NIS_THRE", kRestrictiveNisThreshold); + _vte->updateParamsPublic(); + + const matrix::Vector3f rel_pos_second(4.f, -2.f, 6.f); + const hrt_abstime gps_time_2 = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_time_2); + const hrt_abstime vision_time_2 = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos_second, vte_test::identityQuat(), kSmallVisionCov, vision_time_2); + + // WHEN: the timeout has expired before the next inconsistent sample arrives. + _vte->update(matrix::Vector3f{}); + + // THEN: the filtered bias activates instead of waiting for stability that never comes. + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + const float altitude_bias_first = (kUavAltM - kTargetAltM) - rel_pos_first(2); + const matrix::Vector3f expected_bias_first(-rel_pos_first(0), -rel_pos_first(1), altitude_bias_first); + const matrix::Vector3f expected_gnss_rel(0.f, 0.f, kUavAltM - kTargetAltM); + + expectBiasNear(state, expected_bias_first, 0.3f); + EXPECT_NEAR(state.rel_pos[0] + state.bias[0], expected_gnss_rel(0), 0.3f); + EXPECT_NEAR(state.rel_pos[1] + state.bias[1], expected_gnss_rel(1), 0.3f); + EXPECT_NEAR(state.rel_pos[2] + state.bias[2], expected_gnss_rel(2), 0.3f); + EXPECT_NEAR(state.rel_pos[0], rel_pos_first(0), 0.3f); + EXPECT_NEAR(state.rel_pos[1], rel_pos_first(1), 0.3f); + EXPECT_NEAR(state.rel_pos[2], rel_pos_first(2), 0.3f); +} + +// WHY: If the GNSS-relative sample expires during bias averaging, vision fusion should resume immediately. +// WHAT: Start averaging from GNSS, let the GNSS-relative sample go stale without refreshing it, +// then verify the estimator switches to the current vision position and fuses that sample. +TEST_F(VTEPositionTest, BiasAveragingFallsBackToVisionWhenGnssBecomesStale) +{ + // GIVEN: mission GNSS initializes first and bias averaging is in progress. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + setParamFloat("VTE_BIA_AVG_THR", 0.05f); + setParamFloat("VTE_BIA_AVG_TOUT", 1.0f); + _vte->updateParamsPublic(); + + // Shorten the recent-measurement timeout so the 150 ms gap below unambiguously + // invalidates _pos_rel_gnss + _vte->setMeasRecentTimeout(100_ms); + + const matrix::Vector3f vel_ned(0.4f, -0.3f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + initializeFromMissionGnss(vel_ned); + flushVisionAndMissionOutputs(); + + const matrix::Vector3f rel_pos(3.f, -2.f, 4.f); + const hrt_abstime gps_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_time_1); + const hrt_abstime vision_time_1 = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time_1); + + // WHEN: the first vision sample starts bias averaging. + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + for (int i = 0; i < 3; ++i) { + const hrt_abstime now = vte_test::advanceMicroseconds(50_ms); + setLocalVelocity(vel_ned, now); + _vte->update(matrix::Vector3f{}); + vte_test::flushSubscription(_vte_state_sub); + } + + const hrt_abstime stale_vision_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, stale_vision_time); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, stale_vision_time); + + // WHEN: vision returns after the GNSS-relative sample has gone stale. + _vte->update(matrix::Vector3f{}); + + // THEN: the estimator falls back to fusing the current vision measurement immediately. + ASSERT_TRUE(_aid_fiducial_sub->update()); + const auto aid = _aid_fiducial_sub->get(); + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + const float altitude_bias = (kUavAltM - kTargetAltM) - rel_pos(2); + const matrix::Vector3f expected_bias(-rel_pos(0), -rel_pos(1), altitude_bias); + + EXPECT_EQ(aid.fusion_status[0], static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); + EXPECT_EQ(aid.fusion_status[1], static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); + EXPECT_EQ(aid.fusion_status[2], static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); + EXPECT_NEAR(state.rel_pos[0], rel_pos(0), 0.1f); + EXPECT_NEAR(state.rel_pos[1], rel_pos(1), 0.1f); + EXPECT_NEAR(state.rel_pos[2], rel_pos(2), 0.1f); + expectBiasNear(state, expected_bias, 0.1f); +} + +// WHY: Once vision has already been fused, the estimator can use it directly to initialize GNSS bias. +// WHAT: Initialize from vision, let vision disappear for one cycle, then introduce GNSS and verify bias is set +// on the first sample where GNSS and vision are both available again. +TEST_F(VTEPositionTest, BiasSetImmediatelyWhenGnssArrivesAfterVisionTrusted) +{ + // GIVEN: the estimator starts from a trusted vision-only initialization. + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + setParamFloat("VTE_POS_NIS_THRE", kPermissiveNisThreshold); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(0.5f, -0.5f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + const matrix::Vector3f rel_pos(1.f, 2.f, 3.f); + const hrt_abstime vision_init_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_init_time); + + // WHEN: vision initializes the filter on its own. + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + flushVisionAndMissionOutputs(); + + const hrt_abstime gps_only_time = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_only_time); + _vte->setMissionPosition(kUavLat, kUavLon, kTargetAltM); + + // WHEN: GNSS arrives for one cycle without a matching vision update. + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto gps_only_state = _vte_state_sub->get(); + EXPECT_FALSE(_aid_fiducial_sub->update()); + EXPECT_FALSE(_aid_gps_mission_sub->update()); + EXPECT_FALSE(_bias_init_status_sub->update()); + EXPECT_NEAR(gps_only_state.rel_pos[0], rel_pos(0), 0.1f); + EXPECT_NEAR(gps_only_state.rel_pos[1], rel_pos(1), 0.1f); + EXPECT_NEAR(gps_only_state.rel_pos[2], rel_pos(2), 0.1f); + expectBiasNear(gps_only_state, kZeroVec, kTolerance); + vte_test::flushSubscription(_aid_gps_mission_sub); + vte_test::flushSubscription(_vte_state_sub); + + const hrt_abstime gps_time = vte_test::advanceMicroseconds(kStepUs); + publishNominalUavGps(vel_ned, gps_time); + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, vision_time); + + // WHEN: GNSS and vision are both available again. + _vte->update(matrix::Vector3f{}); + + // THEN: the bias is set immediately without re-entering the averaging path. + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_aid_gps_mission_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_bias_init_status_sub->update()); + const auto state = _vte_state_sub->get(); + const float altitude_bias = (kUavAltM - kTargetAltM) - rel_pos(2); + const matrix::Vector3f expected_bias(-rel_pos(0), -rel_pos(1), altitude_bias); + expectBiasNear(state, expected_bias, 0.1f); +} + +// WHY: Once the GNSS/vision bias has been set, temporary vision loss must not restart bias initialization. +// WHAT: Initialize the bias immediately, fuse GNSS alone for one cycle, then restore vision and verify +// that the same bias stays active without re-entering the initialization path. +TEST_F(VTEPositionTest, VisionReturnAfterTemporaryLossDoesNotReinitializeBias) +{ + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kMissionPos}); + + setParamFloat("VTE_BIA_AVG_TOUT", 0.f); + setParamFloat("VTE_POS_NIS_THRE", kPermissiveNisThreshold); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(0.5f, -0.5f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + const matrix::Vector3f rel_pos(1.f, 2.f, 3.f); + _vte->setMissionPosition(kUavLat, kUavLon, kTargetAltM); + + const hrt_abstime init_gps_time = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.2f, 0.2f, vel_ned, 0.1f, true, init_gps_time); + const hrt_abstime init_vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, init_vision_time); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_aid_gps_mission_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_bias_init_status_sub->update()); + const auto initial_state = _vte_state_sub->get(); + const float altitude_bias = (kUavAltM - kTargetAltM) - rel_pos(2); + const matrix::Vector3f expected_bias(-rel_pos(0), -rel_pos(1), altitude_bias); + expectBiasNear(initial_state, expected_bias, 0.1f); + + vte_test::flushSubscription(_aid_fiducial_sub); + vte_test::flushSubscription(_aid_gps_mission_sub); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + const hrt_abstime gnss_only_time = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.2f, 0.2f, vel_ned, 0.1f, true, gnss_only_time); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_mission_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_aid_fiducial_sub->update()); + EXPECT_FALSE(_bias_init_status_sub->update()); + const auto gnss_only_state = _vte_state_sub->get(); + EXPECT_GT(fabsf(gnss_only_state.bias[0]), 0.5f); + EXPECT_GT(fabsf(gnss_only_state.bias[1]), 1.0f); + EXPECT_GT(fabsf(gnss_only_state.bias[2]), 0.5f); + + vte_test::flushSubscription(_aid_fiducial_sub); + vte_test::flushSubscription(_aid_gps_mission_sub); + vte_test::flushSubscription(_bias_init_status_sub); + vte_test::flushSubscription(_vte_state_sub); + + const hrt_abstime return_gps_time = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.2f, 0.2f, vel_ned, 0.1f, true, return_gps_time); + const hrt_abstime return_vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, vte_test::identityQuat(), kSmallVisionCov, return_vision_time); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_fiducial_sub->update()); + ASSERT_TRUE(_aid_gps_mission_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_FALSE(_bias_init_status_sub->update()); + const auto state = _vte_state_sub->get(); + EXPECT_NEAR(state.bias[0], gnss_only_state.bias[0], 0.5f); + EXPECT_NEAR(state.bias[1], gnss_only_state.bias[1], 0.5f); + EXPECT_NEAR(state.bias[2], gnss_only_state.bias[2], 0.5f); +} + +// WHY: Vision measurements must be rotated to NED and respect noise floors. +// WHAT: Rotate a vector by 180deg yaw and check floor in the innovation message. +TEST_F(VTEPositionTest, VisionNoiseFloorAndRotation) +{ + enableMask({FusionMaskOption::kVisionPos}); + + const matrix::Vector3f vel_ned(0.1f, 0.1f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + const matrix::Quaternionf q{0.f, 0.f, 0.f, 1.f}; + + const matrix::Vector3f rel_pos(1.f, 2.f, 3.f); + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(rel_pos, q, kZeroVec, vision_time); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_fiducial_sub->update()); + const auto aid = _aid_fiducial_sub->get(); + + const matrix::Vector3f expected_obs = q.rotateVector(rel_pos); + EXPECT_NEAR(aid.observation[0], expected_obs(0), kTolerance); + EXPECT_NEAR(aid.observation[1], expected_obs(1), kTolerance); + EXPECT_NEAR(aid.observation[2], expected_obs(2), kTolerance); + EXPECT_NEAR(aid.observation_variance[0], kDefaultEvPosVar, kTolerance); + EXPECT_NEAR(aid.observation_variance[1], kDefaultEvPosVar, kTolerance); + EXPECT_NEAR(aid.observation_variance[2], kDefaultEvPosVar, kTolerance); +} + +// WHY: Any non-finite field on a vision report (covariance, quaternion, or position) must +// cause the sample to be dropped before fusion. +// WHAT: Parameterize the invalid-input case so each invariant is exercised from a single +// fixture without duplicates. +struct InvalidVisionCase { + const char *name; + matrix::Vector3f rel_pos{1.f, 2.f, 3.f}; + matrix::Quaternionf quat{vte_test::identityQuat()}; + matrix::Vector3f cov{kSmallVisionCov}; +}; + +class VTEPositionInvalidVisionTest : public VTEPositionTest, + public ::testing::WithParamInterface {}; + +TEST_P(VTEPositionInvalidVisionTest, RejectsNonFiniteVisionSample) +{ + // GIVEN: vision fusion enabled and the velocity estimate is fresh. + enableMask({FusionMaskOption::kVisionPos}); + + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(matrix::Vector3f(0.1f, 0.1f, 0.1f), vel_time); + + // WHEN: a vision report arrives with one non-finite field. + const auto ¶m = GetParam(); + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(param.rel_pos, param.quat, param.cov, vision_time); + _vte->update(matrix::Vector3f{}); + + // THEN: no aid or state output is published. + EXPECT_FALSE(_aid_fiducial_sub->update()); + EXPECT_FALSE(_vte_state_sub->update()); +} + +static InvalidVisionCase makeInvalidCovCase() +{ + InvalidVisionCase c{}; + c.name = "NanCovariance"; + c.cov = matrix::Vector3f(NAN, NAN, NAN); + return c; +} + +static InvalidVisionCase makeInvalidQuatCase() +{ + InvalidVisionCase c{}; + c.name = "NanQuaternion"; + c.quat(0) = NAN; + return c; +} + +static InvalidVisionCase makeInvalidPosCase() +{ + InvalidVisionCase c{}; + c.name = "NanPosition"; + c.rel_pos(1) = NAN; + return c; +} + +INSTANTIATE_TEST_SUITE_P( + AllInvalidFields, + VTEPositionInvalidVisionTest, + ::testing::Values(makeInvalidCovCase(), makeInvalidQuatCase(), makeInvalidPosCase()), +[](const ::testing::TestParamInfo ¶m_info) { return param_info.param.name; }); + +// WHY: Mission position is a cached input, not a transient fusion decision. +// WHAT: Store the mission waypoint before enabling the mission aid bit and verify +// the first mission-aided update still uses that cached value. +TEST_F(VTEPositionTest, MissionPositionCanBeCachedBeforeAidEnabled) +{ + const matrix::Vector3f vel_ned(0.1f, 0.1f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + _vte->setMissionPosition(kUavLat, kUavLon, kTargetAltM); + enableMask({FusionMaskOption::kMissionPos}); + + const hrt_abstime gps_time = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.01f, 0.01f, vel_ned, 0.1f, true, gps_time); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_mission_sub->update()); + EXPECT_EQ(_aid_gps_mission_sub->get().fusion_status[0], static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + EXPECT_TRUE(state.rel_pos_valid); + EXPECT_NEAR(state.rel_pos[0], 0.f, kTolerance); + EXPECT_NEAR(state.rel_pos[1], 0.f, kTolerance); + EXPECT_NEAR(state.rel_pos[2], kUavAltM - kTargetAltM, kTolerance); +} + +// WHY: Mission GNSS measurements must apply offset and variance floors. +// WHAT: Publish GPS without offset, then apply an offset and verify +// observation changes. +TEST_F(VTEPositionTest, MissionGpsRelativePositionAndOffset) +{ + enableMask({FusionMaskOption::kMissionPos}); + + const matrix::Vector3f vel_ned(0.1f, 0.1f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + const hrt_abstime t0 = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.01f, 0.01f, vel_ned, 0.1f, true, t0); + _vte->setMissionPosition(kUavLat, kUavLon, kTargetAltM); + + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_mission_sub->update()); + const auto aid_no_offset = _aid_gps_mission_sub->get(); + + const matrix::Vector3f gps_offset(1.f, 2.f, 3.f); + _vte->setGpsPosOffset(gps_offset, true); + const hrt_abstime t1 = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.01f, 0.01f, vel_ned, 0.1f, true, t1); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_mission_sub->update()); + const auto aid_offset = _aid_gps_mission_sub->get(); + + EXPECT_NEAR(aid_offset.observation[0], aid_no_offset.observation[0] + gps_offset(0), kTolerance); + EXPECT_NEAR(aid_offset.observation[1], aid_no_offset.observation[1] + gps_offset(1), kTolerance); + EXPECT_NEAR(aid_offset.observation[2], aid_no_offset.observation[2] + gps_offset(2), kTolerance); + EXPECT_NEAR(aid_offset.observation_variance[0], kDefaultGpsPosVar, kTolerance); + EXPECT_NEAR(aid_offset.observation_variance[1], kDefaultGpsPosVar, kTolerance); + EXPECT_NEAR(aid_offset.observation_variance[2], kDefaultGpsPosVar, kTolerance); +} + +// WHY: A stale-gap reset should not drop the cached mission landing point. +// WHAT: Reinitialize after a stale prediction gap and verify mission aiding still works without calling setMissionPosition() again. +TEST_F(VTEPositionTest, MissionPositionSurvivesStaleGapReset) +{ + // GIVEN: a mission-position-only setup that has already initialized once. + enableMask({FusionMaskOption::kMissionPos}); + + const matrix::Vector3f vel_ned(0.1f, 0.1f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + _vte->setMissionPosition(kUavLat, kUavLon, kTargetAltM); + + const hrt_abstime t0 = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.01f, 0.01f, vel_ned, 0.1f, true, t0); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_mission_sub->update()); + ASSERT_TRUE(_vte_state_sub->update()); + vte_test::flushSubscription(_aid_gps_mission_sub); + vte_test::flushSubscription(_vte_state_sub); + + // WHEN: the estimator hits a stale-gap reset and then receives fresh mission/UAV GPS data. + vte_test::advanceMicroseconds(150_ms); + _vte->update(matrix::Vector3f{}); + + const hrt_abstime t1 = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.01f, 0.01f, vel_ned, 0.1f, true, t1); + _vte->update(matrix::Vector3f{}); + + // THEN: mission aiding is available again even though the mission position was not set a second time. + ASSERT_TRUE(_aid_gps_mission_sub->update()); + EXPECT_EQ(_aid_gps_mission_sub->get().fusion_status[0], static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); + ASSERT_TRUE(_vte_state_sub->update()); + EXPECT_TRUE(_vte_state_sub->get().rel_pos_valid); +} + +// WHY: GPS offset should expire if it becomes stale. +// WHAT: Force an offset timeout and ensure the mission GPS measurement is +// rejected. +TEST_F(VTEPositionTest, MissionGpsOffsetTimeoutRejectsMeasurement) +{ + enableMask({FusionMaskOption::kMissionPos}); + + const matrix::Vector3f vel_ned(0.1f, 0.1f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + _vte->setMeasUpdatedTimeout(1_ms); + + const matrix::Vector3f gps_offset(1.f, 2.f, 3.f); + _vte->setGpsPosOffset(gps_offset, true); + _vte->setMissionPosition(kUavLat, kUavLon, kTargetAltM); + + const hrt_abstime gps_time = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.01f, 0.01f, vel_ned, 0.1f, true, gps_time); + _vte->update(matrix::Vector3f{}); + + EXPECT_FALSE(_aid_gps_mission_sub->update()); +} + +// WHY: UAV GPS velocity compensation must not fuse if the antenna rotation +// offset is stale. +// WHAT: Let the velocity offset expire before the next GPS +// sample and expect no velocity aid update. +TEST_F(VTEPositionTest, UavGpsVelocityOffsetTimeoutRejectsMeasurement) +{ + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kUavGpsVel}); + + const hrt_abstime init_vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(matrix::Vector3f{}, init_vel_time); + + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(matrix::Vector3f(2.f, 0.f, -1.f), vte_test::identityQuat(), + kSmallVisionCov, vision_time); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + vte_test::flushSubscription(_aid_gps_vel_uav_sub); + + _vte->setMeasUpdatedTimeout(1_ms); + _vte->setGpsPosOffset(matrix::Vector3f(1.f, 0.f, 0.f), true); + _vte->setVelOffset(matrix::Vector3f(0.2f, 0.3f, 0.4f)); + + vte_test::advanceMicroseconds(2_ms); + + const matrix::Vector3f vel_ned(0.8f, -1.2f, 0.4f); + const hrt_abstime gps_time = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.2f, 0.2f, vel_ned, 0.1f, true, + gps_time); + _vte->update(matrix::Vector3f{}); + + EXPECT_FALSE(_aid_gps_vel_uav_sub->update()); +} + +// WHY: UAV GPS velocity fusion should update state and sign-converted outputs. +// WHAT: Fuse GPS velocity and verify landing_target_pose uses negative sign. +TEST_F(VTEPositionTest, UavGpsVelocityFusionAndSign) +{ + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kUavGpsVel}); + + const matrix::Vector3f init_vel(0.f, 0.f, 0.f); + const hrt_abstime init_vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(init_vel, init_vel_time); + const hrt_abstime init_pos_time = vte_test::advanceMicroseconds(kStepUs); + setLocalPosition(matrix::Vector3f{}, init_pos_time); + + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(matrix::Vector3f(2.f, 0.f, -1.f), vte_test::identityQuat(), + kSmallVisionCov, vision_time); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto state_before = _vte_state_sub->get(); + + const matrix::Vector3f vel_ned(0.8f, -1.2f, 0.4f); + const hrt_abstime gps_time = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.2f, 0.2f, vel_ned, 0.1f, true, gps_time); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_vel_uav_sub->update()); + const auto aid = _aid_gps_vel_uav_sub->get(); + EXPECT_NEAR(aid.observation_variance[0], kDefaultGpsVelVar, kTolerance); + EXPECT_NEAR(aid.observation_variance[1], kDefaultGpsVelVar, kTolerance); + EXPECT_NEAR(aid.observation_variance[2], kDefaultGpsVelVar, kTolerance); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + ASSERT_TRUE(_target_pose_sub->update()); + const auto pose = _target_pose_sub->get(); + + EXPECT_GT(fabsf(state.vel_uav[0] - state_before.vel_uav[0]), 0.1f); + EXPECT_GT(fabsf(state.vel_uav[1] - state_before.vel_uav[1]), 0.1f); + EXPECT_GT(fabsf(state.vel_uav[2] - state_before.vel_uav[2]), 0.1f); + + EXPECT_NEAR(pose.vx_rel, -state.vel_uav[0], 0.5f); + EXPECT_NEAR(pose.vy_rel, -state.vel_uav[1], 0.5f); + EXPECT_NEAR(pose.vz_rel, -state.vel_uav[2], 0.5f); + EXPECT_TRUE(pose.rel_pos_valid); + EXPECT_TRUE(pose.rel_vel_valid); + +#if defined(CONFIG_VTEST_MOVING) + EXPECT_FALSE(pose.is_static); + EXPECT_FALSE(pose.rel_vel_ekf2_valid); +#else + EXPECT_TRUE(pose.is_static); + EXPECT_TRUE(pose.rel_vel_ekf2_valid); +#endif +} + +// WHY: EKF2 auxiliary-velocity aiding must require a recent relative +// measurement, while guidance can still use a finite relative velocity estimate. +// WHAT: Initialize from target GNSS only and verify the velocity-valid flag +// remains true but the EKF2-specific aiding flag stays false. +TEST_F(VTEPositionTest, GpsOnlyRelativeVelocityDoesNotEnableEkf2Aiding) +{ + enableMask({FusionMaskOption::kTargetGpsPos}); + + const matrix::Vector3f vel_ned(0.3f, -0.2f, 0.1f); + const hrt_abstime local_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, local_time); + setLocalPosition(matrix::Vector3f{}, local_time); + + const hrt_abstime gps_time = vte_test::advanceMicroseconds(kStepUs); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.2f, 0.2f, vel_ned, 0.1f, true, gps_time); + publishTargetGnss(kUavLat, kUavLon, kTargetAltM, 0.2f, 0.2f, gps_time, true); + + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_target_pose_sub->update()); + const auto pose = _target_pose_sub->get(); + EXPECT_TRUE(pose.rel_pos_valid); + EXPECT_TRUE(pose.rel_vel_valid); + EXPECT_FALSE(pose.rel_vel_ekf2_valid); +} + +// WHY: GNSS time misalignment should increase measurement variance. +// WHAT: Publish delayed UAV GPS and verify propagation uncertainty is included. +TEST_F(VTEPositionTest, TargetGpsInterpolationVariance) +{ + enableMask({FusionMaskOption::kTargetGpsPos}); + + static constexpr float kGpsPosNoise = 0.02f; + setParamFloat("VTE_GPS_P_NOISE", kGpsPosNoise); + _vte->updateParamsPublic(); + + const matrix::Vector3f vel_ned(10.f, 0.f, 0.f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + const hrt_abstime now = vte_test::nowUs(); + const hrt_abstime uav_time = now - 300_ms; + const hrt_abstime target_time = now - 100_ms; + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.01f, 0.01f, vel_ned, 1.0f, true, uav_time); + publishTargetGnss(kUavLat, kUavLon, kTargetAltM, 0.01f, 0.01f, target_time, true); + + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_target_sub->update()); + const auto aid = _aid_gps_target_sub->get(); + const float base_var = 2.f * kGpsPosNoise * kGpsPosNoise; + const float time_diff_s = (target_time - uav_time) * 1e-6f; + const float expected_shift = -vel_ned(0) * time_diff_s; + + EXPECT_NEAR(aid.observation[0], expected_shift, 0.05f); + EXPECT_GT(aid.observation_variance[0], base_var); + EXPECT_GT(aid.observation_variance[1], base_var); + EXPECT_GT(aid.observation_variance[2], base_var); +} + +// WHY: GNSS latency compensation should use vehicle CoM velocity rather than +// antenna velocity. +// WHAT: Apply a lever-arm velocity correction and verify +// the propagated target observation reflects it. +TEST_F(VTEPositionTest, TargetGpsInterpolationUsesLeverArmCorrectedVelocity) +{ + enableMask({FusionMaskOption::kTargetGpsPos}); + _vte->setMeasUpdatedTimeout(400_ms); + + const matrix::Vector3f vel_com_ned(7.f, 0.f, 0.f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_com_ned, vel_time); + + _vte->setGpsPosOffset(matrix::Vector3f(0.5f, 0.f, 0.f), true); + _vte->setVelOffset(matrix::Vector3f(3.f, 0.f, 0.f)); + + const hrt_abstime now = vte_test::nowUs(); + const hrt_abstime uav_time = now - 300_ms; + const hrt_abstime target_time = now - 100_ms; + const matrix::Vector3f antenna_vel_ned(10.f, 0.f, 0.f); + publishUavGps(kUavLat, kUavLon, kUavAltM, 0.01f, 0.01f, antenna_vel_ned, 1.0f, true, + uav_time); + publishTargetGnss(kUavLat, kUavLon, kTargetAltM, 0.01f, 0.01f, target_time, true); + + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_target_sub->update()); + const auto aid = _aid_gps_target_sub->get(); + const float time_diff_s = (target_time - uav_time) * 1e-6f; + const float expected_shift = -vel_com_ned(0) * time_diff_s + 0.5f; + + EXPECT_NEAR(aid.observation[0], expected_shift, 0.05f); +} + +// WHY: Old measurements must be dropped to avoid stale fusion. +// WHAT: Set a tiny timeout and ensure stale vision data is ignored. +TEST_F(VTEPositionTest, RejectsStaleMeasurement) +{ + enableMask({FusionMaskOption::kVisionPos}); + + const hrt_abstime meas_timeout = 1_ms; + _vte->setMeasRecentTimeout(meas_timeout); + setLocalVelocity(matrix::Vector3f(0.1f, 0.1f, 0.1f), vte_test::advanceMicroseconds(kStepUs)); + + const hrt_abstime stale_time = vte_test::nowUs() - (meas_timeout + 1_ms); + publishVisionPos(matrix::Vector3f(1.f, 1.f, 1.f), vte_test::identityQuat(), + kSmallVisionCov, stale_time); + _vte->update(matrix::Vector3f{}); + + EXPECT_FALSE(_aid_fiducial_sub->update()); + EXPECT_FALSE(_vte_state_sub->update()); +} + +// WHY: A long scheduling gap should reset the filter instead of predicting across stale time. +// WHAT: Initialize once, wait past the allowed prediction gap, then verify a fresh measurement re-initializes cleanly. +TEST_F(VTEPositionTest, ResetsFilterOnStalePredictionGap) +{ + const matrix::Vector3f initial_rel_pos(1.f, 0.5f, -2.f); + const matrix::Vector3f fresh_rel_pos(-0.5f, 1.25f, -1.5f); + + enableMask({FusionMaskOption::kVisionPos}); + _vte->setMeasUpdatedTimeout(500_ms); + setLocalVelocity(matrix::Vector3f{}, vte_test::advanceMicroseconds(kStepUs)); + + publishVisionPos(initial_rel_pos, vte_test::identityQuat(), kSmallVisionCov, + vte_test::advanceMicroseconds(kStepUs)); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto initial_state = _vte_state_sub->get(); + EXPECT_NEAR(initial_state.rel_pos[0], initial_rel_pos(0), kTolerance); + EXPECT_NEAR(initial_state.rel_pos[1], initial_rel_pos(1), kTolerance); + EXPECT_NEAR(initial_state.rel_pos[2], initial_rel_pos(2), kTolerance); + + vte_test::flushSubscription(_aid_fiducial_sub); + vte_test::flushSubscription(_vte_state_sub); + + vte_test::advanceMicroseconds(120_ms); + _vte->update(matrix::Vector3f{}); + + EXPECT_FALSE(_aid_fiducial_sub->update()); + EXPECT_FALSE(_vte_state_sub->update()); + + publishVisionPos(fresh_rel_pos, vte_test::identityQuat(), kSmallVisionCov, + vte_test::advanceMicroseconds(kStepUs)); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_fiducial_sub->update()); + const auto aid = _aid_fiducial_sub->get(); + EXPECT_EQ(aid.fusion_status[0], static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + EXPECT_NEAR(state.rel_pos[0], fresh_rel_pos(0), kTolerance); + EXPECT_NEAR(state.rel_pos[1], fresh_rel_pos(1), kTolerance); + EXPECT_NEAR(state.rel_pos[2], fresh_rel_pos(2), kTolerance); + EXPECT_NEAR(state.vel_uav[0], 0.f, kTolerance); + EXPECT_NEAR(state.vel_uav[1], 0.f, kTolerance); + EXPECT_NEAR(state.vel_uav[2], 0.f, kTolerance); +} + +// WHY: Position validity must reflect the configured timeout. +// WHAT: Set timeout to zero and confirm the published relative position is invalid. +TEST_F(VTEPositionTest, TargetValidityTimeout) +{ + enableMask({FusionMaskOption::kVisionPos}); + _vte->setTargetValidTimeout(0); + setLocalVelocity(matrix::Vector3f{}, vte_test::advanceMicroseconds(kStepUs)); + + publishVisionPos(matrix::Vector3f(0.2f, -0.4f, -1.f), vte_test::identityQuat(), + kSmallVisionCov, vte_test::advanceMicroseconds(kStepUs)); + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_vte_state_sub->update()); + const auto state = _vte_state_sub->get(); + EXPECT_FALSE(state.rel_pos_valid); + EXPECT_FALSE(state.rel_vel_valid); + EXPECT_FALSE(_target_pose_sub->update()); +} + +#if defined(CONFIG_VTEST_MOVING) +// WHY: Moving-target mode must fuse target velocity measurements. +// WHAT: Provide target GNSS velocity and verify fusion output. +TEST_F(VTEPositionTest, TargetVelocityFusionMoving) +{ + enableMask({FusionMaskOption::kVisionPos, FusionMaskOption::kTargetGpsVel}); + + const matrix::Vector3f vel_ned(0.1f, 0.1f, 0.1f); + const hrt_abstime vel_time = vte_test::advanceMicroseconds(kStepUs); + setLocalVelocity(vel_ned, vel_time); + + const hrt_abstime vision_time = vte_test::advanceMicroseconds(kStepUs); + publishVisionPos(matrix::Vector3f(0.f, 0.f, 0.f), vte_test::identityQuat(), + kSmallVisionCov, vision_time); + _vte->update(matrix::Vector3f{}); + + const matrix::Vector3f target_vel(1.f, 2.f, 3.f); + const hrt_abstime target_time = vte_test::advanceMicroseconds(kStepUs); + publishTargetGnss(kUavLat, kUavLon, kTargetAltM, 0.5f, 0.5f, target_time, + true, true, target_vel, 0.1f); + + _vte->update(matrix::Vector3f{}); + + ASSERT_TRUE(_aid_gps_vel_target_sub->update()); + const auto aid = _aid_gps_vel_target_sub->get(); + EXPECT_EQ(aid.fusion_status[0], static_cast(vte::FusionStatus::STATUS_FUSED_CURRENT)); + EXPECT_NEAR(aid.observation_variance[0], kDefaultGpsVelVar, kTolerance); + EXPECT_NEAR(aid.observation_variance[1], kDefaultGpsVelVar, kTolerance); + EXPECT_NEAR(aid.observation_variance[2], kDefaultGpsVelVar, kTolerance); +} +#endif diff --git a/src/modules/vision_target_estimator/test/TEST_VTE_KF_orientation.cpp b/src/modules/vision_target_estimator/test/TEST_VTE_KF_orientation.cpp new file mode 100644 index 00000000000..f922a22b341 --- /dev/null +++ b/src/modules/vision_target_estimator/test/TEST_VTE_KF_orientation.cpp @@ -0,0 +1,373 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file TEST_VTE_KF_orientation.cpp + * @brief Unit test KF_orientation.cpp + * + * @author Jonas Perolini + * + */ + +#include + +#include +#include +#include + +#include "Orientation/KF_orientation.h" + +namespace vte = vision_target_estimator; + +namespace +{ +using namespace time_literals; + +static constexpr float kTolerance = 1e-4f; +static constexpr float kPi = 3.14159265358979323846f; +static constexpr float kYawNearPi = 3.13f; +static constexpr hrt_abstime kNowOffset = 10_us; + +using StateVec = vte::KF_orientation::VectorState; +using StateCov = vte::KF_orientation::SquareMatrixState; +using ScalarMeas = vte::KF_orientation::ScalarMeas; + +StateVec makeState(float yaw, float yaw_rate) +{ + StateVec state{}; + state(vte::KF_orientation::kYaw) = yaw; + state(vte::KF_orientation::kYawRate) = yaw_rate; + return state; +} + +StateVec makeDiag(float d0, float d1) +{ + StateVec diag{}; + diag(0) = d0; + diag(1) = d1; + return diag; +} + +ScalarMeas makeMeas(uint64_t time_us, float val, float unc, const StateVec &H) +{ + ScalarMeas meas{}; + meas.time_us = time_us; + meas.val = val; + meas.unc = unc; + meas.H = H; + return meas; +} + +StateVec makeH(size_t index) +{ + StateVec H{}; + H(index) = 1.f; + return H; +} + +void expectStateAndCovUnchanged(const vte::KF_orientation &filter, const StateVec &state_before, + const StateCov &cov_before) +{ + const StateVec state_after = filter.getState(); + const StateCov cov_after = filter.getStateCovariance(); + + for (size_t i = 0; i < vte::KF_orientation::kSize; i++) { + EXPECT_NEAR(state_after(i), state_before(i), kTolerance); + + for (size_t j = 0; j < vte::KF_orientation::kSize; j++) { + EXPECT_NEAR(cov_after(i, j), cov_before(i, j), kTolerance); + } + } +} + +} // namespace + +// WHY: Yaw must remain in [-pi, pi] to avoid discontinuities. +// WHAT: Predict across the wrap and ensure yaw is normalized. +TEST(KFOrientationTest, PredictWrapsYaw) +{ + // GIVEN: a yaw near +pi with a positive yaw-rate. + vte::KF_orientation filter; + const float yaw = 3.1f; + const float yaw_rate = 1.0f; + const float dt = 1.0f; + filter.setState(makeState(yaw, yaw_rate)); + filter.setStateCovarianceDiag(makeDiag(0.f, 0.f)); + + // WHEN: we advance the filter by one second (crossing pi). + filter.predict(dt); + + // THEN: the predicted yaw is wrapped back into [-pi, pi] and yaw-rate is unchanged. + const StateVec state = filter.getState(); + const float expected_yaw = matrix::wrap_pi(yaw + yaw_rate * dt); + + EXPECT_NEAR(state(vte::KF_orientation::kYaw), expected_yaw, kTolerance); + EXPECT_NEAR(state(vte::KF_orientation::kYawRate), yaw_rate, kTolerance); +} + +// WHY: Process noise must be injected to model yaw acceleration uncertainty. +// WHAT: Verify Q terms are added when yaw_acc_var > 0. +TEST(KFOrientationTest, PredictAddsProcessNoise) +{ + // GIVEN: a zero-initialized covariance and a positive yaw-acceleration variance. + vte::KF_orientation filter; + filter.setState(makeState(0.f, 0.f)); + filter.setStateCovarianceDiag(makeDiag(0.f, 0.f)); + filter.setYawAccVar(0.4f); + + // WHEN: we predict for dt = 2s. + filter.predict(2.0f); + + // THEN: the diagonal terms match the white-noise yaw-acceleration integration. + const StateVec cov_diag = filter.getStateCovarianceDiag(); + + const float expected_p00 = (8.f / 3.f) * 0.4f; + const float expected_p11 = 2.0f * 0.4f; + + EXPECT_NEAR(cov_diag(vte::KF_orientation::kYaw), expected_p00, kTolerance); + EXPECT_NEAR(cov_diag(vte::KF_orientation::kYawRate), expected_p11, kTolerance); +} + +// WHY: The white-noise yaw acceleration model introduces cross-covariance terms. +// WHAT: Ensure off-diagonal terms match dt^2/2 * var and covariance remains symmetric. +TEST(KFOrientationTest, PredictAddsOffDiagonalCovariance) +{ + // GIVEN: a zero covariance with a positive yaw-acc variance. + vte::KF_orientation filter; + filter.setState(makeState(0.f, 0.f)); + filter.setStateCovarianceDiag(makeDiag(0.f, 0.f)); + filter.setYawAccVar(0.4f); + + // WHEN: we predict by dt = 0.5s. + const float dt = 0.5f; + filter.predict(dt); + + // THEN: yaw/yaw-rate cross terms equal dt^2/2 * var and are symmetric. + const auto cov = filter.getStateCovariance(); + const float expected_off_diag = 0.5f * dt * dt * 0.4f; + + EXPECT_NEAR(cov(vte::KF_orientation::kYaw, vte::KF_orientation::kYawRate), expected_off_diag, kTolerance); + EXPECT_NEAR(cov(vte::KF_orientation::kYawRate, vte::KF_orientation::kYaw), expected_off_diag, kTolerance); + EXPECT_NEAR(cov(vte::KF_orientation::kYaw, vte::KF_orientation::kYawRate), cov(vte::KF_orientation::kYawRate, vte::KF_orientation::kYaw), + kTolerance); +} + +// WHY: Invalid noise parameters must not corrupt the covariance. +// WHAT: Confirm negative yaw_acc_var bypasses the Q addition. +TEST(KFOrientationTest, PredictIgnoresInvalidYawAccVar) +{ + // GIVEN: a valid prior covariance and a negative (invalid) yaw-acc variance. + vte::KF_orientation filter; + filter.setState(makeState(0.f, 0.f)); + filter.setStateCovarianceDiag(makeDiag(1.f, 2.f)); + filter.setYawAccVar(-1.f); + + // WHEN: we predict for dt = 1s. + filter.predict(1.0f); + + // THEN: only the deterministic propagation is applied (no Q injection). + const StateVec cov_diag = filter.getStateCovarianceDiag(); + + EXPECT_NEAR(cov_diag(vte::KF_orientation::kYaw), 3.f, kTolerance); + EXPECT_NEAR(cov_diag(vte::KF_orientation::kYawRate), 2.f, kTolerance); +} + +// WHY: Zero dt should not change state or covariance. +// WHAT: Predict with dt=0 and ensure state/cov stay unchanged. +TEST(KFOrientationTest, PredictZeroDtNoChange) +{ + // GIVEN: a filter with an arbitrary state/covariance snapshot. + vte::KF_orientation filter; + filter.setState(makeState(1.2f, -0.5f)); + filter.setStateCovarianceDiag(makeDiag(0.3f, 0.2f)); + filter.setYawAccVar(0.4f); + + const StateVec state_before = filter.getState(); + const StateCov cov_before = filter.getStateCovariance(); + + // WHEN: we call predict with dt = 0. + filter.predict(0.f); + + // THEN: the filter is a no-op: state and covariance are preserved. + expectStateAndCovUnchanged(filter, state_before, cov_before); +} + +// WHY: Invalid predict inputs must not corrupt state or covariance. +// WHAT: Exercise the negative-dt and non-finite-dt guards. +TEST(KFOrientationTest, PredictRejectsInvalidDt) +{ + vte::KF_orientation filter; + filter.setState(makeState(-1.0f, 0.7f)); + filter.setStateCovarianceDiag(makeDiag(0.6f, 0.4f)); + filter.setYawAccVar(0.4f); + + const StateVec state_before = filter.getState(); + const StateCov cov_before = filter.getStateCovariance(); + + filter.predict(-0.1f); + expectStateAndCovUnchanged(filter, state_before, cov_before); + + filter.predict(NAN); + expectStateAndCovUnchanged(filter, state_before, cov_before); +} + +// WHY: Innovations across the wrap should be small, not ~2pi. +// WHAT: Check innovation for +pi to -pi transitions is wrapped. +TEST(KFOrientationTest, InnovationWrapsAcrossPi) +{ + vte::KF_orientation filter; + filter.setState(makeState(kYawNearPi, 0.f)); + filter.setStateCovarianceDiag(makeDiag(1.f, 1.f)); + + const StateVec H = makeH(vte::KF_orientation::kYaw); + static constexpr hrt_abstime kMeasTime = 1_s; + const vte::KF_orientation::ScalarMeas meas = makeMeas(kMeasTime, -kYawNearPi, 0.1f, H); + const vte::FusionResult res = filter.fuseScalarAtTime(meas, kMeasTime + kNowOffset, 100.f); + + const float expected_innov = matrix::wrap_pi(-kYawNearPi - kYawNearPi); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_NEAR(res.innov, expected_innov, kTolerance); +} + +// WHY: Only yaw innovations should be wrapped; yaw-rate is linear. +// WHAT: Ensure yaw-rate innovation uses the raw difference. +TEST(KFOrientationTest, InnovationDoesNotWrapYawRateMeasurement) +{ + vte::KF_orientation filter; + filter.setState(makeState(0.f, kYawNearPi)); + filter.setStateCovarianceDiag(makeDiag(1.f, 1.f)); + + const StateVec H = makeH(vte::KF_orientation::kYawRate); + static constexpr hrt_abstime kMeasTime = 1500_ms; + const vte::KF_orientation::ScalarMeas meas = makeMeas(kMeasTime, -kYawNearPi, 0.1f, H); + const vte::FusionResult res = filter.fuseScalarAtTime(meas, kMeasTime + kNowOffset, 100.f); + + const float expected_innov = -kYawNearPi - kYawNearPi; + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_NEAR(res.innov, expected_innov, kTolerance); +} + +// WHY: NIS gating is critical to rejecting yaw outliers. +// WHAT: Provide a large innovation and expect REJECT_NIS. +TEST(KFOrientationTest, RejectsOutlierNis) +{ + vte::KF_orientation filter; + filter.setState(makeState(0.f, 0.f)); + filter.setStateCovarianceDiag(makeDiag(0.01f, 0.01f)); + + const StateVec H = makeH(vte::KF_orientation::kYaw); + static constexpr hrt_abstime kMeasTime = 2_s; + const vte::KF_orientation::ScalarMeas meas = makeMeas(kMeasTime, kPi, 0.01f, H); + const vte::FusionResult res = filter.fuseScalarAtTime(meas, kMeasTime + kNowOffset, 0.1f); + + const StateVec state = filter.getState(); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_REJECT_NIS); + EXPECT_NEAR(state(vte::KF_orientation::kYaw), 0.f, kTolerance); + EXPECT_NEAR(state(vte::KF_orientation::kYawRate), 0.f, kTolerance); +} + +// WHY: Very small variances can destabilize future updates. +// WHAT: Ensure correction enforces a minimum covariance floor. +TEST(KFOrientationTest, ClampCovarianceToMin) +{ + vte::KF_orientation filter; + filter.setState(makeState(0.f, 0.f)); + filter.setStateCovarianceDiag(makeDiag(1e-12f, 1e-12f)); + + const StateVec H = makeH(vte::KF_orientation::kYaw); + // Keep innovation small to avoid NIS rejection while exercising the clamp. + static constexpr hrt_abstime kMeasTime = 3_s; + const vte::KF_orientation::ScalarMeas meas = makeMeas(kMeasTime, 0.f, 1e-4f, H); + const vte::FusionResult res = filter.fuseScalarAtTime(meas, kMeasTime + kNowOffset, 100.f); + const StateVec cov_diag = filter.getStateCovarianceDiag(); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_GE(cov_diag(vte::KF_orientation::kYaw), vte::KF_orientation::kMinVar); + EXPECT_GE(cov_diag(vte::KF_orientation::kYawRate), vte::KF_orientation::kMinVar); +} + +// WHY: Correction should normalize yaw after applying the gain. +// WHAT: Force a correction that would exceed pi without wrapping. +TEST(KFOrientationTest, CorrectionWrapsYaw) +{ + vte::KF_orientation filter; + filter.setState(makeState(kYawNearPi, 0.f)); + filter.setStateCovarianceDiag(makeDiag(0.5f, 0.2f)); + + const StateVec H = makeH(vte::KF_orientation::kYaw); + static constexpr hrt_abstime kMeasTime = 4_s; + const vte::KF_orientation::ScalarMeas meas = makeMeas(kMeasTime, -kYawNearPi, 0.2f, H); + const vte::FusionResult res = filter.fuseScalarAtTime(meas, kMeasTime + kNowOffset, 100.f); + const StateVec state = filter.getState(); + + const float expected_innov = matrix::wrap_pi(-kYawNearPi - kYawNearPi); + const float expected_k = 0.5f / (0.5f + 0.2f); + const float expected_yaw = matrix::wrap_pi(kYawNearPi + expected_k * expected_innov); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_NEAR(res.innov, expected_innov, kTolerance); + EXPECT_NEAR(state(vte::KF_orientation::kYaw), expected_yaw, kTolerance); + EXPECT_LE(state(vte::KF_orientation::kYaw), kPi); + EXPECT_GE(state(vte::KF_orientation::kYaw), -kPi); +} + +// WHY: Corrections must keep covariance symmetric and within the Cauchy-Schwarz bound. +// WHAT: Predict to seed cross-covariance, fuse a yaw measurement, and verify symmetry +// plus |cov(i,j)| <= sqrt(var(i) * var(j)). +TEST(KFOrientationTest, CorrectionMaintainsSymmetricCovariance) +{ + vte::KF_orientation filter; + filter.setState(makeState(0.2f, 0.1f)); + filter.setStateCovarianceDiag(makeDiag(0.6f, 0.4f)); + filter.setYawAccVar(0.3f); + + // Predict so the yaw/yaw-rate cross-covariance is non-zero before fusion. + filter.predict(0.2f); + + const StateVec H = makeH(vte::KF_orientation::kYaw); + static constexpr hrt_abstime kMeasTime = 5_s; + const vte::KF_orientation::ScalarMeas meas = makeMeas(kMeasTime, 0.25f, 0.1f, H); + const vte::FusionResult res = filter.fuseScalarAtTime(meas, kMeasTime + kNowOffset, 100.f); + const StateCov cov_after = filter.getStateCovariance(); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_NEAR(cov_after(vte::KF_orientation::kYaw, vte::KF_orientation::kYawRate), + cov_after(vte::KF_orientation::kYawRate, vte::KF_orientation::kYaw), kTolerance); + + const float cs_bound = sqrtf(cov_after(vte::KF_orientation::kYaw, vte::KF_orientation::kYaw) + * cov_after(vte::KF_orientation::kYawRate, vte::KF_orientation::kYawRate)) + kTolerance; + EXPECT_LE(fabsf(cov_after(vte::KF_orientation::kYaw, vte::KF_orientation::kYawRate)), cs_bound); +} diff --git a/src/modules/vision_target_estimator/test/TEST_VTE_KF_position.cpp b/src/modules/vision_target_estimator/test/TEST_VTE_KF_position.cpp new file mode 100644 index 00000000000..c9c83ff04af --- /dev/null +++ b/src/modules/vision_target_estimator/test/TEST_VTE_KF_position.cpp @@ -0,0 +1,633 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file TEST_VTE_KF_position.cpp + * @brief Unit test KF_position.cpp + * + * @author Jonas Perolini + * + */ + +#include + +#include +#include +#include +#include + +#include "Position/KF_position.h" + +namespace vte = vision_target_estimator; + +namespace +{ +using namespace time_literals; + +static constexpr float kTolerance = 1e-4f; +static constexpr float kTightTolerance = 1e-7f; +#if !defined(CONFIG_VTEST_MOVING) +static constexpr hrt_abstime kNowOffset = 10_us; +#endif // !defined(CONFIG_VTEST_MOVING) + +using StateVec = vte::KF_position::VectorState; +using StateCov = vte::KF_position::SquareMatrixState; +using ScalarMeas = vte::KF_position::ScalarMeas; + +#if !defined(CONFIG_VTEST_MOVING) +StateVec makeState(float pos_rel, float vel_uav, float bias) +{ + StateVec state{}; + state(vtest::State::pos_rel) = pos_rel; + state(vtest::State::vel_uav) = vel_uav; + state(vtest::State::bias) = bias; + return state; +} + +StateVec makeDiag(float d0, float d1, float d2) +{ + StateVec diag{}; + diag(0) = d0; + diag(1) = d1; + diag(2) = d2; + return diag; +} +#endif + +#if defined(CONFIG_VTEST_MOVING) +StateVec makeStateMoving(float pos_rel, float vel_uav, float bias, float acc_target, float vel_target) +{ + StateVec state{}; + state(vtest::State::pos_rel) = pos_rel; + state(vtest::State::vel_uav) = vel_uav; + state(vtest::State::bias) = bias; + state(vtest::State::acc_target) = acc_target; + state(vtest::State::vel_target) = vel_target; + return state; +} + +StateVec makeDiagMoving(float d0, float d1, float d2, float d3, float d4) +{ + StateVec diag{}; + diag(0) = d0; + diag(1) = d1; + diag(2) = d2; + diag(3) = d3; + diag(4) = d4; + return diag; +} +#endif + +void setFilterState(vte::KF_position &filter, const StateVec &state, const StateVec &cov_diag) +{ + filter.setState(state); + filter.setStateCovarianceDiag(cov_diag); +} + +void expectSymmetric(const StateCov &cov, float tolerance = kTolerance) +{ + for (size_t row = 0; row < vte::KF_position::kStateSize; row++) { + for (size_t col = 0; col < vte::KF_position::kStateSize; col++) { + EXPECT_NEAR(cov(row, col), cov(col, row), tolerance); + } + } +} + +void expectStateAndCovUnchanged(const vte::KF_position &filter, const StateVec &state_before, + const StateCov &cov_before) +{ + const StateVec state_after = filter.getState(); + const StateCov cov_after = filter.getStateCovariance(); + + for (size_t i = 0; i < vte::KF_position::kStateSize; i++) { + EXPECT_NEAR(state_after(i), state_before(i), kTolerance); + + for (size_t j = 0; j < vte::KF_position::kStateSize; j++) { + EXPECT_NEAR(cov_after(i, j), cov_before(i, j), kTolerance); + } + } +} + +#if !defined(CONFIG_VTEST_MOVING) +ScalarMeas makeMeas(uint64_t time_us, float val, float unc, const StateVec &H) +{ + ScalarMeas meas{}; + meas.time_us = time_us; + meas.val = val; + meas.unc = unc; + meas.H = H; + return meas; +} + +StateVec makeH(uint8_t index) +{ + StateVec H{}; + H(index) = 1.f; + return H; +} + +hrt_abstime makeFusionNow(hrt_abstime meas_time) +{ + return meas_time + kNowOffset; +} +#endif // !defined(CONFIG_VTEST_MOVING) + +} // namespace + +// WHY: Invalid predict inputs must not corrupt state or covariance. +// WHAT: Exercise the negative-dt, non-finite-dt, and non-finite-acceleration guards. +TEST(KFPositionTest, PredictRejectsInvalidInputs) +{ + StateVec state{}; + StateVec cov_diag{}; + + for (size_t i = 0; i < vte::KF_position::kStateSize; i++) { + state(i) = 1.f + static_cast(i); + cov_diag(i) = 0.1f * (1.f + static_cast(i)); + } + + vte::KF_position filter; + setFilterState(filter, state, cov_diag); + + const StateVec state_before = filter.getState(); + const StateCov cov_before = filter.getStateCovariance(); + + filter.predict(-0.01f, 1.f); + expectStateAndCovUnchanged(filter, state_before, cov_before); + + filter.predict(NAN, 1.f); + expectStateAndCovUnchanged(filter, state_before, cov_before); + + filter.predict(0.01f, NAN); + expectStateAndCovUnchanged(filter, state_before, cov_before); +} + +#if !defined(CONFIG_VTEST_MOVING) + +// WHY: State propagation and process-noise integration are the backbone of the +// position filter. A regression here corrupts every downstream fusion. +// WHAT: Predict one step from a non-zero prior and check both the propagated state +// and the full Q-augmented covariance against the analytic discrete model. +TEST(KFPositionTest, PredictUpdatesStateAndCovariance) +{ + // Inputs (named so a failing line points at a labelled quantity, not a literal). + constexpr float kInitPosRel = 1.f; // m + constexpr float kInitVelUav = 2.f; // m/s + constexpr float kInitBias = 3.f; // m + constexpr float kPriorVarPos = 1.f; // m^2 (diagonal prior) + constexpr float kPriorVarVel = 2.f; // (m/s)^2 + constexpr float kPriorVarBias = 3.f; // m^2 + constexpr float kQAcc = 0.4f; // UAV-acceleration PSD, m^2/s^3 + constexpr float kQBias = 0.1f; // bias random-walk PSD, m^2/s + constexpr float kDt = 0.5f; // s + constexpr float kAccUav = 1.5f; // m/s^2 (deterministic input) + + vte::KF_position filter; + setFilterState(filter, makeState(kInitPosRel, kInitVelUav, kInitBias), + makeDiag(kPriorVarPos, kPriorVarVel, kPriorVarBias)); + filter.setInputVar(kQAcc); + filter.setBiasVar(kQBias); + + filter.predict(kDt, kAccUav); + + // Reference state: discrete prediction model (static target) + // r_{k+1} = r_k - dt * v_uav_k - 0.5 * dt^2 * acc_uav + // v_uav_{k+1} = v_uav_k + dt * acc_uav + // b_{k+1} = b_k + const float dt2 = kDt * kDt; + const float dt3 = dt2 * kDt; + const float expected_pos_rel = kInitPosRel - kDt * kInitVelUav - 0.5f * dt2 * kAccUav; + const float expected_vel_uav = kInitVelUav + kDt * kAccUav; + const float expected_bias = kInitBias; + + const StateVec state = filter.getState(); + EXPECT_NEAR(state(vtest::State::pos_rel), expected_pos_rel, kTolerance); + EXPECT_NEAR(state(vtest::State::vel_uav), expected_vel_uav, kTolerance); + EXPECT_NEAR(state(vtest::State::bias), expected_bias, kTolerance); + + // Reference covariance: P_new = Phi * P_prior * Phi^T + Q. + // For diagonal P_prior and the static Phi (only off-diagonal entry is Phi[r,v_uav] = -dt): + // (Phi P Phi^T)[r, r] = var(r) + dt^2 * var(v_uav) + // (Phi P Phi^T)[r, v_uav] = -dt * var(v_uav) + // (Phi P Phi^T)[v_uav,v_uav] = var(v_uav) + // (Phi P Phi^T)[b, b] = var(b) + // Q from continuous white UAV-acceleration noise + bias random walk: + // Q[r, r] = q_acc * dt^3 / 3 + // Q[r, v_uav] = -q_acc * dt^2 / 2 + // Q[v_uav, v_uav] = q_acc * dt + // Q[b, b] = q_bias * dt + const float expected_p_r_r = kPriorVarPos + dt2 * kPriorVarVel + kQAcc * dt3 / 3.f; + const float expected_p_r_v = -kDt * kPriorVarVel - kQAcc * dt2 / 2.f; + const float expected_p_v_v = kPriorVarVel + kQAcc * kDt; + const float expected_p_b_b = kPriorVarBias + kQBias * kDt; + + const StateCov cov = filter.getStateCovariance(); + EXPECT_NEAR(cov(vtest::State::pos_rel, vtest::State::pos_rel), expected_p_r_r, kTolerance); + EXPECT_NEAR(cov(vtest::State::pos_rel, vtest::State::vel_uav), expected_p_r_v, kTolerance); + EXPECT_NEAR(cov(vtest::State::vel_uav, vtest::State::pos_rel), expected_p_r_v, kTolerance); + EXPECT_NEAR(cov(vtest::State::vel_uav, vtest::State::vel_uav), expected_p_v_v, kTolerance); + EXPECT_NEAR(cov(vtest::State::bias, vtest::State::bias), expected_p_b_b, kTolerance); + expectSymmetric(cov); +} + +// WHY: Continuous-time process noise should not depend on how the predict +// interval is sliced. dt-invariance is what makes the spectral-density +// parameterization transferable across update rates. +// WHAT: One predict step of dt and two predict steps of dt/2 from the same zero +// prior must produce the same posterior covariance. +TEST(KFPositionTest, PredictCovarianceIsSplitStepInvariant) +{ + constexpr float kQAcc = 0.4f; + constexpr float kQBias = 0.1f; + constexpr float kFullDt = 0.02f; + constexpr float kHalfDt = 0.01f; + + const StateVec zero_state = makeState(0.f, 0.f, 0.f); + const StateVec zero_cov = makeDiag(0.f, 0.f, 0.f); + + vte::KF_position single_step; + vte::KF_position split_step; + setFilterState(single_step, zero_state, zero_cov); + setFilterState(split_step, zero_state, zero_cov); + single_step.setInputVar(kQAcc); + single_step.setBiasVar(kQBias); + split_step.setInputVar(kQAcc); + split_step.setBiasVar(kQBias); + + single_step.predict(kFullDt, 0.f); + split_step.predict(kHalfDt, 0.f); + split_step.predict(kHalfDt, 0.f); + + const StateCov cov_single = single_step.getStateCovariance(); + const StateCov cov_split = split_step.getStateCovariance(); + + for (size_t row = 0; row < vte::KF_position::kStateSize; row++) { + for (size_t col = 0; col < vte::KF_position::kStateSize; col++) { + EXPECT_NEAR(cov_single(row, col), cov_split(row, col), kTightTolerance) + << "Split-step mismatch at (" << row << ", " << col << ")"; + } + } +} + +// WHY: Innovation consistency ensures measurement mapping is correct. +// WHAT: Check innov and innov_var against an analytic H*x and HPH^T + R. +TEST(KFPositionTest, InnovationMatchesH) +{ + // GIVEN: a filter with a position measurement model and a finite prior covariance. + vte::KF_position filter; + setFilterState(filter, makeState(1.f, 2.f, 3.f), makeDiag(4.f, 1.f, 1.f)); + + const StateVec H = makeH(vtest::State::pos_rel); + static constexpr hrt_abstime kMeasTime = 1_s; + const ScalarMeas meas = makeMeas(kMeasTime, 2.5f, 0.5f, H); + + const StateVec state_before = filter.getState(); + const StateVec cov_diag_before = filter.getStateCovarianceDiag(); + + // WHEN: we fuse the measurement with a permissive NIS threshold. + const vte::FusionResult res = filter.fuseScalarAtTime(meas, makeFusionNow(kMeasTime), 1e6f); + + // THEN: the reported innovation terms equal the analytic residual and variance. + const float expected_innov = meas.val - state_before(vtest::State::pos_rel); + const float expected_innov_var = cov_diag_before(vtest::State::pos_rel) + meas.unc; + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_NEAR(res.innov, expected_innov, kTolerance); + EXPECT_NEAR(res.innov_var, expected_innov_var, kTolerance); +} + +// WHY: The fast-path (non-OOSM) fusion is used for most measurements. +// WHAT: Verify current fusion updates state and reduces covariance as expected. +TEST(KFPositionTest, FusesCurrentMeasurement) +{ + // GIVEN: a filter with uncertainty on relative position and a matching position measurement. + vte::KF_position filter; + setFilterState(filter, makeState(0.f, 0.f, 0.f), makeDiag(4.f, 1.f, 1.f)); + + const StateVec H = makeH(vtest::State::pos_rel); + static constexpr hrt_abstime kMeasTime = 2_s; + const hrt_abstime now = makeFusionNow(kMeasTime); + const ScalarMeas meas = makeMeas(kMeasTime, 5.f, 1.f, H); + + const float state_pos = filter.getState()(vtest::State::pos_rel); + const float p00 = filter.getStateCovarianceDiag()(vtest::State::pos_rel); + const float innov = meas.val - state_pos; + const float innov_var = p00 + meas.unc; + const float k_pos = p00 / innov_var; + const float expected_pos = state_pos + k_pos * innov; + const float expected_p00 = (1.f - k_pos) * p00; + + // WHEN: we fuse the current measurement and then one stamped slightly in the future. + const vte::FusionResult res = filter.fuseScalarAtTime(meas, now, 100.f); + const StateVec state = filter.getState(); + const StateVec cov_diag = filter.getStateCovarianceDiag(); + const hrt_abstime future_meas_time = now + 10_ms; + const ScalarMeas future_meas = makeMeas(future_meas_time, 6.f, 1.f, H); + const vte::FusionResult future_res = filter.fuseScalarAtTime(future_meas, now, 100.f); + + // THEN: only the observed state is corrected and future stamps still use the current path. + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_NEAR(state(vtest::State::pos_rel), expected_pos, kTolerance); + EXPECT_NEAR(cov_diag(vtest::State::pos_rel), expected_p00, kTolerance); + EXPECT_NEAR(cov_diag(vtest::State::vel_uav), 1.f, kTolerance); + EXPECT_NEAR(cov_diag(vtest::State::bias), 1.f, kTolerance); + EXPECT_EQ(future_res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); +} + +// WHY: Invalid innovation variance must stop the correction to avoid NaNs. +// WHAT: Ensure REJECT_COV and unchanged state when S is near zero. +TEST(KFPositionTest, RejectsInvalidInnovationVariance) +{ + // GIVEN: a measurement with zero uncertainty applied to a zero-covariance prior. + vte::KF_position filter; + setFilterState(filter, makeState(1.f, 2.f, 3.f), makeDiag(0.f, 0.f, 0.f)); + + const StateVec H = makeH(vtest::State::pos_rel); + static constexpr hrt_abstime kMeasTime = 3_s; + const ScalarMeas meas = makeMeas(kMeasTime, 1.f, 0.f, H); + + // WHEN: we attempt to fuse the measurement. + const vte::FusionResult res = filter.fuseScalarAtTime(meas, makeFusionNow(kMeasTime), 100.f); + + // THEN: the filter rejects the correction and preserves the full state. + const StateVec state = filter.getState(); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_REJECT_COV); + EXPECT_NEAR(state(vtest::State::pos_rel), 1.f, kTolerance); + EXPECT_NEAR(state(vtest::State::vel_uav), 2.f, kTolerance); + EXPECT_NEAR(state(vtest::State::bias), 3.f, kTolerance); +} + +// WHY: NIS gating protects against large outliers. +// WHAT: Provide a large innovation with small variance and expect REJECT_NIS. +TEST(KFPositionTest, RejectsOutlierNis) +{ + // GIVEN: a tightly constrained prior and a large position residual. + vte::KF_position filter; + setFilterState(filter, makeState(0.f, 0.f, 0.f), makeDiag(0.01f, 0.01f, 0.01f)); + + const StateVec H = makeH(vtest::State::pos_rel); + static constexpr hrt_abstime kMeasTime = 3500_ms; + const ScalarMeas meas = makeMeas(kMeasTime, 10.f, 0.01f, H); + + // WHEN: we fuse with a tight NIS threshold. + const vte::FusionResult res = filter.fuseScalarAtTime(meas, makeFusionNow(kMeasTime), 0.1f); + + // THEN: the measurement is rejected and the state remains untouched. + const StateVec state = filter.getState(); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_REJECT_NIS); + EXPECT_NEAR(state(vtest::State::pos_rel), 0.f, kTolerance); + EXPECT_NEAR(state(vtest::State::vel_uav), 0.f, kTolerance); + EXPECT_NEAR(state(vtest::State::bias), 0.f, kTolerance); +} + +// WHY: GNSS with bias must use H(pos_rel)=1 and H(bias)=1. +// WHAT: Verify innovation and corrections for a joint position+bias observation. +TEST(KFPositionTest, FusesMeasurementWithBiasInH) +{ + // GIVEN: a filter whose position and bias both contribute to the scalar measurement. + vte::KF_position filter; + setFilterState(filter, makeState(1.f, 0.f, 2.f), makeDiag(2.f, 1.f, 3.f)); + + StateVec H{}; + H(vtest::State::pos_rel) = 1.f; + H(vtest::State::bias) = 1.f; + + static constexpr hrt_abstime kMeasTime = 3600_ms; + const ScalarMeas meas = makeMeas(kMeasTime, 10.f, 1.f, H); + + // WHEN: we fuse the combined position-plus-bias observation. + const vte::FusionResult res = filter.fuseScalarAtTime(meas, makeFusionNow(kMeasTime), 100.f); + + // THEN: the innovation is shared across both observed states according to their variance. + const StateVec state = filter.getState(); + + const float expected_innov = 10.f - (1.f + 2.f); + const float innov_var = 2.f + 3.f + 1.f; + const float k_pos = 2.f / innov_var; + const float k_bias = 3.f / innov_var; + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_NEAR(res.innov, expected_innov, kTolerance); + EXPECT_NEAR(state(vtest::State::pos_rel), 1.f + k_pos * expected_innov, kTolerance); + EXPECT_NEAR(state(vtest::State::bias), 2.f + k_bias * expected_innov, kTolerance); +} + +// WHY: OOSM fusion must handle delayed measurements consistently. +// WHAT: Provide history and fuse a delayed measurement to trigger FUSED_OOSM. +TEST(KFPositionTest, FusesOosmMeasurementWithHistory) +{ + // GIVEN: a filter with three history snapshots spanning the delayed measurement time. + vte::KF_position filter; + setFilterState(filter, makeState(0.f, 0.f, 0.f), makeDiag(1.f, 1.f, 1.f)); + filter.setInputVar(0.2f); + filter.setBiasVar(0.1f); + + static constexpr hrt_abstime kT0 = 1_s; + static constexpr hrt_abstime kHistoryStep = 20_ms; + static constexpr hrt_abstime kMeasOffset = 10_ms; + static constexpr hrt_abstime kNowOffsetLocal = 60_ms; + + filter.predict(0.02f, 1.f); + filter.pushHistory(kT0); + filter.predict(0.02f, 1.f); + filter.pushHistory(kT0 + kHistoryStep); + filter.predict(0.02f, 1.f); + filter.pushHistory(kT0 + kHistoryStep * 2); + + const StateVec state_before = filter.getState(); + const StateVec H = makeH(vtest::State::pos_rel); + const ScalarMeas meas = makeMeas(kT0 + kMeasOffset, 5.f, 0.5f, H); + + // WHEN: we fuse the delayed measurement after newer samples are already in history. + const vte::FusionResult res = filter.fuseScalarAtTime(meas, kT0 + kNowOffsetLocal, 100.f); + + // THEN: the OOSM path is used and the delayed correction changes the current state. + const StateVec state_after = filter.getState(); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_OOSM); + EXPECT_GT(res.history_steps, 0u); + EXPECT_GT(fabsf(state_after(vtest::State::pos_rel) - state_before(vtest::State::pos_rel)), 1e-4f); +} + +// WHY: Very small covariances can destabilize future updates. +// WHAT: Verify covariance diagonals are clamped to a minimum after correction. +TEST(KFPositionTest, ClampCovarianceToMin) +{ + // GIVEN: a filter with near-zero covariance and a near-zero innovation measurement. + vte::KF_position filter; + setFilterState(filter, makeState(0.f, 0.f, 0.f), makeDiag(1e-12f, 1e-12f, 1e-12f)); + + const StateVec H = makeH(vtest::State::pos_rel); + static constexpr hrt_abstime kMeasTime = 4_s; + const ScalarMeas meas = makeMeas(kMeasTime, 0.f, 1e-4f, H); + + // WHEN: we fuse without triggering NIS rejection. + const vte::FusionResult res = filter.fuseScalarAtTime(meas, makeFusionNow(kMeasTime), 100.f); + + // THEN: every diagonal entry is clamped to at least the configured minimum variance. + const StateVec cov_diag = filter.getStateCovarianceDiag(); + + EXPECT_EQ(res.status, vte::FusionStatus::STATUS_FUSED_CURRENT); + EXPECT_GE(cov_diag(vtest::State::pos_rel), vte::KF_position::kMinVar); + EXPECT_GE(cov_diag(vtest::State::vel_uav), vte::KF_position::kMinVar); + EXPECT_GE(cov_diag(vtest::State::bias), vte::KF_position::kMinVar); +} + +#endif // !defined(CONFIG_VTEST_MOVING) + +#if defined(CONFIG_VTEST_MOVING) +// WHY: In moving mode, target velocity and acceleration couple into pos_rel, +// and white jerk on acc_target injects an integrated noise block. Both +// must be present and correct. +// WHAT: Predict one step with only target-jerk PSD enabled (UAV and bias PSDs +// zeroed). State propagation must include the target-motion coupling; the +// resulting covariance must equal the closed-form constant-jerk Q block +// because the prior covariance is zero. +TEST(KFPositionTest, PredictMovingTargetAddsTargetTerms) +{ + // Initial state: non-zero so the propagation coupling is observable. + constexpr float kInitPosRel = 1.f; // m + constexpr float kInitVelUav = 2.f; // m/s + constexpr float kInitBias = 3.f; // m + constexpr float kInitAccTarget = 0.4f; // m/s^2 + constexpr float kInitVelTarget = -0.5f; // m/s + // Process noise: only target jerk is active so the resulting Q isolates that path. + constexpr float kQJerk = 0.2f; // target jerk PSD, (m/s^2)^2/s + constexpr float kDt = 0.5f; // s + constexpr float kAccUav = 1.2f; // m/s^2 + + vte::KF_position filter; + setFilterState(filter, + makeStateMoving(kInitPosRel, kInitVelUav, kInitBias, kInitAccTarget, kInitVelTarget), + makeDiagMoving(0.f, 0.f, 0.f, 0.f, 0.f)); // zero prior, so cov(after) == Q + filter.setInputVar(0.f); + filter.setBiasVar(0.f); + filter.setTargetAccVar(kQJerk); + + filter.predict(kDt, kAccUav); + + // Reference state: moving-target discrete prediction model + // r_{k+1} = r - dt * (v_uav - v_target) - 0.5 * dt^2 * (acc_uav - acc_target) + // v_uav_{k+1} = v_uav + dt * acc_uav + // v_target_{k+1} = v_target + dt * acc_target + // acc_target, b unchanged + const float dt2 = kDt * kDt; + const float dt3 = dt2 * kDt; + const float dt4 = dt2 * dt2; + const float dt5 = dt4 * kDt; + const float expected_pos_rel = kInitPosRel + - kDt * (kInitVelUav - kInitVelTarget) + - 0.5f * dt2 * (kAccUav - kInitAccTarget); + const float expected_vel_uav = kInitVelUav + kDt * kAccUav; + const float expected_vel_target = kInitVelTarget + kDt * kInitAccTarget; + const float expected_acc_target = kInitAccTarget; + const float expected_bias = kInitBias; + + const StateVec state = filter.getState(); + EXPECT_NEAR(state(vtest::State::pos_rel), expected_pos_rel, kTolerance); + EXPECT_NEAR(state(vtest::State::vel_uav), expected_vel_uav, kTolerance); + EXPECT_NEAR(state(vtest::State::bias), expected_bias, kTolerance); + EXPECT_NEAR(state(vtest::State::acc_target), expected_acc_target, kTolerance); + EXPECT_NEAR(state(vtest::State::vel_target), expected_vel_target, kTolerance); + + // Reference Q from continuous white jerk on acc_target, integrated through the + // constant-jerk model. Prior cov is zero, so cov(after predict) == Q exactly. + // Q[r, r] = q * dt^5 / 20 + // Q[r, v_target] = q * dt^4 / 8 + // Q[r, acc_target] = q * dt^3 / 6 + // Q[v_target, v_target] = q * dt^3 / 3 + // Q[v_target, acc_target] = q * dt^2 / 2 + // Q[acc_target,acc_target]= q * dt + const float expected_q_r_r = kQJerk * dt5 / 20.f; + const float expected_q_r_vt = kQJerk * dt4 / 8.f; + const float expected_q_r_at = kQJerk * dt3 / 6.f; + const float expected_q_vt_vt = kQJerk * dt3 / 3.f; + const float expected_q_vt_at = kQJerk * dt2 / 2.f; + const float expected_q_at_at = kQJerk * kDt; + + const StateCov cov = filter.getStateCovariance(); + EXPECT_NEAR(cov(vtest::State::pos_rel, vtest::State::pos_rel), expected_q_r_r, kTolerance); + EXPECT_NEAR(cov(vtest::State::pos_rel, vtest::State::vel_target), expected_q_r_vt, kTolerance); + EXPECT_NEAR(cov(vtest::State::pos_rel, vtest::State::acc_target), expected_q_r_at, kTolerance); + EXPECT_NEAR(cov(vtest::State::vel_target, vtest::State::vel_target), expected_q_vt_vt, kTolerance); + EXPECT_NEAR(cov(vtest::State::vel_target, vtest::State::acc_target), expected_q_vt_at, kTolerance); + EXPECT_NEAR(cov(vtest::State::acc_target, vtest::State::acc_target), expected_q_at_at, kTolerance); + expectSymmetric(cov); +} + +// WHY: Moving mode shares the same continuous white-UAV-acceleration model as +// static mode. Confirms the larger state vector does not perturb the +// (pos_rel, vel_uav) Q block, and that the target sub-block stays at zero +// when only UAV-input noise is active. +// WHAT: Predict one step with only UAV-input PSD enabled (bias and jerk PSDs +// zeroed). cov(pos_rel, vel_uav) must match the static-mode integrated Q; +// cov(acc_target, acc_target) and cov(vel_target, vel_target) must be zero. +TEST(KFPositionTest, PredictMovingTargetAddsUavInputNoise) +{ + constexpr float kQAcc = 0.4f; // UAV-acceleration PSD, m^2/s^3 + constexpr float kDt = 0.5f; + + vte::KF_position filter; + setFilterState(filter, + makeStateMoving(0.f, 0.f, 0.f, 0.f, 0.f), + makeDiagMoving(0.f, 0.f, 0.f, 0.f, 0.f)); // zero prior, so cov(after) == Q + filter.setInputVar(kQAcc); + filter.setBiasVar(0.f); + filter.setTargetAccVar(0.f); + + filter.predict(kDt, 0.f); + + // Reference Q from continuous white UAV-acceleration noise (same closed-form + // block as in the static test): + // Q[r, r] = q * dt^3 / 3 + // Q[r, v_uav] = -q * dt^2 / 2 + // Q[v_uav, v_uav] = q * dt + // Target sub-block must remain identically zero because no jerk noise was injected. + const float dt2 = kDt * kDt; + const float dt3 = dt2 * kDt; + const float expected_q_r_r = kQAcc * dt3 / 3.f; + const float expected_q_r_v = -kQAcc * dt2 / 2.f; + const float expected_q_v_v = kQAcc * kDt; + + const StateCov cov = filter.getStateCovariance(); + EXPECT_NEAR(cov(vtest::State::pos_rel, vtest::State::pos_rel), expected_q_r_r, kTolerance); + EXPECT_NEAR(cov(vtest::State::pos_rel, vtest::State::vel_uav), expected_q_r_v, kTolerance); + EXPECT_NEAR(cov(vtest::State::vel_uav, vtest::State::pos_rel), expected_q_r_v, kTolerance); + EXPECT_NEAR(cov(vtest::State::vel_uav, vtest::State::vel_uav), expected_q_v_v, kTolerance); + EXPECT_NEAR(cov(vtest::State::acc_target, vtest::State::acc_target), 0.f, kTolerance); + EXPECT_NEAR(cov(vtest::State::vel_target, vtest::State::vel_target), 0.f, kTolerance); + expectSymmetric(cov); +} +#endif // defined(CONFIG_VTEST_MOVING) diff --git a/src/modules/vision_target_estimator/test/TEST_VTE_VisionTargetEst.cpp b/src/modules/vision_target_estimator/test/TEST_VTE_VisionTargetEst.cpp new file mode 100644 index 00000000000..06043abaf06 --- /dev/null +++ b/src/modules/vision_target_estimator/test/TEST_VTE_VisionTargetEst.cpp @@ -0,0 +1,1040 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file TEST_VTE_VisionTargetEst.cpp + * @brief Unit test VisionTargetEst.cpp + * + * @author Jonas Perolini + * + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_MODULES_VISION_TARGET_ESTIMATOR) && CONFIG_MODULES_VISION_TARGET_ESTIMATOR +#include +#endif // CONFIG_MODULES_VISION_TARGET_ESTIMATOR +#include +#include + +#include "VTETestHelper.hpp" +#include "VisionTargetEst.h" +#include "../../navigator/navigation.h" + +namespace vte = vision_target_estimator; + +namespace +{ +using namespace time_literals; + +static constexpr float kTolerance = 1e-4f; +static constexpr float kGravity = 9.80665f; +static constexpr hrt_abstime kStepUs = 1_ms; + +void expectVectorNear(const matrix::Vector3f &actual, const matrix::Vector3f &expected) +{ + EXPECT_NEAR(actual(0), expected(0), kTolerance); + EXPECT_NEAR(actual(1), expected(1), kTolerance); + EXPECT_NEAR(actual(2), expected(2), kTolerance); +} + +void expectVectorArrayNear(const float *actual, const matrix::Vector3f &expected) +{ + EXPECT_NEAR(actual[0], expected(0), kTolerance); + EXPECT_NEAR(actual[1], expected(1), kTolerance); + EXPECT_NEAR(actual[2], expected(2), kTolerance); +} + +void expectQuaternionArrayNear(const float *actual, const matrix::Quaternionf &expected) +{ + EXPECT_NEAR(actual[0], expected(0), kTolerance); + EXPECT_NEAR(actual[1], expected(1), kTolerance); + EXPECT_NEAR(actual[2], expected(2), kTolerance); + EXPECT_NEAR(actual[3], expected(3), kTolerance); +} + +position_setpoint_triplet_s makePositionSetpointTriplet(hrt_abstime timestamp, uint8_t current_type, uint8_t next_type) +{ + position_setpoint_triplet_s triplet{}; + triplet.timestamp = timestamp; + triplet.current.type = current_type; + triplet.next.type = next_type; + return triplet; +} + +navigator_mission_item_s makeNavigatorMissionItem(hrt_abstime timestamp, uint16_t nav_cmd, + float lat, float lon, float alt, bool altitude_is_relative = false) +{ + navigator_mission_item_s mission_item{}; + mission_item.timestamp = timestamp; + mission_item.nav_cmd = nav_cmd; + mission_item.latitude = lat; + mission_item.longitude = lon; + mission_item.altitude = alt; + mission_item.altitude_is_relative = altitude_is_relative; + return mission_item; +} + +} // namespace + +class VisionTargetEstTestable : public vte::VisionTargetEst +{ +public: + using vte::VisionTargetEst::_acc_sample_count; + using vte::VisionTargetEst::_current_task_ptr; + using vte::VisionTargetEst::_gps_pos_is_offset; + using vte::VisionTargetEst::_gps_pos_offset_xyz; + using vte::VisionTargetEst::_last_acc_reset; + using vte::VisionTargetEst::_last_update_pos; + using vte::VisionTargetEst::_orientation_estimator_running; + using vte::VisionTargetEst::_prec_land_task; + using vte::VisionTargetEst::_vte_orientation; + using vte::VisionTargetEst::_position_estimator_running; + using vte::VisionTargetEst::_vehicle_acc_body; + using vte::VisionTargetEst::_vehicle_acc_ned_sum; + using vte::VisionTargetEst::_vehicle_acceleration_sub; + using vte::VisionTargetEst::_vehicle_angular_velocity_sub; + using vte::VisionTargetEst::_vehicle_attitude_sub; + using vte::VisionTargetEst::_vehicle_gps_position_sub; + using vte::VisionTargetEst::_vehicle_local_position_sub; + using vte::VisionTargetEst::_vte_orientation_enabled; + using vte::VisionTargetEst::_vte_position; + using vte::VisionTargetEst::_vte_position_enabled; + using vte::VisionTargetEst::_vte_task_mask; + using vte::VisionTargetEst::adjustAidMask; + using vte::VisionTargetEst::computeGpsVelocityOffset; + using vte::VisionTargetEst::isCurrentTaskComplete; + using vte::VisionTargetEst::restartTimedOutEstimators; + using vte::VisionTargetEst::setNewTaskIfAvailable; + using vte::VisionTargetEst::kAccUpdatedTimeoutUs; + using vte::VisionTargetEst::kMinAccDownsampleTimeoutUs; + using vte::VisionTargetEst::kPosUpdatePeriodUs; + using vte::VisionTargetEst::kYawUpdatePeriodUs; + using vte::VisionTargetEst::pollEstimatorInput; + using vte::VisionTargetEst::publishVteInput; + using vte::VisionTargetEst::startPosEst; + using vte::VisionTargetEst::startYawEst; + using vte::VisionTargetEst::stopPosEst; + using vte::VisionTargetEst::stopYawEst; + using vte::VisionTargetEst::updateGpsAntennaOffset; + using vte::VisionTargetEst::updateEstimators; + using vte::VisionTargetEst::updateParams; + using vte::VisionTargetEst::updateTaskTopics; + using vte::VisionTargetEst::updateWhenIntervalElapsed; + + void clearCurrentTask() { _current_task_ptr = nullptr; } + void setCurrentTaskToPrecLand() { _current_task_ptr = &_prec_land_task; } + bool isCurrentTaskPrecLand() const { return _current_task_ptr == &_prec_land_task; } + + const position_setpoint_s *findLandSetpoint() { return _prec_land_task.findLandSetpoint(); } + const position_setpoint_s *currentTripletLandSetpoint() { return &_prec_land_task._pos_sp_triplet_buffer.current; } + const position_setpoint_s *nextTripletLandSetpoint() { return &_prec_land_task._pos_sp_triplet_buffer.next; } + + void resetPrecLandMissionSetpoint() { _prec_land_task.resetMissionSetpoint(); } + bool updatePrecLandMissionSetpoint() { return _prec_land_task.updateMissionSetpoint(); } + const position_setpoint_s &precLandMissionSetpoint() const { return _prec_land_task._cached_mission_setpoint; } + + void setPrecLandActive(bool active) { _prec_land_task._is_in_prec_land = active; } + bool isPrecLandActive() const { return _prec_land_task._is_in_prec_land; } +}; + +class VisionTargetEstTest : public ::testing::Test +{ +protected: + static void SetUpTestSuite() { uORB::Manager::initialize(); } + + void SetUp() override + { + param_control_autosave(false); + vte_test::useFakeTime(); + + setParamInt("VTE_POS_EN", 1); + setParamInt("VTE_YAW_EN", 1); + setParamInt("VTE_TASK_MASK", 0); + setParamInt("VTE_AID_MASK", 0); + setParamFloat("VTE_BTOUT", 3.f); + setParamFloat("VTE_TGT_TOUT", 2.f); + setParamFloat("VTE_M_REC_TOUT", 1.f); + setParamFloat("VTE_M_UPD_TOUT", 0.1f); + + _vte = std::make_unique(); + + _attitude_pub = std::make_unique>(ORB_ID(vehicle_attitude)); + _accel_pub = std::make_unique>(ORB_ID(vehicle_acceleration)); + _ang_vel_pub = std::make_unique>(ORB_ID(vehicle_angular_velocity)); + _uav_gps_pub = std::make_unique>(ORB_ID(vehicle_gps_position)); + _home_position_pub = std::make_unique>(ORB_ID(home_position)); + _navigator_mission_item_pub = std::make_unique>(ORB_ID(navigator_mission_item)); + _pos_sp_triplet_pub = std::make_unique>(ORB_ID(position_setpoint_triplet)); + _land_detected_pub = std::make_unique>(ORB_ID(vehicle_land_detected)); +#if !defined(CONSTRAINED_FLASH) + _prec_land_status_pub = std::make_unique>(ORB_ID(prec_land_status)); +#endif + + _vte_input_sub = std::make_unique>(ORB_ID(vte_input)); + + flushInternalSubscriptions(); + vte_test::flushSubscription(_vte_input_sub); + } + + void TearDown() override + { + _param_guard.restore(); + param_control_autosave(true); + + _vte_input_sub.reset(); +#if !defined(CONSTRAINED_FLASH) + _prec_land_status_pub.reset(); +#endif + _land_detected_pub.reset(); + _pos_sp_triplet_pub.reset(); + _navigator_mission_item_pub.reset(); + _home_position_pub.reset(); + _uav_gps_pub.reset(); + _ang_vel_pub.reset(); + _accel_pub.reset(); + _attitude_pub.reset(); + + _vte.reset(); + vte_test::useRealTime(); + } + + void setParamFloat(const char *name, float value) + { + ASSERT_TRUE(_param_guard.setFloat(name, value)); + } + + void setParamInt(const char *name, int32_t value) + { + ASSERT_TRUE(_param_guard.setInt(name, value)); + } + + void publishAttitude(const matrix::Quaternionf &q, hrt_abstime timestamp) + { + vehicle_attitude_s msg{}; + msg.timestamp = timestamp; + q.copyTo(msg.q); + ASSERT_TRUE(_attitude_pub->publish(msg)); + } + + void publishAcceleration(const matrix::Vector3f &accel, hrt_abstime timestamp) + { + vehicle_acceleration_s msg{}; + msg.timestamp = timestamp; + msg.xyz[0] = accel(0); + msg.xyz[1] = accel(1); + msg.xyz[2] = accel(2); + ASSERT_TRUE(_accel_pub->publish(msg)); + } + + void publishAngularVelocity(const matrix::Vector3f &ang_vel, hrt_abstime timestamp) + { + vehicle_angular_velocity_s msg{}; + msg.timestamp = timestamp; + msg.xyz[0] = ang_vel(0); + msg.xyz[1] = ang_vel(1); + msg.xyz[2] = ang_vel(2); + ASSERT_TRUE(_ang_vel_pub->publish(msg)); + } + + void publishUavGps(const matrix::Vector3f &antenna_offset, hrt_abstime timestamp) + { + ASSERT_TRUE(vte_test::publishUavGps(*_uav_gps_pub, 47.0, 8.0, 500.f, 0.5f, 0.5f, + matrix::Vector3f{}, 0.1f, true, timestamp, antenna_offset)); + } + + void publishHomePosition(float alt_amsl, hrt_abstime timestamp) + { + home_position_s msg{}; + msg.timestamp = timestamp; + msg.alt = alt_amsl; + ASSERT_TRUE(_home_position_pub->publish(msg)); + } + + void publishNavigatorMissionItem(const navigator_mission_item_s &mission_item) + { + ASSERT_TRUE(_navigator_mission_item_pub->publish(mission_item)); + } + + void publishLandDetected(bool landed, hrt_abstime timestamp) + { + vehicle_land_detected_s msg{}; + msg.timestamp = timestamp; + msg.landed = landed; + ASSERT_TRUE(_land_detected_pub->publish(msg)); + } + + void publishPositionSetpointTriplet(const position_setpoint_triplet_s &triplet) + { + ASSERT_TRUE(_pos_sp_triplet_pub->publish(triplet)); + } + +#if !defined(CONSTRAINED_FLASH) + void publishPrecLandStatus(uint8_t state, hrt_abstime timestamp) + { + prec_land_status_s msg{}; + msg.timestamp = timestamp; + msg.state = state; + ASSERT_TRUE(_prec_land_status_pub->publish(msg)); + } +#endif + + void flushInternalSubscriptions() + { + vte_test::flushSubscription(_vte->_vehicle_attitude_sub); + vte_test::flushSubscription(_vte->_vehicle_acceleration_sub); + vte_test::flushSubscription(_vte->_vehicle_angular_velocity_sub); + vte_test::flushSubscription(_vte->_vehicle_gps_position_sub); + vte_test::flushSubscription(_vte->_vehicle_local_position_sub); + vte_test::flushSubscription(_vte->_prec_land_task._home_position_sub); + vte_test::flushSubscription(_vte->_prec_land_task._navigator_mission_item_sub); + vte_test::flushSubscription(_vte->_prec_land_task._pos_sp_triplet_sub); + vte_test::flushSubscription(_vte->_prec_land_task._vehicle_land_detected_sub); +#if !defined(CONSTRAINED_FLASH) + vte_test::flushSubscription(_vte->_prec_land_task._prec_land_status_sub); +#endif + } + + std::unique_ptr _vte; + std::unique_ptr> _attitude_pub; + std::unique_ptr> _accel_pub; + std::unique_ptr> _ang_vel_pub; + std::unique_ptr> _uav_gps_pub; + std::unique_ptr> _home_position_pub; + std::unique_ptr> _navigator_mission_item_pub; + std::unique_ptr> _pos_sp_triplet_pub; + std::unique_ptr> _land_detected_pub; +#if !defined(CONSTRAINED_FLASH) + std::unique_ptr> _prec_land_status_pub; +#endif + + std::unique_ptr> _vte_input_sub; + + vte_test::ParamGuard _param_guard{}; +}; + +// WHY: If there is a GNSS on the target, do not use the mission position +// WHAT: Enable mission position and GNSS on target, expect GNSS on target only +TEST_F(VisionTargetEstTest, AdjustAidMaskResolvesConflicts) +{ + // GIVEN: Mission position and target GNSS aiding are both enabled. + vte::SensorFusionMaskU mask{}; + mask.flags.use_target_gps_pos = 1; + mask.flags.use_mission_pos = 1; + + // WHEN: The aid mask is sanitized. + const uint16_t adjusted = _vte->adjustAidMask(mask.value); + vte::SensorFusionMaskU adjusted_mask{}; + adjusted_mask.value = adjusted; + + // THEN: Mission position aiding is dropped in favor of target GNSS. + EXPECT_TRUE(adjusted_mask.flags.use_target_gps_pos); + EXPECT_FALSE(adjusted_mask.flags.use_mission_pos); +} + +#if defined(CONFIG_VTEST_MOVING) +// WHY: Moving-target builds cannot use a static mission landing point as a target position source. +// WHAT: Enable mission-position aiding by itself and expect adjustAidMask() to clear it. +TEST_F(VisionTargetEstTest, AdjustAidMaskDisablesMissionPositionForMovingTarget) +{ + vte::SensorFusionMaskU mask{}; + mask.flags.use_mission_pos = 1; + + vte::SensorFusionMaskU adjusted_mask{}; + adjusted_mask.value = _vte->adjustAidMask(mask.value); + + EXPECT_FALSE(adjusted_mask.flags.use_mission_pos); +} +#endif + +// WHY: The active GPS antenna offset comes from vehicle_gps_position +// WHAT: Publish non-zero then zero antenna offsets and verify the cached lever arm tracks the topic output. +TEST_F(VisionTargetEstTest, UpdateGpsAntennaOffsetTracksVehicleGpsPosition) +{ + // GIVEN: The vehicle GPS topic reports a non-zero antenna lever arm. + const matrix::Vector3f gps_offset_gt{0.2, -0.015, 3.1}; + publishUavGps(gps_offset_gt, vte_test::advanceMicroseconds(kStepUs)); + + // WHEN: The module refreshes the cached GPS antenna offset. + ASSERT_TRUE(_vte->updateGpsAntennaOffset()); + + // THEN: The cached lever arm matches the published GPS offset. + EXPECT_TRUE(_vte->_gps_pos_is_offset); + expectVectorNear(_vte->_gps_pos_offset_xyz, gps_offset_gt); + + // GIVEN: The next GPS sample reports no antenna offset. + publishUavGps(matrix::Vector3f{}, vte_test::advanceMicroseconds(kStepUs)); + + // WHEN: The offset cache is refreshed again. + ASSERT_TRUE(_vte->updateGpsAntennaOffset()); + + // THEN: The cached lever arm is cleared. + EXPECT_FALSE(_vte->_gps_pos_is_offset); + expectVectorNear(_vte->_gps_pos_offset_xyz, matrix::Vector3f{}); +} + +// WHY: Compensate for the rotational velocity if the GNSS antenna is not at the center of mass, +// i.e. when the drone rotates around the center of mass, the GNSS will record a velocity. +// WHAT: Expect false without config/data, then true once angular velocity is published. +TEST_F(VisionTargetEstTest, ComputeGpsVelocityOffsetRequiresOffsetAndData) +{ + // GIVEN: No lever arm or angular velocity samples are available yet. + matrix::Vector3f vel_offset{}; + + // WHEN: The velocity compensation is computed without prerequisites. + EXPECT_FALSE(_vte->computeGpsVelocityOffset(vel_offset)); + + // GIVEN: A GPS antenna lever arm is configured, but angular velocity is still missing. + const matrix::Vector3f gps_offset(1.f, 0.f, 0.f); + _vte->_gps_pos_is_offset = true; + _vte->_gps_pos_offset_xyz = gps_offset; + + // WHEN: The compensation is computed again without gyro data. + EXPECT_FALSE(_vte->computeGpsVelocityOffset(vel_offset)); + + // GIVEN: Angular velocity data is now available. + const matrix::Vector3f ang_vel(0.f, 0.f, 1.f); + publishAngularVelocity(ang_vel, vte_test::advanceMicroseconds(kStepUs)); + + // WHEN: The velocity compensation is recomputed with all required inputs. + EXPECT_TRUE(_vte->computeGpsVelocityOffset(vel_offset)); + const matrix::Vector3f expected_offset = ang_vel.cross(gps_offset); + + // THEN: The offset matches the rigid-body cross product. + expectVectorNear(vel_offset, expected_offset); +} + +// WHY: Attitude is required to transform body-frame data into NED. +// WHAT: Call pollEstimatorInput without attitude and expect it to fail. +TEST_F(VisionTargetEstTest, PollEstimatorInputRequiresAttitude) +{ + // GIVEN: No vehicle attitude sample has been published. + matrix::Vector3f acc_ned{}; + matrix::Quaternionf q_att{}; + matrix::Vector3f gps_offset{}; + matrix::Vector3f vel_offset{}; + const bool vel_offset_updated = true; + bool acc_valid = true; + + // WHEN: The estimator input is polled. + EXPECT_FALSE(_vte->pollEstimatorInput(acc_ned, q_att, gps_offset, vel_offset, + vel_offset_updated, acc_valid)); +} + +// WHY: Valid inputs should be rotated into NED and include gravity compensation. +// WHAT: Publish attitude/accel with offsets and verify transformed outputs. +TEST_F(VisionTargetEstTest, PollEstimatorInputTransformsAccelerationAndOffsets) +{ + // GIVEN: Attitude, acceleration, and GPS lever-arm data are all available. + const hrt_abstime timestamp = vte_test::nowUs(); + matrix::Quaternionf q{0.f, 0.f, 0.f, 1.f}; // 180 degrees rotation around z-axis + const matrix::Vector3f non_rotated_vec{1.f, 2.f, 3.f}; + const matrix::Vector3f rotated_vec{-1.f, -2.f, 3.f}; + + publishAttitude(q, timestamp); + publishAcceleration(non_rotated_vec, timestamp); + + _vte->_gps_pos_is_offset = true; + _vte->_gps_pos_offset_xyz = non_rotated_vec; + + matrix::Vector3f acc_ned{}; + matrix::Quaternionf q_att{}; + matrix::Vector3f gps_offset = non_rotated_vec; + matrix::Vector3f vel_offset = non_rotated_vec; + const bool vel_offset_updated = true; + bool acc_valid = false; + + // WHEN: The estimator input is polled. + ASSERT_TRUE(_vte->pollEstimatorInput(acc_ned, q_att, gps_offset, vel_offset, + vel_offset_updated, acc_valid)); + + // THEN: Acceleration and offset vectors are rotated into NED. + EXPECT_TRUE(acc_valid); + expectVectorNear(acc_ned, matrix::Vector3f(rotated_vec(0), rotated_vec(1), rotated_vec(2) + kGravity)); + expectVectorNear(gps_offset, rotated_vec); + expectVectorNear(vel_offset, rotated_vec); +} + +// WHY: With GPS offset disabled, offset vectors must be zeroed. +// WHAT: Disable offset and verify returned GNSS/velocity offsets are zero. +TEST_F(VisionTargetEstTest, PollEstimatorInputNoOffsetZerosVectors) +{ + // GIVEN: Attitude and acceleration are present, but GPS offset compensation is disabled. + const hrt_abstime timestamp = vte_test::nowUs(); + publishAttitude(vte_test::identityQuat(), timestamp); + publishAcceleration(matrix::Vector3f(0.1f, 0.2f, 0.3f), timestamp); + + _vte->_gps_pos_is_offset = false; + _vte->_gps_pos_offset_xyz = matrix::Vector3f(1.f, 2.f, 3.f); + + matrix::Vector3f acc_ned{}; + matrix::Quaternionf q_att{}; + matrix::Vector3f gps_offset{}; + matrix::Vector3f vel_offset(4.f, 5.f, 6.f); + const bool vel_offset_updated = true; + bool acc_valid = false; + + // WHEN: The estimator input is polled. + ASSERT_TRUE(_vte->pollEstimatorInput(acc_ned, q_att, gps_offset, vel_offset, + vel_offset_updated, acc_valid)); + + // THEN: Offset vectors are zeroed even if stale values were passed in. + EXPECT_TRUE(acc_valid); + expectVectorNear(gps_offset, matrix::Vector3f{}); + expectVectorNear(vel_offset, matrix::Vector3f{}); +} + +// WHY: Published inputs must reflect the sampled accel and attitude data. +// WHAT: Populate sample timestamp and verify the published message fields. +TEST_F(VisionTargetEstTest, PublishVteInputPopulatesMessage) +{ + // GIVEN: A sampled acceleration timestamp and estimator inputs are prepared. + const hrt_abstime sample_time = vte_test::nowUs(); + _vte->_vehicle_acc_body.timestamp = sample_time; + + const matrix::Vector3f acc_ned(0.5f, -0.25f, 9.0f); + const matrix::Quaternionf q_att = vte_test::identityQuat(); + const uint32_t sample_count = 4; + + // WHEN: The vision target estimator input topic is published. + _vte->publishVteInput(acc_ned, q_att, sample_count); + + // THEN: The published message mirrors the sampled timestamp and data payload. + ASSERT_TRUE(_vte_input_sub->update()); + const auto msg = _vte_input_sub->get(); + + EXPECT_EQ(msg.timestamp_sample, sample_time); + expectVectorArrayNear(msg.acc_xyz, acc_ned); + expectQuaternionArrayNear(msg.q_att, q_att); + EXPECT_EQ(msg.acc_sample_count, sample_count); +} + +// WHY: The update gate should only allow execution after the interval elapses. +// WHAT: Expect false before the interval and true after waiting. +TEST_F(VisionTargetEstTest, UpdateWhenIntervalElapsedRespectsInterval) +{ + // GIVEN: An interval and a timestamp from the current simulated time. + const hrt_abstime interval = 10_ms; + hrt_abstime last_time = vte_test::nowUs(); + + // WHEN: The interval has not elapsed yet. + EXPECT_FALSE(_vte->updateWhenIntervalElapsed(last_time, interval)); + + // GIVEN: The last update time is moved far enough into the past. + last_time = vte_test::nowUs() - interval - 1_ms; + + // WHEN: The interval check runs again. + // THEN: The update is allowed. + EXPECT_TRUE(_vte->updateWhenIntervalElapsed(last_time, interval)); +} + +// WHY: The triplet fallback must ignore stale land types on invalid setpoints. +// WHAT: Publish invalid then valid land setpoints and verify only valid entries are selected. +TEST_F(VisionTargetEstTest, FindLandSetpointRequiresValidSetpoint) +{ + // GIVEN: No setpoint triplet has been published yet. + EXPECT_EQ(_vte->findLandSetpoint(), nullptr); + + // GIVEN: The current setpoint is marked as land but invalid. + position_setpoint_triplet_s triplet = makePositionSetpointTriplet( + vte_test::advanceMicroseconds(kStepUs), + position_setpoint_s::SETPOINT_TYPE_LAND, + position_setpoint_s::SETPOINT_TYPE_IDLE); + triplet.current.valid = false; + publishPositionSetpointTriplet(triplet); + + // WHEN: The active land setpoint is queried. + // THEN: Invalid land entries are ignored. + EXPECT_EQ(_vte->findLandSetpoint(), nullptr); + + // GIVEN: The current setpoint is a valid land setpoint. + triplet.current.valid = true; + triplet.current.lat = 47.1; + triplet.current.lon = 8.2; + triplet.current.alt = 520.f; + publishPositionSetpointTriplet(triplet); + + // WHEN: The active land setpoint is queried. + const position_setpoint_s *current_sp = _vte->findLandSetpoint(); + + // THEN: The current setpoint is returned. + ASSERT_NE(current_sp, nullptr); + EXPECT_EQ(current_sp, _vte->currentTripletLandSetpoint()); + + // GIVEN: The next setpoint is now the land setpoint. + triplet = makePositionSetpointTriplet( + vte_test::advanceMicroseconds(kStepUs), + position_setpoint_s::SETPOINT_TYPE_IDLE, + position_setpoint_s::SETPOINT_TYPE_LAND); + triplet.current.valid = false; + triplet.next.valid = true; + triplet.next.lat = 47.2; + triplet.next.lon = 8.3; + triplet.next.alt = 530.f; + publishPositionSetpointTriplet(triplet); + + // WHEN: The land setpoint is queried again. + const position_setpoint_s *next_sp = _vte->findLandSetpoint(); + + // THEN: The next setpoint is selected and remains cached for repeated reads. + ASSERT_NE(next_sp, nullptr); + EXPECT_EQ(next_sp, _vte->nextTripletLandSetpoint()); + + const position_setpoint_s *cached_sp = _vte->findLandSetpoint(); + ASSERT_NE(cached_sp, nullptr); + EXPECT_EQ(cached_sp, _vte->nextTripletLandSetpoint()); +} + +// WHY: Precision landing needs a stable mission waypoint even after precland mutates the live triplet. +// WHAT: Cache the navigator mission land item, then verify task start keeps using it after the triplet changes. +TEST_F(VisionTargetEstTest, StartPosEstUsesCachedNavigatorMissionLandSetpoint) +{ + // GIVEN: A precision-land task with a stable navigator mission land item and a mutable triplet. + _vte->_vte_position_enabled = true; + _vte->setCurrentTaskToPrecLand(); + _vte->resetPrecLandMissionSetpoint(); + + const hrt_abstime timestamp = vte_test::advanceMicroseconds(kStepUs); + publishHomePosition(500.f, timestamp); + publishNavigatorMissionItem(makeNavigatorMissionItem(timestamp, NAV_CMD_LAND, 47.1f, 8.2f, 15.f, true)); + + position_setpoint_triplet_s triplet = makePositionSetpointTriplet(timestamp, + position_setpoint_s::SETPOINT_TYPE_POSITION, + position_setpoint_s::SETPOINT_TYPE_IDLE); + triplet.current.valid = true; + triplet.current.lat = 47.9; + triplet.current.lon = 8.9; + triplet.current.alt = 650.f; + publishPositionSetpointTriplet(triplet); + + // WHEN: The position estimator starts for precision landing. + ASSERT_TRUE(_vte->startPosEst()); + + // THEN: The cached mission waypoint is used instead of the rewritten triplet. + EXPECT_TRUE(_vte->precLandMissionSetpoint().valid); + EXPECT_NEAR(_vte->precLandMissionSetpoint().lat, 47.1, kTolerance); + EXPECT_NEAR(_vte->precLandMissionSetpoint().lon, 8.2, kTolerance); + EXPECT_NEAR(_vte->precLandMissionSetpoint().alt, 515.f, kTolerance); +} + +// WHY: The mission controller can expose the upcoming landing point in triplet.next before the current logical mission item becomes LAND. +// WHAT: Publish a non-land navigator mission item with a valid next land setpoint and verify VTE still caches the upcoming landing waypoint. +TEST_F(VisionTargetEstTest, UpdatePrecLandMissionSetpointFallsBackToNextLandSetpoint) +{ + // GIVEN: The current logical mission item is not LAND yet, but the next triplet setpoint already is. + _vte->resetPrecLandMissionSetpoint(); + + const hrt_abstime timestamp = vte_test::advanceMicroseconds(kStepUs); + publishNavigatorMissionItem(makeNavigatorMissionItem(timestamp, NAV_CMD_WAYPOINT, 47.0f, 8.0f, 540.f)); + + position_setpoint_triplet_s triplet = makePositionSetpointTriplet(timestamp, + position_setpoint_s::SETPOINT_TYPE_POSITION, + position_setpoint_s::SETPOINT_TYPE_LAND); + triplet.current.valid = true; + triplet.current.lat = 47.0; + triplet.current.lon = 8.0; + triplet.current.alt = 540.f; + triplet.next.valid = true; + triplet.next.lat = 47.5; + triplet.next.lon = 8.5; + triplet.next.alt = 520.f; + publishPositionSetpointTriplet(triplet); + + // WHEN: The precision-land mission setpoint is updated. + ASSERT_TRUE(_vte->updatePrecLandMissionSetpoint()); + + // THEN: The upcoming LAND setpoint from triplet.next is cached. + EXPECT_TRUE(_vte->precLandMissionSetpoint().valid); + EXPECT_NEAR(_vte->precLandMissionSetpoint().lat, triplet.next.lat, kTolerance); + EXPECT_NEAR(_vte->precLandMissionSetpoint().lon, triplet.next.lon, kTolerance); + EXPECT_NEAR(_vte->precLandMissionSetpoint().alt, triplet.next.alt, kTolerance); +} + +// WHY: Internal estimator restarts during the same precision-land task must not switch to precland's dynamic triplet. +// WHAT: Start once from navigator mission data, mutate the triplet to a different land point, then restart and verify the cached point stays fixed. +TEST_F(VisionTargetEstTest, StartPosEstKeepsCachedMissionLandSetpointAcrossRestart) +{ + // GIVEN: Precision landing already cached the original mission land setpoint. + _vte->_vte_position_enabled = true; + _vte->setCurrentTaskToPrecLand(); + _vte->resetPrecLandMissionSetpoint(); + + const hrt_abstime timestamp = vte_test::advanceMicroseconds(kStepUs); + publishNavigatorMissionItem(makeNavigatorMissionItem(timestamp, NAV_CMD_LAND, 47.3f, 8.4f, 530.f)); + ASSERT_TRUE(_vte->startPosEst()); + + const position_setpoint_s cached_setpoint = _vte->precLandMissionSetpoint(); + + // GIVEN: Precland later rewrites the current triplet to another land position. + position_setpoint_triplet_s triplet = makePositionSetpointTriplet(vte_test::advanceMicroseconds(kStepUs), + position_setpoint_s::SETPOINT_TYPE_LAND, + position_setpoint_s::SETPOINT_TYPE_IDLE); + triplet.current.valid = true; + triplet.current.lat = 48.0; + triplet.current.lon = 9.0; + triplet.current.alt = 700.f; + publishPositionSetpointTriplet(triplet); + + // WHEN: The estimator is stopped and restarted within the same task. + _vte->stopPosEst(); + ASSERT_TRUE(_vte->startPosEst()); + + // THEN: The original mission land point is reused instead of the rewritten triplet. + EXPECT_NEAR(_vte->precLandMissionSetpoint().lat, cached_setpoint.lat, kTolerance); + EXPECT_NEAR(_vte->precLandMissionSetpoint().lon, cached_setpoint.lon, kTolerance); + EXPECT_NEAR(_vte->precLandMissionSetpoint().alt, cached_setpoint.alt, kTolerance); +} + +// WHY: Precision landing tasks should start once requested and complete on land detect. +// WHAT: Request the task, then publish land detected and verify completion. +TEST_F(VisionTargetEstTest, PrecisionLandTaskRequestAndCompletion) +{ + // GIVEN: Precision landing is enabled and currently active. + _vte->_vte_task_mask = vte::task_bits::kPrecLand; + _vte->clearCurrentTask(); + _vte->setPrecLandActive(true); + + // WHEN: Task availability is checked. + EXPECT_TRUE(_vte->setNewTaskIfAvailable()); + + // THEN: The precision landing task becomes current. + EXPECT_TRUE(_vte->isCurrentTaskPrecLand()); + + // GIVEN: Land detection reports touchdown. + publishLandDetected(true, vte_test::advanceMicroseconds(kStepUs)); + + // WHEN: Task completion is checked. + // THEN: The task completes and precision landing state is cleared. + EXPECT_TRUE(_vte->isCurrentTaskComplete()); + EXPECT_FALSE(_vte->isPrecLandActive()); +} + +#if !defined(CONSTRAINED_FLASH) +// WHY: Precision landing status topics should drive internal task state. +// WHAT: Publish ongoing and stopped states and verify the internal flag toggles. +TEST_F(VisionTargetEstTest, UpdateTaskTopicsTracksPrecisionLandState) +{ + // GIVEN: Precision landing task tracking is enabled. + _vte->_vte_task_mask = vte::task_bits::kPrecLand; + _vte->setPrecLandActive(false); + + // WHEN: The precision landing status reports an active state. + publishPrecLandStatus(prec_land_status_s::PREC_LAND_STATE_HORIZONTAL, vte_test::advanceMicroseconds(kStepUs)); + _vte->updateTaskTopics(); + + // THEN: Internal task state reflects an active precision landing sequence. + EXPECT_TRUE(_vte->isPrecLandActive()); + + // WHEN: The precision landing status reports that it has stopped. + publishPrecLandStatus(prec_land_status_s::PREC_LAND_STATE_STOPPED, vte_test::advanceMicroseconds(kStepUs)); + _vte->updateTaskTopics(); + + // THEN: The internal precision landing state is cleared. + EXPECT_FALSE(_vte->isPrecLandActive()); +} +#endif + +// WHY: The acceleration downsample must reset after timeout to avoid stale averages. +// WHAT: Force a timeout and verify the accumulator resets before admitting new samples. +TEST_F(VisionTargetEstTest, UpdateEstimatorsForcesDownsampleResetAfterTimeout) +{ + // GIVEN: The downsample accumulator already contains stale acceleration data. + _vte->_vte_position_enabled = true; + _vte->_position_estimator_running = true; + _vte->_acc_sample_count = 3; + _vte->_vehicle_acc_ned_sum = matrix::Vector3f(50.f, 60.f, 70.f); + + const hrt_abstime now = vte_test::nowUs(); + const hrt_abstime acc_downsample_timeout = VisionTargetEstTestable::kMinAccDownsampleTimeoutUs; + _vte->_last_acc_reset = now - (acc_downsample_timeout + 1_ms); + _vte->_last_update_pos = now; // prevent the position update from firing this cycle + + // WHEN: A cycle runs with a fresh sample but a stale accumulator timer. + // Identity attitude: acc_ned = acc_body + (0, 0, g). + publishAttitude(vte_test::identityQuat(), now); + publishAcceleration(matrix::Vector3f(1.f, 2.f, 3.f - kGravity), now); + _vte->updateEstimators(); + + // THEN: The accumulator is reset and restarted from the new sample. + EXPECT_EQ(_vte->_acc_sample_count, 1u); + expectVectorNear(_vte->_vehicle_acc_ned_sum, matrix::Vector3f(1.f, 2.f, 3.f)); +} + +// WHY: The averaged acceleration must reflect the mean of collected samples. +// WHAT: Feed multiple samples, trigger an update, and verify the published mean. +TEST_F(VisionTargetEstTest, UpdateEstimatorsAveragesAccSamples) +{ + // GIVEN: A running position estimator with a clean accumulator. + _vte->_vte_position_enabled = true; + _vte->_position_estimator_running = true; + _vte->_vehicle_acc_ned_sum.setAll(0.f); + _vte->_acc_sample_count = 0; + + const hrt_abstime t0 = vte_test::nowUs(); + _vte->_last_acc_reset = t0; + _vte->_last_update_pos = t0; + + // WHEN: Two samples arrive before the publish interval elapses. + // Identity attitude: acc_ned = acc_body + (0, 0, g). + publishAttitude(vte_test::identityQuat(), t0); + publishAcceleration(matrix::Vector3f(1.f, 2.f, 3.f - kGravity), t0); + _vte->updateEstimators(); + + vte_test::advanceMicroseconds(1_ms); + const hrt_abstime t1 = vte_test::nowUs(); + publishAttitude(vte_test::identityQuat(), t1); + publishAcceleration(matrix::Vector3f(3.f, 4.f, 5.f - kGravity), t1); + _vte->updateEstimators(); + + // THEN: The accumulator stores the running sum. + EXPECT_EQ(_vte->_acc_sample_count, 2u); + const matrix::Vector3f expected_sum(1.f + 3.f, 2.f + 4.f, 3.f + 5.f); + expectVectorNear(_vte->_vehicle_acc_ned_sum, expected_sum); + + // WHEN: A third sample arrives after the publish interval has elapsed. + vte_test::advanceMicroseconds(VisionTargetEstTestable::kPosUpdatePeriodUs + 1_ms); + const hrt_abstime t2 = vte_test::nowUs(); + publishAttitude(vte_test::identityQuat(), t2); + publishAcceleration(matrix::Vector3f(2.f, 6.f, 1.f - kGravity), t2); + _vte->updateEstimators(); + + // THEN: The published acceleration is the mean of all collected samples. + ASSERT_TRUE(_vte_input_sub->update()); + const auto msg = _vte_input_sub->get(); + const matrix::Vector3f mean_acc((1.f + 3.f + 2.f) / 3.f, + (2.f + 4.f + 6.f) / 3.f, + (3.f + 5.f + 1.f) / 3.f); + expectVectorArrayNear(msg.acc_xyz, mean_acc); + + EXPECT_EQ(_vte->_acc_sample_count, 0u); +} + +// WHY: A stopped estimator should be available again as soon as the task needs it. +// WHAT: Start, stop, and verify restart is immediate. +TEST_F(VisionTargetEstTest, StartEstimatorsRestartImmediatelyAfterStop) +{ + // GIVEN: Both estimators are enabled. + _vte->_vte_position_enabled = true; + _vte->_vte_orientation_enabled = true; + _vte->_current_task_ptr = nullptr; + + // WHEN: The estimators are started, stopped, and restarted immediately. + EXPECT_TRUE(_vte->startPosEst()); + EXPECT_TRUE(_vte->startYawEst()); + + _vte->stopPosEst(); + _vte->stopYawEst(); + + // THEN: Both estimators can start again without a guard delay. + EXPECT_TRUE(_vte->startPosEst()); + EXPECT_TRUE(_vte->startYawEst()); +} + +// WHY: Disabling the aid mask at runtime should stop any estimator that no longer has inputs. +// WHAT: Mark both estimators running, then clear VTE_AID_MASK and verify they are stopped. +TEST_F(VisionTargetEstTest, UpdateParamsStopsRunningEstimatorsWhenFusionDisabled) +{ + // GIVEN: Both estimators are running with a non-zero aid mask. + _vte->_vte_position_enabled = true; + _vte->_vte_orientation_enabled = true; + _vte->_position_estimator_running = true; + _vte->_orientation_estimator_running = true; + + vte::SensorFusionMaskU aid_mask{}; + aid_mask.flags.use_vision_pos = 1; + setParamInt("VTE_AID_MASK", aid_mask.value); + _vte->updateParams(); + + // THEN: The estimators remain running while valid fusion input is configured. + EXPECT_TRUE(_vte->_position_estimator_running); + EXPECT_TRUE(_vte->_orientation_estimator_running); + + // WHEN: Fusion input is disabled at runtime. + setParamInt("VTE_AID_MASK", 0); + _vte->updateParams(); + + // THEN: Both estimators stop. + EXPECT_FALSE(_vte->_position_estimator_running); + EXPECT_FALSE(_vte->_orientation_estimator_running); +} + +// WHY: Changing the frequency of the filter has consequences. +// If the period is changed, the OOSM windows: +// OOSMManager _oosm; +// OOSMManager _oosm; +// must be updated accordingly. +// Other constants such as kAccUpdatedTimeoutUs or kMinAccDownsampleTimeoutUs +// WHAT: Create a test that fails is the filter's period is changed. +TEST_F(VisionTargetEstTest, EstimatorUpdatePeriod) +{ + // THEN: The expected estimator timing constants stay in sync. + ASSERT_EQ(VisionTargetEstTestable::kPosUpdatePeriodUs, 20_ms); + ASSERT_EQ(VisionTargetEstTestable::kYawUpdatePeriodUs, 20_ms); + EXPECT_EQ(vte::kOosmMinTimeUs, VisionTargetEstTestable::kPosUpdatePeriodUs); + EXPECT_EQ(vte::kOosmMaxTimeUs, 500_ms); + EXPECT_EQ(vte::kOosmHistorySize, 25); + EXPECT_LT(VisionTargetEstTestable::kAccUpdatedTimeoutUs, VisionTargetEstTestable::kMinAccDownsampleTimeoutUs); +} + +// WHY: Timeout detection must reset a running estimator without imposing a restart delay. +// WHAT: Initialize, force a timeout, and verify timeout handling re-arms the estimator immediately. +TEST_F(VisionTargetEstTest, RestartTimedOutEstimatorsRearmsPositionEstimatorImmediately) +{ + // GIVEN: A running position estimator with fresh vision input. + _vte->_vte_position_enabled = true; + _vte->_position_estimator_running = true; + _vte->_orientation_estimator_running = false; + + ASSERT_TRUE(_vte->_vte_position.init()); + vte::SensorFusionMaskU aid_mask{}; + aid_mask.flags.use_vision_pos = 1; + _vte->_vte_position.setVteAidMask(aid_mask.value); + + const hrt_abstime timestamp = vte_test::nowUs(); + _vte->_vte_position.setLocalVelocity(matrix::Vector3f{}, true, timestamp); + + uORB::Publication vision_pub{ORB_ID(fiducial_marker_pos_report)}; + ASSERT_TRUE(vte_test::publishVisionPos( + vision_pub, matrix::Vector3f(1.f, 0.f, -1.f), vte_test::identityQuat(), + matrix::Vector3f(0.01f, 0.01f, 0.01f), timestamp)); + + // WHEN: The estimator times out after receiving an initial update. + _vte->_vte_position.update(matrix::Vector3f{0.f, 0.f, 0.f}); + _vte->_vte_position.setVteTimeout(1_ms); + + vte_test::advanceMicroseconds(2_ms); + + // THEN: Timeout handling resets and re-arms the position estimator in the same call. + ASSERT_TRUE(_vte->_vte_position.timedOut()); + _vte->restartTimedOutEstimators(); + EXPECT_TRUE(_vte->_position_estimator_running); + EXPECT_FALSE(_vte->_vte_position.timedOut()); +} + +// WHY: Timeout detection must reset a running yaw estimator without imposing a restart delay. +// WHAT: Initialize, force a timeout, and verify timeout handling re-arms the estimator immediately. +TEST_F(VisionTargetEstTest, RestartTimedOutEstimatorsRearmsOrientationEstimatorImmediately) +{ + // GIVEN: A running orientation estimator with fresh yaw input. + _vte->_vte_orientation_enabled = true; + _vte->_orientation_estimator_running = true; + _vte->_position_estimator_running = false; + + ASSERT_TRUE(_vte->_vte_orientation.init()); + vte::SensorFusionMaskU aid_mask{}; + aid_mask.flags.use_vision_pos = 1; + _vte->_vte_orientation.setVteAidMask(aid_mask.value); + + const hrt_abstime timestamp = vte_test::nowUs(); + uORB::Publication vision_yaw_pub{ORB_ID(fiducial_marker_yaw_report)}; + ASSERT_TRUE(vte_test::publishVisionYaw(vision_yaw_pub, 0.2f, 0.01f, timestamp)); + + // WHEN: The estimator times out after receiving an initial update. + _vte->_vte_orientation.update(); + _vte->_vte_orientation.setVteTimeout(1_ms); + + vte_test::advanceMicroseconds(2_ms); + + // THEN: Timeout handling resets and re-arms the orientation estimator in the same call. + ASSERT_TRUE(_vte->_vte_orientation.timedOut()); + _vte->restartTimedOutEstimators(); + EXPECT_TRUE(_vte->_orientation_estimator_running); + EXPECT_FALSE(_vte->_vte_orientation.timedOut()); +} + +// WHY: Estimator updates should tolerate missing local pose data. +// WHAT: Provide attitude and acceleration only and ensure update proceeds. +TEST_F(VisionTargetEstTest, UpdateEstimatorsHandlesMissingLocalPose) +{ + // GIVEN: Position estimation is running with attitude and acceleration data only. + _vte->_vte_position_enabled = true; + _vte->_position_estimator_running = true; + + const hrt_abstime timestamp = vte_test::nowUs(); + publishAttitude(vte_test::identityQuat(), timestamp); + publishAcceleration(matrix::Vector3f(0.1f, -0.2f, 9.5f), timestamp); + + _vte->_last_update_pos = timestamp - (VisionTargetEstTestable::kPosUpdatePeriodUs + 1_ms); + _vte->_last_acc_reset = timestamp; + + // WHEN: The estimators are updated without local pose input. + _vte->updateEstimators(); + + // THEN: A new estimator input message is still published. + ASSERT_TRUE(_vte_input_sub->update()); +} + +// WHY: Stale acceleration must not be mixed into the downsample accumulator. +// WHAT: Publish stale accel data and verify the accumulator does not grow. +TEST_F(VisionTargetEstTest, UpdateEstimatorsDropsStaleAcceleration) +{ + // GIVEN: The estimator is running with a fresh accumulator. + _vte->_vte_position_enabled = true; + _vte->_position_estimator_running = true; + _vte->_acc_sample_count = 0; + _vte->_vehicle_acc_ned_sum.setAll(0.f); + _vte->_last_acc_reset = vte_test::nowUs(); + + const hrt_abstime timestamp = vte_test::nowUs(); + publishAttitude(vte_test::identityQuat(), timestamp); + + const hrt_abstime stale_timestamp = + timestamp - (VisionTargetEstTestable::kAccUpdatedTimeoutUs + 1_ms); + publishAcceleration(matrix::Vector3f(0.1f, -0.2f, 9.5f), stale_timestamp); + + // WHEN: Estimator updates run with stale acceleration input. + _vte->updateEstimators(); + + // THEN: Stale samples are not accumulated. + EXPECT_EQ(_vte->_acc_sample_count, 0u); + expectVectorNear(_vte->_vehicle_acc_ned_sum, matrix::Vector3f{}); +} diff --git a/src/modules/vision_target_estimator/test/VTETestHelper.hpp b/src/modules/vision_target_estimator/test/VTETestHelper.hpp new file mode 100644 index 00000000000..94a8a8da19c --- /dev/null +++ b/src/modules/vision_target_estimator/test/VTETestHelper.hpp @@ -0,0 +1,308 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file VTETestHelper.hpp + * @brief Helper functions for Vision Target Estimator unit tests + * + * @author Jonas Perolini + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../common.h" + +namespace vte_test +{ +using namespace time_literals; + +class ParamGuard +{ +public: + ParamGuard() = default; + ~ParamGuard() { restore(); } + + bool setFloat(const char *name, float value) + { + param_t handle = param_find(name); + + if (handle == PARAM_INVALID) { + return false; + } + + if (param_type(handle) != PARAM_TYPE_FLOAT) { + return false; + } + + if (!storeOriginal(handle)) { + return false; + } + + return param_set(handle, &value) == 0; + } + + bool setInt(const char *name, int32_t value) + { + param_t handle = param_find(name); + + if (handle == PARAM_INVALID) { + return false; + } + + if (param_type(handle) != PARAM_TYPE_INT32) { + return false; + } + + if (!storeOriginal(handle)) { + return false; + } + + return param_set(handle, &value) == 0; + } + + void restore() + { + for (auto it = _entries.rbegin(); it != _entries.rend(); ++it) { + if (it->type == PARAM_TYPE_FLOAT) { + (void)param_set(it->handle, &it->value.f); + + } else if (it->type == PARAM_TYPE_INT32) { + (void)param_set(it->handle, &it->value.i); + } + } + + _entries.clear(); + } + +private: + struct ParamEntry { + param_t handle{PARAM_INVALID}; + param_type_t type{PARAM_TYPE_INT32}; + + union { + float f; + int32_t i; + } value{}; + }; + + std::vector _entries{}; + + bool storeOriginal(param_t handle) + { + for (const auto &entry : _entries) { + if (entry.handle == handle) { + return true; + } + } + + ParamEntry entry{}; + entry.handle = handle; + entry.type = param_type(handle); + + if (entry.type == PARAM_TYPE_FLOAT) { + if (param_get(handle, &entry.value.f) != 0) { + return false; + } + + } else if (entry.type == PARAM_TYPE_INT32) { + if (param_get(handle, &entry.value.i) != 0) { + return false; + } + + } else { + return false; + } + + _entries.push_back(entry); + return true; + } +}; + +inline matrix::Quaternionf identityQuat() +{ + matrix::Quaternionf q{1.f, 0.f, 0.f, 0.f}; + return q; +} + +template +void flushSubscription(Subscription &sub) +{ + while (sub.update()) {} +} + +template +void flushSubscription(std::unique_ptr &sub) +{ + if (!sub) { + return; + } + + while (sub->update()) {} +} + +template +void flushSubscription(Subscription &sub) +{ + Msg msg{}; + + while (sub.update(&msg)) {} +} + +inline hrt_abstime &testClockNowStorage() +{ + // Start past VTE's fixed restart/warn windows so zero timestamps + // behave the same way they do on a real monotonic clock. + static hrt_abstime now_us = 30_s; + return now_us; +} + +inline hrt_abstime testClockNow() +{ + return testClockNowStorage(); +} + +inline void useFakeTime(hrt_abstime start_time_us = 30_s) +{ + testClockNowStorage() = start_time_us; + vision_target_estimator::TimeSourceProvider::setTimeSourceForTest(testClockNow); +} + +inline void useRealTime() +{ + vision_target_estimator::TimeSourceProvider::resetTimeSourceForTest(); +} + +inline hrt_abstime advanceMicroseconds(hrt_abstime delta_us) +{ + testClockNowStorage() += delta_us; + return testClockNowStorage(); +} + +inline hrt_abstime nowUs() +{ + return testClockNowStorage(); +} + +inline bool publishVisionYaw(uORB::Publication &pub, + float yaw, float yaw_var, hrt_abstime timestamp) +{ + fiducial_marker_yaw_report_s msg{}; + msg.timestamp = timestamp; + msg.timestamp_sample = timestamp; + msg.yaw_ned = yaw; + msg.yaw_var_ned = yaw_var; + return pub.publish(msg); +} + +inline bool publishVisionPos(uORB::Publication &pub, + const matrix::Vector3f &rel_pos, const matrix::Quaternionf &q, + const matrix::Vector3f &cov, hrt_abstime timestamp) +{ + fiducial_marker_pos_report_s msg{}; + msg.timestamp = timestamp; + msg.timestamp_sample = timestamp; + msg.rel_pos[0] = rel_pos(0); + msg.rel_pos[1] = rel_pos(1); + msg.rel_pos[2] = rel_pos(2); + msg.cov_rel_pos[0] = cov(0); + msg.cov_rel_pos[1] = cov(1); + msg.cov_rel_pos[2] = cov(2); + q.copyTo(msg.q); + return pub.publish(msg); +} + +inline bool publishUavGps(uORB::Publication &pub, double lat, double lon, float alt, + float eph, float epv, const matrix::Vector3f &vel_ned, float vel_var, + bool vel_valid, hrt_abstime timestamp, + const matrix::Vector3f &antenna_offset = matrix::Vector3f{}) +{ + sensor_gps_s msg{}; + msg.timestamp = timestamp; + msg.timestamp_sample = timestamp; + msg.latitude_deg = static_cast(lat); + msg.longitude_deg = static_cast(lon); + msg.altitude_msl_m = static_cast(alt); + msg.eph = eph; + msg.epv = epv; + msg.vel_n_m_s = vel_ned(0); + msg.vel_e_m_s = vel_ned(1); + msg.vel_d_m_s = vel_ned(2); + msg.s_variance_m_s = vel_var; + msg.vel_ned_valid = vel_valid; + msg.antenna_offset_x = antenna_offset(0); + msg.antenna_offset_y = antenna_offset(1); + msg.antenna_offset_z = antenna_offset(2); + return pub.publish(msg); +} + +inline bool publishTargetGnss(uORB::Publication &pub, double lat, double lon, float alt, + float eph, float epv, hrt_abstime timestamp, bool abs_pos_updated, + bool vel_ned_updated = false, const matrix::Vector3f &vel_ned = matrix::Vector3f{}, + float vel_acc = NAN) +{ + target_gnss_s msg{}; + msg.timestamp = timestamp; + msg.timestamp_sample = timestamp; + msg.latitude_deg = static_cast(lat); + msg.longitude_deg = static_cast(lon); + msg.altitude_msl_m = static_cast(alt); + msg.eph = eph; + msg.epv = epv; + msg.abs_pos_updated = abs_pos_updated; + msg.vel_ned_updated = vel_ned_updated; + msg.vel_n_m_s = vel_ned(0); + msg.vel_e_m_s = vel_ned(1); + msg.vel_d_m_s = vel_ned(2); + msg.s_acc_m_s = vel_acc; + return pub.publish(msg); +} + +} // namespace vte_test diff --git a/src/modules/vision_target_estimator/vision_target_estimator_params.yaml b/src/modules/vision_target_estimator/vision_target_estimator_params.yaml new file mode 100644 index 00000000000..311d7e61cdd --- /dev/null +++ b/src/modules/vision_target_estimator/vision_target_estimator_params.yaml @@ -0,0 +1,348 @@ +module_name: vision_target_estimator +parameters: +- group: Vision Target Estimator + definitions: + VTE_EN: + description: + short: Vision Target Estimator module enable + type: boolean + default: 1 + reboot_required: true + VTE_YAW_EN: + description: + short: Vision Target Estimator module enable orientation estimation + type: boolean + default: 0 + reboot_required: true + VTE_POS_EN: + description: + short: Vision Target Estimator module enable position estimation + type: boolean + default: 1 + reboot_required: true + VTE_AID_MASK: + description: + short: Integer bitmask controlling data fusion and aiding methods + long: |- + Set bits in the following positions to enable: + 0 : Set to true to use the target's GNSS position data if available. (+1) + 1 : Set to true to use the UAV GNSS velocity data if available. (+2) + 2 : Set to true to use the target relative position from vision-based data if available. (+4) + 3 : Set to true to use the mission land point. Ignored if target GNSS position enabled. (+8) + 4 : Set to true to use the target GNSS velocity if available. (+16) + type: bitmask + bit: + 0: target GNSS position + 1: UAV GNSS velocity + 2: vision relative position + 3: mission position + 4: target GNSS velocity + default: 14 + VTE_TASK_MASK: + description: + short: Integer bitmask controlling the tasks of the target estimator + long: |- + Set bits in the following positions to enable: + 0 : Set to true to use the vision target estimator for precision landing. (+1) + 1 : DEBUG, always active. (+2) + type: bitmask + bit: + 0: precision landing + 1: DEBUG, always active + default: 1 + VTE_BTOUT: + description: + short: Vision target timeout + long: Time after which the target is considered lost without any new fused measurements. When this timeout expires, the estimator is reset and can restart immediately once an enabled fusion source is available. + type: float + default: 3.0 + unit: s + min: 0.0 + max: 50 + decimal: 1 + increment: 0.5 + VTE_TGT_TOUT: + description: + short: Target validity timeout + long: Maximum time without any fused measurements before the published relative pose/yaw is flagged invalid. + type: float + default: 2.0 + unit: s + min: 0.0 + max: 50 + decimal: 2 + increment: 0.25 + VTE_M_REC_TOUT: + description: + short: Measurement recent timeout + long: Time window for considering a raw measurement as recent and eligible for fusion. + type: float + default: 1.0 + unit: s + min: 0.0 + max: 10 + decimal: 2 + increment: 0.05 + VTE_M_UPD_TOUT: + description: + short: Measurement updated timeout + long: Maximum allowed age of a retained measurement before it is discarded from the estimator's cache. + type: float + default: 0.1 + unit: s + min: 0.0 + max: 5 + decimal: 3 + increment: 0.01 + VTE_ACC_D_UNC: + description: + short: UAV acceleration white-noise power spectral density + long: |- + White-noise PSD on the UAV acceleration input. The + 1-sigma vel_uav change allowed over a time t is sqrt(VTE_ACC_D_UNC * t). + + This is a variance rate, not a per-step variance; the value is independent + of the filter update rate. Higher values let the filter follow new + measurements more tightly and reject fewer outliers. + + Unit: m^2/s^3. + type: float + default: 0.02 + min: 0.0001 + decimal: 4 + VTE_ACC_T_UNC: + description: + short: Target acceleration random-walk process noise + long: |- + Process-noise spectral density of the target acceleration random walk + (moving-target builds only). The 1-sigma target-acceleration change over a + time t is sqrt(VTE_ACC_T_UNC * t) (e.g. for the 0.1 default, ~0.32 m/s^2 + after 1 s, ~1.0 m/s^2 after 10 s). + + This is a variance rate, not a linear rate of change; the value is + independent of the filter update rate. Higher values let the filter follow + target manoeuvres more aggressively and accept more outliers. + + Unit: ((m/s^2)^2)/s. + type: float + default: 0.1 + min: 0.01 + decimal: 2 + VTE_BIAS_UNC: + description: + short: Bias random-walk process noise + long: |- + Process-noise spectral density of the GPS/vision bias random walk. The + 1-sigma expected bias change over a time t is sqrt(VTE_BIAS_UNC * t) (e.g. + for the 0.001 default, ~3 cm after 1 s, ~10 cm after 10 s, ~32 cm after + 100 s). + + This is a variance rate, not a linear drift rate; the value is independent + of the filter update rate. Higher values let the bias follow new + observations more aggressively; lower values keep it stiff. Tune to match + the realistic physical drift of the absolute reference (typically a few + centimetres over tens of seconds for consumer GNSS, less for RTK). + + Unit: m^2/s. + type: float + default: 0.001 + min: 0.0001 + decimal: 4 + VTE_POS_UNC_IN: + description: + short: Initial target and drone relative position uncertainty + long: |- + Initial variance of the relative target position in x, y, and z direction. + Changes while the estimator is running are picked up immediately by the module but only take effect + the next time the estimator initializes or resets. + type: float + default: 0.5 + unit: m^2 + min: 0.001 + decimal: 3 + VTE_VEL_UNC_IN: + description: + short: Initial target and drone relative velocity uncertainty + long: |- + Initial variance of the relative target velocity in x, y, and z directions. + Changes while the estimator is running are picked up immediately by the module but only take effect + the next time the estimator initializes or resets. + type: float + default: 0.5 + unit: (m/s)^2 + min: 0.001 + decimal: 3 + VTE_BIA_UNC_IN: + description: + short: Initial GPS bias uncertainty + long: |- + Initial variance of the bias between the GPS on the target and the GPS on the drone. + Changes while the estimator is running are picked up immediately by the module but only take effect + the next time the estimator initializes or resets. + Once the filter is running, the steady-state bias variance is governed by VTE_BIAS_UNC + and the measurement updates, so this parameter does not influence runtime behaviour. + Keep it large so initialization can absorb initial misalignments. + type: float + default: 1.0 + unit: m^2 + min: 0.001 + decimal: 3 + VTE_BIA_AVG_THR: + description: + short: Initial GNSS/vision bias averaging threshold + long: |- + When the GNSS/vision bias first becomes observable while the estimator is still referenced to GNSS, + VTE low-pass filters the first GNSS/vision bias samples before activating the bias estimate. + The LPF exit requires consecutive raw bias samples to stay within this threshold and for the LPF + to have run for at least 2 * tau, or until VTE_BIA_AVG_TOUT elapses. + type: float + default: 0.3 + unit: m + min: 0.0 + decimal: 2 + VTE_BIA_AVG_TOUT: + description: + short: Initial GNSS/vision bias averaging timeout + long: |- + Maximum time spent averaging the initial GNSS bias before activating it once GNSS and vision + are jointly observable while the estimator is still referenced to GNSS. During that phase, valid + vision samples keep updating the LPF. While the current GNSS-relative measurement stays valid, + it can be propagated with the UAV velocity estimate to match the vision timestamp. If that GNSS + sample is no longer valid, averaging stops, the current vision position is used, and the current + LPF bias is activated. + + Set to 0 to disable averaging and activate the bias immediately. + type: float + default: 1.0 + unit: s + min: 0.0 + decimal: 2 + VTE_YAW_UNC_IN: + description: + short: Initial orientation uncertainty + long: |- + Initial variance of the target orientation yaw in rad^2. + Changes while the estimator is running are picked up immediately by the module but only take effect + the next time the estimator initializes or resets. + type: float + default: 1.0 + min: 0.001 + decimal: 3 + VTE_YAW_ACC_UNC: + description: + short: Yaw acceleration white-noise power spectral density + long: |- + White-noise PSD on the yaw acceleration driving the + yaw-rate state. The 1-sigma yaw-rate change allowed over a time t is + sqrt(VTE_YAW_ACC_UNC * t) (e.g. for the 0.004 default, ~3.6 deg/s after 1 s, + ~11.5 deg/s after 10 s). + + This is a variance rate, not a per-step variance; the value is independent + of the filter update rate. Higher values let the filter follow rapid + heading changes; lower values smooth the yaw estimate aggressively. + + Unit: rad^2/s^3. + type: float + default: 0.004 + min: 0.0 + decimal: 4 + VTE_ACC_UNC_IN: + description: + short: Initial target absolute acceleration uncertainty + long: |- + Initial variance of the relative target acceleration in x, y, and z directions + (moving-target builds only). + Changes while the estimator is running are picked up immediately by the module but only take effect + the next time the estimator initializes or resets. + Once the filter is running, the steady-state target-acceleration variance is + governed by VTE_ACC_T_UNC and the measurement updates, so this parameter does + not influence runtime behaviour. + type: float + default: 0.1 + unit: (m/s^2)^2 + min: 0.001 + decimal: 3 + VTE_GPS_V_NOISE: + description: + short: Minimum standard deviation for GPS velocity observations + long: |- + Lower bound on the standard deviation used when fusing GPS velocity. The + estimator squares this value and clamps the per-sample observation variance + to max(reported_variance, VTE_GPS_V_NOISE^2). The floor only takes effect when + the sensor under-reports its own noise; if the reported variance is already + above the floor, this parameter has no effect. + type: float + default: 0.3 + unit: m/s + min: 0.01 + max: 5.0 + decimal: 2 + VTE_GPS_P_NOISE: + description: + short: Minimum standard deviation for GPS position observations + long: |- + Lower bound on the standard deviation used when fusing GPS position (target or + mission landing waypoint). The estimator squares this value and clamps the + per-sample observation variance to max(reported_variance, VTE_GPS_P_NOISE^2). + The floor only takes effect when the sensor under-reports its own noise. + type: float + default: 0.5 + unit: m + min: 0.01 + max: 10.0 + decimal: 2 + VTE_EVA_NOISE: + description: + short: Minimum standard deviation for vision yaw observations + long: |- + Lower bound on the standard deviation used when fusing the vision yaw + observation. The estimator squares this value and clamps the per-sample + observation variance to max(reported_variance, VTE_EVA_NOISE^2). The floor only + takes effect when the sensor under-reports its own noise. + The default of ~0.07 rad (4 deg) is a reasonable starting point for marker-based + yaw detection. Lowering it makes the filter trust each yaw sample more, which + can cause the controller to chase the resulting setpoint changes and oscillate. + type: float + default: 0.07 + min: 0.05 + unit: rad + decimal: 2 + VTE_EVP_NOISE: + description: + short: Minimum standard deviation for vision relative-position observations + long: |- + Lower bound on the standard deviation used when fusing the vision relative + position. The estimator squares this value and clamps the per-sample + observation variance to max(reported_variance, VTE_EVP_NOISE^2). The floor only + takes effect when the sensor under-reports its own noise. + type: float + default: 0.1 + min: 0.01 + unit: m + decimal: 2 + VTE_POS_NIS_THRE: + description: + short: Normalized innovation squared threshold for the position estimator + long: |- + Lower values mean that more measurements will be rejected. Null hypothesis H0: the innovation is + consistent with the innovation covariance matrix. Values of 0.46, 1.64, 2.71, 3.84, 6.63, and 10.83 + correspond to 50%, 20%, 10%, 5%, 1%, and 0.1% probability respectively that H0 is incorrectly rejected. + The confidence interval is computed from the chi-squared distribution. + type: float + default: 3.84 + min: 0.46 + max: 10.83 + decimal: 2 + VTE_YAW_NIS_THRE: + description: + short: Normalized innovation squared threshold for the orientation estimator + long: |- + Lower values mean that more measurements will be rejected. Null hypothesis H0: the innovation is + consistent with the innovation covariance matrix. Values of 0.46, 1.64, 2.71, 3.84, 6.63, and 10.83 + correspond to 50%, 20%, 10%, 5%, 1%, and 0.1% probability respectively that H0 is incorrectly rejected. + The confidence interval is computed from the chi-squared distribution. + type: float + default: 3.84 + min: 0.46 + max: 10.83 + decimal: 2

~?Kh`NM!G_wEyy zKYV}fy11HP2r}i%sTS;Yys3Gy^~%i|B(gPW@^{9lLpM*V;D2Xx=3C-%(Y_=Vm_=fl zKe>uSf|Rn}1B)mPU{V9EVwEfBO0RgX>h6{BXScsa;$r2Dz@l-Y&*Y!}6;>izUVbie zpvbtikBcu?@8_NSh$KYua2Tla6{F(V&C9G_i{BF^&4Fs8=UYRGk}RQ{)Za;#0M{-- z1D?MnX2{UBxvQ>0<8DjGVr>px9Hp+bodpG>PxP1`Xral6-ig=gVi0bds zEgC}rb7O*{_zeMRi=6%2i1Q)%b8dDO@L%Z<$aXbWLphr4?c1mUZLKP=s#P&_b|JVb z2++Odn~;N8mzZ!qfA5E3HwcuiT26VefOgw4uQS{uJ1;p2RR9lCc*?o;gfunsLr`;p z(d8(yBBCNa=x_iPa7d8eDh>^DrV`#%S57N4mf!D|)FDJF<6mxXHvrJB-kVM=jrexX zxpIR%p-4JHC5TjGJu=|K%kEb9T@eikCA-T3r>0Dms|Y4*b`_;t`^mbciP9hI)}*1g zn~C#Zb0&q)ejBp`5z{v}UNMj9vb0$ABsC6ZGx&QlzEd8J)o^XF{7TgHnJXd`SX>Er zxVCbwU?1S4DGlNC<-5}5^#p7TEAzLo6`d3uIiPX^n<96W4C4)ldvyr;*w*O!Z9b;P z>Lqq742M zQ*%_KN{n=>Cn?6R>B|Q!aE|pw5$+_-N@X^yClTC-H?G4ZW1QsMA^fE& zmUBT|pEhK!g3h0(fcbC8AYgnn^X(UQ&5j z&cUF5tF4_1MP+17kBQNdxd~#-uXWqxM!%X^)oI~Jt2r&VdR+0Hdj{k)`2HPc9hxhm zW9$UQsQPTCN6Me6HH>jEZerXz&96nUYS*Y)99KOZ&MBd`$o@+F{^B=M8>BLGk9U@1 zY8sDJ`uW*B2~riM|AX0)MwrUpTo<|#GYh-Px=j-!Wi>T74tq~CIy!nP&?oW2s^nhL z*x`i_am^eYS07y7Q2pFK7xboC4c#>40Cm&J|UyJ0S=%raX2(O0S%P zZZo2yYE&w;(F@4~QsKLubyce!P|4fa$AUZ7FSYh+p3^&9!v~0ij?(suYMkLT^lCN! zj9-KZBtYP`qGeq*Vx#p|nD=+-gbhv)_Qkkp0gv_8*cTH-^&^K4wY8v{C`Vc?657OWj-rb`~J#XK0oh4Zc#?e5v80sz#3F9rKBrY_q`v~?m9$^hr;jRr+cKw z*GCgE4%Yp~KX#{XxNHbojI}A(KwY?MCxVqkvrvuLoN- zGA8*$HA_{2L}aGUHyRd+axlCx()^ zxLXZI#^d9fATMe07OQF_Yw5%7yViMmh%ofq0yZzt)XwaN_<7^ z9#1WgBx=F}22f`{+SoYWO=_7x9Y*LAXH0-feVAppD47oB?KVt*Ncy4eKC=`(;i}o%h|CMYt}G5Ni;Eo2_k#;FN#6J9CiXAp;u)Wp z2+5g@f0lN~Z(n;q^8q;(80*=8PVVq_%oo{|Aj^2g6@qGzR5=4K<$@;B15-0}y*2Pl zDG{B_ST;WS5sx%fz+dy74z`9*pHe$GD65g01tX@wjM^3F6Ko|(smzRGQdgHcEk&vy z0JklkzgPS&6oSWOimcVPbB2a+5JKEJjH?p#GhObCo&IudZFchXKwQU`3@tvGG$U&`%97A;#qc2iodz%+VCYoGzicua?TG z|3(;r#Ac6^Q#7Vu*6o!mGV~A`=;H_vE%Is~!Ae&m+^^31l2x?SxlZYf0`A*m zdDNJ$kPb2j3hv+x%zZ88TV2&2i0sVdZVe_)65LliE*`#HKXrkYsmswfUj3bqoJVvd zGKLi28am!C62sQ`3LJ|0UPrI8L zCGMQRdj0h!z5Z(RZd~_-Kf2g+NttD?!V(oz9>1AXCgk^BR!*t1%rf@9%Itflh2ys!%}~i z0DBrJhho2AEDHb%*2ci}p$+psRBorF)i8~~=eATVTu z_V?}`W5hfnb1G~7N8qrBw+DIXFk+#(!uPy32`3+yO6tjUJa5o>$ zwedL+Hd2=jr_W}eo0Ngl`Hr?jU|qM1E&0YCLXsUi-4?>2L~Q1%rqcHx%hp69f;*FT zahsHlX2wtn5=4pe8Y#bVvMhBjPpl9-_+vV&l*9AD{+-3Kvj>O6hZY{BmQ`K;BUeVS zI#YL`4^+Evg~5Gsj`g~3vkVwjR#UvJqXtMm4mN=pp!eDHV)+B>Vdi9` zCnFT#{@u{wJM;u0pLBLZht(u#VjZN=%hff5Vl@2)lBq*k3DgDng_7c_cq z)xP=NcfuOCKYbVb8DW@@H1yQP)I^wh2tdo+HhlB3M-K;A`m!U3(owgpS0&x_*=@F2 zj%FafMQe;cUqJ*BI^EXoWfKr?Vw}l&NM+c*%3PeMxZL+acie-N%%N;kU~bQk&b&+p z3q85c;^)x-py7SHZ$qihz+9CI#IPfSoJsfiTp53ETb!GQF*YqzET%vl_+@*3R8e0R z?ow2Jxo%wV<(p+sJR26SC{!LQol`PYq+xG8=s~B0PW!%>kJrI|yg@~_^T_K~Pc+-E zwM^1{vsD7x4N@M4C{JzXJum`{uXrQnhsl!;5u%lfz})fP_F=GbI!jmnEMc+0y`g$_ zFE#(w9JgL1vS!S4iyfmUs}4qvt!?YXPgM>}dFTk`s$c}QP*ZpEczwxjV_Igq(PcfJ z*iWIuK?gDV=6sv1I(8(F!&|xPCSJK3=xceoz=A?2Zz>r7;Yf8Jm^xR1x=sb|oG+D^4vc-x`~?)GgR~rSlnU%q=^$Y-8-*O3Q2Z&c-wJMa^h&-cdzs3 zvmK$^CvQ8xl>fGqCkK;glt`kGcp8fiO@;@KF2-X|Q4N-)`9GgIE1rAl+Ccev<@1ke z;~10wEq2o2(8N`gS@V4>{%btd_D6fmgmbz&F4`D(v}zLJNns zsIUAE;omwsI&z$7a+TyMo1ivxbyng>G>AP~Ff>(SY3(6cOHMeN$1iYDUFTkZx$g-# z@OKlMI&_jyLUHxOfk5E@CO8cIEP&&}*Fj3hFnaj}IZ=(Q%Tyc|4gJ?0J6%8W{KFpcRjYjkHi1tr5(e+v!k2U^Y-S79uP{? zQ=*FkQnmp&Y{(`-8Jnwo_nh8tjKdcwAhQ8V{0(op^%bcN_MiW zD6~PDug~S$fJc^pwYi|d;1l8_Xe8mU`*Gz{!Z8l`LD6jRrvDqk^dIRaO3oN)NB@hL z>PXlaR`8t=7mCDxg<*e-{ZH?za%e;TBm1$w^@=94pcRGN#`2ZJ8kt7dH$^{NVkF{JD{LOO-=2U zA*6bBq@dpTJkmeOB?{8)6tculbn5(Eas4 zOOO926O|A%RKmZ+4c!S-|H_rKIW+8}1>R>o2%sDg_LLc4!LQRn5SOWsheVeMTmMPc zJ7h$;^6J~mSsT~IkF%4%55@MT;Ik)=noJGEB-j)|Vat>CtJe05Rp+rIW$4G9KHQGm zXTu!l9P=Gs|0)IwE+Tb1N54g=xEwSjxDrxjyhq>0NnIi?6|Wg=D8KU$gs|+W)BAw0 z$r^n0exkq+x0ms?KDuN)ITnA(t)2LtkIERyAaAjb^@5>N*7`U+SPsDq2Fh#tZNUwn>SV&$_`9=yl<*4Y^r-6_nA{>O8j)JMO%yy2LCnM;?<`fg3ZjAM`~SFXBAc`z18Q_}O_Yg8 zyW-w%M4lxQ%g5bqW9ahE?3k4;b}3FRw4$R4%K*>KPGi_Ky3XSiRi7cbEx*URz9(0_ z*mI5MSzb*%)_CGm#bJZt)(@H3MRo*|j(B>p|B;PPsS0R|kNae1`a4Gdd+Zpo12NhI z5}=X$88Q{2rEV~brfJGl<#7kPO0`}LS|qZ_Rstraw+ikD{EB%HsZ45d+~4!rV)3}K ziv}@~s&^K;7>4Ig7jEhh_Pbx)>`!b`t0gx2i|h%DtWPE)(j*Uwm2*U_cG=Rc7Ml63 z&K|Rg4?9g-V}h%lN?dn*u3u{@R&7IWgai~=H$jF&lNhdOy=InkE{5p+Dcm*G|^qonhtkM4DWlY7-N(|>)lBO*qzQ3 zp|d??Q)>^lC*EG8V;RqO8ZQn?clJ%eHNmUi*2BCB10O%I^|;GUJ$x;4jnR4KrCue+ zdr%iUQGOuNMs@R3s%YkvT!>1`PNqh@>lR?n>hA7H^9o2(=aJ2BI15ETj?))wosGdfF z*#gh_FhF9vz}e^e!AH)X)YN(oGvkCk#n~9|H!hbUQvm4JE@B#E$UE;X9-@+wDZJCy zGg5>Dvf+*-Q4>cO4rq5EB=*dlv3uWI(p(jtD0Tq)GqSgoRw$&ogsBFCz8 za64^O?mZ8iGhNO@={#6BxC?TmssPxf=Q5eyi*}i9kYt1 zBD}=75go_=H9fLmJK}_-=tg~u?;Gf31w|Ss2EZ;=y)GEL0(IGASDoev<@vuxk z@=Y52-K4|0bJ2!XLE=bzL()ZW6YD+_I?eGYKXTTN-!-&}eGqj!DVW;H_^&br} zVPUO?JM~F2#l<^CZUf#^`}bl1Q=XSo_4WbQSD=PNfvsWtpFG^QF1uqu^((#>j#uK* zaENlFS8pS z%fHT7a&QC%Im|jdo8I(X->3bSl%%+sz$fW?LbtTDBf;S~q{-&<6`SR<*L!nkUx0Z+ z2y$ajt;WO_Cs!zxcxKTpp~3@2acfn$pr0hJ`pdkG%jF*Xt!NDaQVEh9AJ{G2m~$RILQ#8or=tNGWnunwMjdAl3e0yJeL_q= z1W8QTO7&ZBH5&|I^$QYqxR~#;xcSd7cv!~umeLak>psLcpRbc?Ypx(aAqO%P+G3n6 zRFU)95c?U@mX*}tmDbJP;_sWc`+2RQdAraQ7Ud3~g{M~PCw_px*&P3Ffjn2_eOXZ_ zIH&Xzgmn*?*uPT8ulp;4OGT%6UVIn^{wOlLvdC-I+L|PqJ1V{If@EH~+aL7^O+no5 z`*eqe*%=}enzIhG{G&}{s!8Y)K1|aB&)dc^TOV!*K9hE`+*>p+#_=^_tn^7@>5B99 zHN&XIdj}D*yEv_Y1P7XpQ?D9ty1if{U<$Yjd(w8W8*2v5aVg;mAUpQBY7R@u)icN? zxc_--H+Gv~Ows0OXVtqt-kQD5sI6>^z>>!0TV5oo_xPAZAalHH=}&d2Sb5wvmTA39 z#ElTQHkoCyH94;EA6d~X;BHxi5pT+YTgC8S>X+{Uyq|92<#4#7*0k(uJoU0DDT z;4Yq34jV&VcM6W-)8-#6tO#QolC&v74oK<+?bKH^;zts zr(2OLSa6bxZcnzi4MDSvdD|GL8i=3v(%RUXPu{`;z7_$e+C3Lbxr+;oYF;{+Kkf`zn?9;(R!*=vv76{&9hh zts%-jliiiYnwP3u%_m3~rTF0BSL*U`wzMDjR69JL`V5=M+o)CGZfIf}hRw%%@%D52 z2e$4UtQV#lc0E)o?cXR$(bmR8gKxV|JhYe^`Rdlgtb|ch+-T)4{&5IZl&nx44d$<@ zT3#KA?KoYRk$9(Hu>(V%O>y*F8U;Sou48CFFC^0g^{P~wN>u1utf<7U&Ml!!*yr$j zA8EyFy5@i}-KWdjjur(F!P1G&VP7sD5_ks8XkuPS*0-|TN>*x&a#%MQL@x?1906R? zzy~{}_UMmC;^4-QATs#wVv7xIy2`@TJQ@Ua@p1KA>Hk#X`}nnF(KcE{<_ zCMqFtXK0y_bHfK(D%4=?#U8t6>Pjc=O<(b(mNrD~P45j4;c`vZ@7cWlrHmPXqnP%}d(A{oN4YK@RA<`il*lw?m%n;0t@*ce1t4g@@DDOzGLA z##k+DtDR7O$4-KO8sUGB9h>B8PDF`Q*#hQ3L6%}_8=&yZ!uL#bf;w&Nz}oiGIn&Ym z1S=%?K>(G{k7h|*R-FR|!pZ=kcQImIB0oOzYcqREFDmScBIs7bbJJ!oI>$~@CnKSS z?(m@L^9Nwr-T?A9aq;^@d@d@n`O&KIfIGN_a^5pZq8h~1bRN&?FlVjq+x;09zKvTI!3@+!cqCnZ7c*e#wk3FI=@fHY%>%#LV&g7#2O!J8S)TheA8J-Q8|U9wKsfqP0pO@NnVJA|c2s z%EY0^US+-^GKe@es@#&Qc2!P^vs_h}sBO;;Gv&z7Xr0rEQb4L-X*$flD5!nqyc>5o z11eNYBz}%&UYksC9s%6-3)-!|hAQjNB-mbx4WplV;oLV57i=oeQ@yEKSaaQ|B9;Xx zJrTzJwl?rVeZ_Y+nld@$UjM+3vpmC8=uh(MX zBJlA0$j9vi((U{FY`ZAi4nniWBcyWsx|w<$?d4RDi`%jR9M>o8-27F{j{pi9|0Ean zK#hYG(uD1=USC~aMyBn#kjpCA|7`x6v&}=K5>M9{>mC>`&V{9;3VPvk`diX#S7ykd zD)D|6udpEtC%&6=|MPqAafq_=^N)}1;*4S*>Ahh>3OYWd?5u{)c~O&e3hHJqNbHkK zxypxbG1+ZBa8!FQZ$mz_1CC?ymh!}DLs)!gAsqG}Zy<+%Xeg>v>dADrc8}uRK z9c>&7?pL2!(%EaQ-@T*#P{8m_q>)T(wWU)j-J5Z7n|NP_EtKJ)`ZOhRY z)EL4uo94#L=wK-P#vPL&rkOjtscF-I)>GJhiN*i_)Ty$X+HK(?)Avae`cJ1m=U*qM z(@R6>iV@H6l4ja2Nkc}%yAfDIkWa?hB3np1xl`>@7(VzQZmDB8!)#xxxS~8`h%8D? z5e2yoyFS2(W^P*xbl5`^5}ufh)6XY-JEOjv);^0{HAKe^lP#GhJUYb83*DZ`snVA< zZgluaz$B;Q%U`-^*-vQP$*D?JnAv7-!;M7In{KwD`#)Ezjham@{3NFA?Ab|9fLMbz zZ$!AY+tv84Jsr4~=$Ph5pUb zb(xZoT5J7*#pch!s{NvtW@_90F7K#P#M8q)MjNV~e5=K@GQvI7gf|FruiZVRklgUA z8^7o;wQQ#?l)W07=u>Q1U~Xd{Ow3SdUp**0zZM_dj%ZQ*Wslo11Xp6EuCmUg&xgF( zAzQO2c{^~5-I>XMY692pY83}kF+w?e_if$Y&PlKS6b?=P^EWYlCA_hS$3yH3iEq{t zkq5wu?Q+}}jt5uZS}|zuiJ~wPiuKm!m!?z9&8KKtE~>Q=v{oeb+!ryk%vaRkJnZF8 z;?WjV;5%dU!mj1P%5 z&gRy0tgI!KdQ@-;hSBl0d`um~*6&M(fCpro5Cbu;@csVHyO0T$*SyHwJsPb7x>-Ys zU+J${&Yf_t6IcFArjhWjF`lj`&cq<|;hmhsvvE(aIBUu9ccsry8<^~{yd|46uA`8g z2`?ul0_CehgBxPs7|1m;-15+Vpg@3pVHrqsscVT(ke3{>L5+4dRL|cU^NWJa}vDL?o}^907gTvE7`- zN6g9uywsnXVy_!Dl&1WZuhZflb=EbLe9)lfRaw56rHbl5p*r;+og>!``p@nzyc#kB z3XG^OZZ|(98Urc2QSPQrnvuFy4(SYoY&CWg&d+~U5AfYhTkd;TT2@JEsSfbT8-h`z zGpn)x^z3M|TOM=SipNf6&D;W8TwP_23K~cF`aRo-NA2uH5?^i04YB?qyMrzFmszXCqbl4St)lIG{ zt2XTOLJmcnuaiuvEe%o8M*H>|SrYZ4;$OITn>a23c<+%b@tG{ooe1rWC2P~B1$X9l zSn^aQuj5L)2#%F)HFpC>x*qPZm3{1r^>30LkIuU5Q&Hr-iq`$?2J>I=Mf>FQ)J)0u znKLU(i}}}l6n+S=bU`{gJrVBCPyke=a51J(O;D>Di`F;t27zj149K@P6)RSzol$a1&ySnf0)1_QKH3)|ZvPB?mh%{so%%%L z-$Boee%nTRFzb38U0Mt?LVn6cmAKgpuyeZsu-rlm<9uST<_}17Ty^Qi`~B!2ZWFH& z(9$H^-2BZ0Pc8gROi8q`@0ODff;TqA+N#6?A|SMu;^3`6;TUCCVo9CbD)eq@dwEqU zCpB-_#uTfXOJRv0Af&BDrM11z*1*E@ONI;GXJK8;6%kN!mH!#_Wl`z6iTb!)?V`7< zuMwVBurhAQwl-`LUZg_Y*}K7CEf9N|?~o0^l_-Xx$Vi7=%5heeb7^v+ z#7CAu$D8r8`an6+|KyVzkp)Oo4zKvTcVErP>C%@ktjs&g)O3Y2pYpFKpaVZfCYZ^U zehisXV>$R1ucUa3ZrYSgU>>ck{5(cGnpI{V4Rt2F>y;0*Qor@*J*_FV0yO8?+srhwnE(jgmH*Tp5T zxH*zLbsgeHV|_*SbZGueLA-{JcejroU?|=WM;LJ-X>B6cdJ3IWc=qo3%RWrS72Y&p z9JSf^y4uV@GrdGeb!6eW<&~@OB9n(Bfy=C}Gz#Q3=G1j9|BGN}Ykcb>bwxw%*`*=C zPv5LYtKK=}I<=VSKfFk*6UPm=h!2ZOJamDD`LMgDnqSw!M(VoA-<|}lDZ}?pt@&wdggE;6%~4h8S^UU2B`sq*Fq09MR;;}ey#?)x`zVEZ&}?1n;U z>ukBa`fpuGygvUU;E-Pnn)GC~U8sguDFME=mFJ$+f$IL9%LeBxY$L*>lt7y zLW$~nO<9rx^#sd-x4ucj4f}XmQ!YLN{J|n(@rI(Hj**kmXj?z*+RY=a6g0-VXg4{^ z#%>_~mA2^ZN>|6TR$u?6(=qu)q&;~))_OHQsk@wP5rGm5xSRB3bN5_tFX0B|XaM>R z?J_RGU*t=WiEjU0o`T&K9e}TB+DF z;AHmjz(?kT_)kR{8NU2)-s&`tw$!79CzqC&`_ zRO|F}-n4q{9?nriY0shLcNR4N6 zMk0eR6@XWUXV4oZRGL`1*VmA2z|Hclb)~mfzA^qmYtToVaA&;N^6fd~$jvb|y8vep ztz^=zB*L_*ViUaZlJ||cG|Gt3W?TxLeSGmD2^7H4k?p_N`7kNCn^_wC4V4NS==G@H|Fx*ZTX$mrrEnB5N9ar?6~X-?9rsyRZ5?IVg*G z_ZSA9gsVYW%8J51{mJZMtJmettZoz8f1(~OE0I1kcTq;mg9%aZ-;LfRI8s3Zv|1> zt7>1ylbWV0r?2Dqo8p%;+8b<(xjG~EaP3#GvQuhdXDF}tbQ;4quTyaq{0Bc3jzUdL zyjrf#zgaANi%o3)t;;vAlDLX3t{XR(oq2PBIhI+-IZ>1d{|D&;#Vh8^@<@It^hh8G zWKoQbd{Wcgoaf6G5)p2v*Fy4P<`eZZ&fo`<=n$I+(PG+){kx5!2{kU9t?1Yf&TpMV z$$5NhN>m5?PyejtPn_>Iim1SIkV?RN7sR-L>X#_5ea{-zoiQrCLC+9*v||)};YnxZ zDbz#-V;|K{MB@HIYb0uw(^-QbS#G%(4BiXA4U31Q_#dwnF_^_w2Q=O@!dy7w{-=W-? zb%-z)y~%M_7Pty(mABS@WA>pdvd4Tpj#I|6D(%qtf}{YL^C3Y$UL2aIDVXAE5heah z70^0A|D7UMU~l#Q$r61-4kPRepENT!r>qz_X;6v}8zZeLR5;6qOsrq|d;@6KhLx>PUgkeUc02Zz-yXX-y-@EZtxL8N^QfXV zxlob33y|uk^p2mHyrkx%OjKc!uKF_rEzj4L5kg{wIY0?rBAQ|+!N}X`)4uk zO|36?dnd%v#pYRzSM>nsn=x&Yff%$RX|mDN`B1j|(6wQ|jr5+%+PLd(MZLnWCL~Se zkgCmRh2br<&JpFrtEyI{DO`9ld${nSzbLugjEppqkz*+Gn{a{Gim-a_$!^-i_ZDK6 zF4PSsN$A_d^PASG%RO!A_2&;Ms(LuqQcgeWV+rZy-N~bybVh?viAKdYf2oByw@v_^ zq>~P#mo7-3_KT2<06N^esqpy-VK>A~bycOV@15A^U&rsm2I`L*JE5BCibzciI@PAq z0Dxq$=&nH*0MVHZ%aob@VZ#;k`dFy+zhzASdtJ~RnUDNhRuLOb<5O!LmCDB?tH_CC zV|)n=nRRF@NOGmuH$#AKE2`t0m{r*3_TGQ+UYv4&=-Uqdj5bPq@u?xz>Ui}K#iO}I zS^0nbp?lOCSQIE=EjGO@^5f{0IXmQC{kN&>wmOYs>Li)m<467qKe96|iWH30*qTJS z3cNGQBJXZEev6l%dKWiF>7ZjO=B^T68AxxYB#JV~RVQraPUdh?rquN^@&=`=e%8oG z<*mFNas})h9;>IY89RUzQB4l+C{A-y!n)Q%Gw@_>)d2?8YyHO?S&Fi4CdTWT({OZM z@gk1ea^}=}`2J=rjjyEylq?Z)`%0Pbn~=Zk@{5#*j}7!9Nw1LPpr4oza!+jxnyY7v z!)_GW4c$#Sp!o@Z{4ez8(-n1DQ3z}4;T+eCt(u;%7+gAy!u=3`y|6GZ(FtMvYoO^sIT zuDZhc4DJ!=_LTB6)oOX>t^YuIt_(t+AOaln|56QLM+S-*g7xqWp4|Z{JI7U{|6A;J zP0+gJ|D)|az?#~&u3>vn82}oB_5a~72L3(IX0)`eVAT81aLhlfo5PDUS zCWMwk4M>+7DWN2ke}j5F=ic+)`+nc^{rh=TBs+VrGS^&ljXB0zo_TA5jZ|cb%N`vn zQ?Edm%`+JVor~#7_NqG)@sryHq{DyEzA!e&8bX`KGxz_WwbW1C`cyW<{N9?VQ0&LQ zKS35v$T`2?sOkE+rYLZ3vN$#=Z zg6t{$ei`FPkw{gKN1b(bfv!Z)52GX_@r8_gd_A@=Yk{|I{zS2U@Bw<`EYESklzhZ5 z{I3G9ANi|K7bSkyGE}eY2ZA5_t0DF(E|3mHb9Ddry-r7FJ|=58I~P6zTWxt#@c*E@ z|IU5@e1(nW;{TKG23EtDW=yZsTQ2xtEvejUQIscOAO2nne;POi@_h_^HWAf$;XJTA zY~-#&_3zTpzy7bu%t7WC7vL{SRzMWWNHF92f~@r$5HP5??zPk%iWdneS>DTZq*?wN zhrx?KwSPrKQ9C}z?-cjR)|v3AkQ;Rvpk#uct8q&nYxJ=vV3IrWP1=UsGPQd+ijE=H z(~qxG*f)^P$QC7QEb&u4i73hbN#F;tmfGW5k4QI;>-34rSa1VpXnJjpI52VpM1IrV zVObOOK5dT}Dcrbud<~usP)ztTZ?HCq)-!UflHAOr3I^)$n{A4xC;wDq{u~S-Yd2qs zK-;bxe2Uy9UeOnZO< z8rqmw>mfkDK@N$hD9F!D5t$;k8lzIw`)i-ATskS{3@UAWST0=5 z0tvn(k9^_~=2y=$?^RPjaw|>OU_<|?L_u9)4acryjL4o5{cyu%;UfY+N$sVHZFueF zQg4#a`!tAwU-igi&I z?s>F@JF1m%LtWf=)JKF{zs$jYEzckpy_k9(bnOvZ8uN)7N)zZR%tjaW;HQcIjC=oZ#tQeV@{Xyv>?-Gs53XC4X;L@g!gz|7~KTIR0N@QE9dFSc?x)T6Z*Zb%16#A5QDtrjol{!Zy8FzGMP z=bQx8=r6VLs>e{azJ1e~cScNB?WkK2tMXe0ZppoP))1LH_`<*Fv>4C-BYS<13{!Ck z1Hc}odYBuv`QM#%s$IpE_et_RHCdUyQB^b()8O~M2u4kLKG-u!{(x-Nz7>XS0A(wi zsRWy6(~#e|ls$6o?OR!>85G#^_E9ExR(D)CSZhu-5d9Lo|9g6y`O^2yTQl(tZMURf;8aN?Gk!9r zn0BS5+*|!?tQcKUVyiJH`3m7lVZW|{deRt;t8`E$Lq_m%og^X{43?( z)5mQ{*KTcYPU%k_+)tvY?L9NDxjUHA%4AFDbq%3icRTl?{RiFt<2qd_i#)ww*bl8f zpOxLQGV!-U4=56Y^Q~=cg;%ly*#vE}#CvnOb7t(Kw>Nj@k8_@HKa}%B29;9^-VIIE z|4cO+db4rO1E2uf%Fl8DZb(vkSC1ZB7*=C*4}SgE;Q7BO0)W`XKERLYN&Uy_1SlSGUATm!JK{Sqf1G^!$1isOw!6;5lcQ7C(>8i@%B{+F z3&Hn)5XH{hZ-w7>tW z2rJBue3_}Ua_sm}LLPOwha-@O`03JA8Mu4|@p8Jqc0bWid7L0-+d|g@0R;WR)pk2y z9Swv>9#PyKWLsCGmKD?+^uJN*Ph~6a8iDXL|5OJH2MzA*?DQx$bVs^w7UR`Rmo85D zJJf#_axiIBgj=|dC-?l%%Rrm;h5-Ku{TfxQuJw#FX?am z{q4p4ZCMW6RE+DNoCns0iLoaZcRGf=<>j?Y?9bP7zE)#+@$AY9dz#{@JJ~aVmmZ>@ z75LX&pm4k0NP2unW{%7M*^Ayg>i5nv&|RhFuIcH#ctPPpxVa@9e%s_hV!VPN=Z2xJ zMINV+OZ(j5_=j=RDdyorf;35KV^j1r&p$KK(s0=&kIYJo#_`=?l_1dWEwbjZ#p zFu8l~h#}1TM7%oA_At#^c1P48@V)CsEl*Xq2S!3acd*j@fw2f0sYB8vB}E_Led^;c z=TmH;zsjzz_gNRxTZ?djZ>rNnoP5`LAJcGE0D=Owf)Lej9a_Wsmt8l~Fv$M0pew1b z>V~lOCu&fRI_z(AAUtH|#gs;a9;MCo6Es&}ca1Q=JnPcq?o1srK%tEui7S@fySfNe z_E`#0*&mn5vE8E@cCTlazqX^kE&Th8fj@6NiFy3vKALCNy9d$}(U}JQO5wHvL-j!r6;QQwR3V%NI_Mbofx5xkgP~!jX zBX6tql{=-fdwjc?o{?cmjedFf#7u(cg8JRNcRwUV{n-KsLd%AI^v`gr;Jnv}nGq2Y zN^4C`O}5{^eng7cBY|B&*xpak)Ah#uY!I4_)i$9HE<-7ZEk1sxr zc>6X<-=X4u9U#+nsM~UrqI^r;=WP@v(0E`a=;vFXc}ci_d%L^wIj>&vgS9~y1R+;9 zwZdg;rjgYV7cF3>h0@A?Ce87uEgaD}e1aVZ>M=;QXnohhlxmw_Ay-hn^zZ{~!)deK z)5LbK3)b3MYIn#p_;3L^z9>athjJ;gx?7!pn$hi(4;2);QW4T9RhcaVBx^sSKM5t#Yy-0oiU5jQ)e*5Vow z90l$161JaS9Yv`nznH;gr%q!tcf%Qvug?#!Y)mB{UJaa zHKz*8;KY=JPJ5>E?9)w$!CS$sqAKO9DLLd|bTyP_{z&wQSRR-+eHnKgZWe za}5oR-G10eQMo~w5F82o$TfMxI7`gU%1P%TW#N~jc|Q^T zqbwX^i^Oh2jhU5>mljegDDP!DU$RS#a~>YcZ*&0N)qESIMu9cSHY6SiD3-AF@u#42~&DU{QU zX&+a+3T5zDGdzO}iUw-#5Q3&{ag!lU_&QTqr1)jIm+W=g!BHwbR<_+mk_y)KiqKg& zHA}ITD-vq4qh)&PRKTr`Q;o-hXhy*_|7Iz_o9Zv-V{X-Pw9f(%KOgr>dd_RC-Ijab zqmuZ>{?qlkZ_f!Yi>+`h-Zzu(u3AYfy*bnrq=A#y4NhiCrw6r1tXXHFgcs7b>p8mE z3{xYBa^r*MAm6*A$_qe8Kl}6vXry$M!Aud!l^I{-%W#CLytXSfX`MbOUyV6|!$F)q@4&mS#6FEMm zFRNOS+}dBr^*s^Su}ZkGWfekgnda~7aP7MQA9~#0r3>u(nQEeY0tCG<6SUQt8|M|| z+FuBZ%+{SF?$l0mK=WaeA``gag@cy&u+}cbOnGN%eK*Xgl4?;$wakStp9j~_Efb-A zU%2B|ES(h0m;Dg`V2o3*<^&z3jviNO=6m$#;NiR1&}r5 zXi0g|X|%wZk_?Oqy}#HHmx|#=s2pPZQBLjJ)fVfW zFkOmsm&bg7s@CX7WeW7u77KM*x3ajS0@wlO=LC?H_6C8F>0?qU*iTNp9246>s~K)e znw}r>1Wk_mqPo^KYLKpx*ObfelVuSym+b4ySY&+iMPMQDg+4)}8e45JxzT;LYMh7^ zOnQd`7o^74NnUH=vL8NO<7sRRh3FWQk%noeiD}aTi-|T$YeM6+%~4JdDXhduVU?$% z4JP-0JHY?Jtbh0lPV*?(vDdQZqP}-er|wRL&+dNMvrBH68JEV&m{i`1K}~`1TEZb( zGIe|O`XY7~H-|OSqb! zQ#nDDp60lku(_VH5E>eq>1{qv zWi(gF^*hFFFmC$ZNA`a#LL%}iT&u;5UqmzL-UmBH;!)KYT^jtmG>?WKsy_HR(ie;)!@)(o+Xv* zDtVH~?dY`9tWN@9p+vzDdQRW7$TpeLZm>tR|V-kX1v)r zgu1ly3OF(&l+Qq0vy3Ckzn+5H<2CZC5QK12O#uhV1{G*T%xclhR2)^NV~?;jO;z9Xz!+|$tj)TiG+3w z!87CAn&uMo+d&=JDyJd4?eoFMl~}W~LiUp*>c*<36 z{n?L3AgxMQ`uQBJ9&eOSN}j8R3sk^~gW=GM3UXix)Fcq!J)N0ZKFC>$Pb zZl=^<*@L-C=DT^KW56a%>W$?*RaOaoO*BTAT62xu!Kp-bTSHb*HG&0fu9*&KpdUvy zF^!2V`!z);6xiLgX|z4={WLfm^aLsPRT-`^OqH_iS+P~F7b%NT6=eerjoVM=jLa)< z)rPm}s8T4Xm<(ANkpayhf$OZ8b!mF#o$M;iA{N#*De4h(9I<1n5!5pm3q`-N5oxYQ z&plJveXD-1ZspZJCX(qg@xA4>N#s$>hEoWIJ}MekBrk;}zn-|(a9&7etDs`~`?yB9 z^JrXE=86zKMOmauvhUy&h$_Qm(w^`0oOxsR&X_m#pgG-mYc8V2&1RTifv-D(!vAb!2$`XmTOD!HiB79;wAer z+sPD`{g~o#x<%wm>>(tJlre}E8-{Ur7rANAuK!rY$144Xz~zoS$A#$FxcX0M5`x7n z7YHCNtpuDc$ubAu-gDcy^B?_m)d#xlE`6{FRTe!t9~C-oB&g|fmtS+(?Ub%$e~vvm z(^g@&io8BS))Kj5pxw@qU&UvT={QMhfxUBlaMjSco(6wB>MTq8kgVr*SUXrRbf#-k z3|*W*c2lZX=;5i06S$|HvMkQ4UYO0R>a;xR-#_2VGb*{ics-fhI42mXy@sx_8U?{8 zNsuSYmuJ8QK?bKvaMUgd+-OG(#i8eowx1T(LUdId^F(0;ic5E)w>K!flO2|!!d#FD zAIxl*Lh=lLo~1G`YmE`QDzl*$uX(g4Y)dp_#ZQHKCR_Rd$Band(!y}R;;M!)2A5}6 zjn*RbKsM?4LK1vDK}Zvx{$Oc=&?6L;qglNuc{+Qia$>W2Z0xj#Pft)sb>$3D znuXjauix2bZC^fgeTmvf5o$mv6;YQTv|Q&&egFPR`kZbi1MAxLK5aQGQOD%|bhQ7b zbxH^-cROxlZtxaup!?_8%Zm}-MHj<$IM6ed13{4;cCaU3|oH= zAi;wS*9Nlh@M_s8$VZF`6W=}*pUr(Ap6IJ1t;ldvNSY8>I#R+QHkjrvEo@)RYzJp)jZb}L9;kDYu`+Pqlb%S#2$iD zREV15mA;q8)~1ud0oKFdn(AQ)A<+Tm-bTpPX2X%fxGUPVj=zyq481trQK(-PGS@9% z1{Dv5dqU4kYD-8tT%};GFbf@*c{6j<^h7rkjpmA#3k-+VgJTVn?xKda0*>cvmEl{_$``}P`RU#%iz8{ubgwkrS(T*Xt!!j7 zeJabHhlYIkx772Ow6*i@?kBEqr-W}bHE!pDa)vrBbmzWfbll+VrWNMemC5;DUPY69 zh6Rx>3*bnxdJtrFL}^F;Bn$CT@D~T%3^{wcBZ-_Nin1HK7I2(ibL$$k1U|3FCJ1zw zob76lrqaus45g2IZVdJLs4tx0_Fc!H`7f3Ygi#0Up@ge51E%R2GMm1&Io#$cncB*YGBf1bh$H+095 zWvw59O8mB9`il$T19NP6rJzx+w>F>G?P5eo<#6mexaEn`81iV4HvV>yMfhv9^ixRn zITBRyA+}432ei|q{jk}|)?Kb|6Bh9W@I&);7y>`*37&>mC_8hI_Kh>#;4DSH3i8@Y zCb@r&6ZtJ&!p4Ndrhk8Zv3OVNXS}BHf=hPC2Nmu-HGGX%lHQKgogGm)LPKNKdV5E? zb2zV{djjgR$?x~V6f}M7$hh!_7}1Jdz>_w?Wf!YB>n>Ki2+ps*wvE1+p<=F$H5>GB znaP`xw4^fDE0;x!XXwoPT7LDE2x@wY`FM2<6Tf3)Khu+I0}-_|tvu${>lHe{I#@Dq zy#SlnbgyS_P*#^`#>#*(fKVwS}0qc?;~|AD9S)xyC_i88r^4kgTJFLoLx5ene3^lRBXPnT zK%Nxmj++7fnDqV^>;!ZrIXJ*z=5(;+j&x)~`R&X44BOGqHy==EZJ^%eFEZLH!1Mto zSlj1Mz9-6u3{Sn|#{uBbB|*WZVnk386;C%j5a<%W4SNr)HA)n7Rwb8KWVQ zv%3ySchkXuT0x5Qxw}|ZX&RxmEdj}~scdm1jW+k#1j05X3vw^uhP?Ah<*3;!6&&Binnfb}1680FU# zBj3w^f)YOw!+)FLE%<@cBY_3p{hDJRoS60wxBfu82Q$3Ta^jFZ#mo%rmzS&EpMstJ z)*GTbqyii>`mYxN3|4a!Bm%ESMiUz}GnaBWOaC3W1E7)@P^-c-MRfnVq%}&mwA#2E z{Iiih_V1#nT#ErzCR%vcm7j-2Kda^`#f*kES{^zY@?YbW9}sE6nIfK2Gp@9;RIXmr zz0N$gx0XL}{m&&mjU5Bk(g{Eo7~EBQ8`*RJz0`l{fZt6AROLMOMo3VQTzDXWzJ(6MT`Ap2{NwyT zmh2yX$!QMGbw8)rh;MqT6e2LeO77D2jJqof~=Vme07sO%TCip z3+jqO;0gufjo%tPg!0h=8LofgPVbZYm7PkW0q_X~ua8_0vF_1SkZuxY;GNBv$ipjN zpldVB-hIV^h8EhX^|t}x3zSH>BrG#~UnK5*u+(pa?0+)GT}*oql++DMen6-;<%KpC zGLn1JcwBw2r1N33+P#bC-d#n)TwGV#tVudGP~aFs95lhl>)ZL)6J{gZLCJ3)5;k{n z)TEm?chgxH9x(JX(RR4y>4j%`@Wy5vQ0zwpAb4DQ2~UrZ5pcuab-sDWvQRT5AkC<*v4kmw%(JTQ#KJG|j;r*Mwcg3Xx zUH}|f046utOUUijAfQuEoHL`k^oDU>>U3Fp9)1aA1hOG;8Pl8mr~%FGuJ3iax!si} z-*0Pgo5nS6SIb{dfR}6%r$Ae3Ck)+T5qGb|z@xs^beWOK=Q`e)1$Ao-I#+2%OoEm? zG%2nH~OjYa8%Zawr3&PrV&V>tJ z3kQjP7d7}4hT_jaEe622_3%33)fXBXGl?Ecn?@eq;Z0NLFQPL`=|uS}mQrQuo5+v%Gr=m^-LW%X62x#7tQ|-(UJ~3zpxG;FLsQ z`dC$9-`=AR9Nz=;0S7m%d;X_`i-$q}>DqaZE{~2DhgSLmxEHSV$(7%=|K*0nE>@Wk zb>{&0#;})^`Q3QntiHuV?qWO(d)d0A_XllvhjG$po&__mKQ4-wnyK^uN~*okcmp}d zXeA=_;K})adCLFP1#xc;-~7(4Jo{;=ydn{)DVatW)Up(K%oIS8DC zl=gpNzS@t0lSi85)!*0ep7MO;AN*(}kSLADbqzyT)-lZzFu;DJz6|>8cy(c=&@~daO~pcqPuE&>~+CP=-Gx6ryrC5?nDvS zkqYHE&fQm)(AgbTm8I2Kg{jk%rrNSOxa9HWp8D*`huBIk^Oedw!N`lPTtCNBGj2;% zm+-EUFPVAi2i;LbmyABsx}FiW0N=Pz>@2D_5R1p6bu>xk@{W9u^5%CcwJK~>iIkPV z$||fbtvYJkYhGOHmPHIR%Q-2(iZ^49xp z|4*nAot-A5F6`DU&)qi^+a)s=sYTDN67u`I?b2Xx4klm^Vfz$8LGjHop~}VVj+M1W zsfT>}`fP_Jvl!*+)$0Aj_u1C-M9uiFTdjv;VHN=<>;S-9Vx!8lOgDP!!e&t5z;$4$9Vq=$TeS)eSGtMI??&})9HNIqvikkvx0yOJ z)`aIqUPD%w9@`Ta5k?E;I;p-j$&oe{@#vy{gSFyDpYOqh+&6f6Q9qmR;1e^{dkVCn zEcCcu1e~x0%^|m-4U0()`ogOnS`7_sT8VG;i#^vIwicTb`)h22ho&{}2TPRc#CJ;i z7|O%(1BsD@NU#V17Btz#NofWGU=CJ$*me?CE;$~KAlt>}fPJM3<{6doarfy;%ne)s zMY^{KubZEFh>fZj1GI{yyhT|P#Q0P{_hECY*(Q;M75Lb=h;log^K@IakK-r3zrXL_ zT7JLaVU=2%C<)KH)IN&}5R&QSmsf=ky;zs-5c+|e_ACMjsSxmot`ib41SGoxJdTF^ zL)wGWoH18M`4-@S{_>$_hLTXWqVdfg8{((WIH>`x?7rq=>#k45)}n1*uwEv!?zYCG z;8+n}B(f6EimZY^Nt7g<5&gLGX8N&*J3@dwK(tHn_%3)xv+B*XginbAsFBGrMR#%g z2{y;V@Qh(<^7NDWz{#ksA;|&^+8bH1xY=&`xlF+aZaCykirofz#FUkKs0_U;`lgPp zTzn$5^Ev8mrB~3j7WLY)c9D#giqPS6k`Qq@vS0^qU&6G}T6@f7>13DXcTRc10vnRB zi}FjO$voZ!r8NuAi84Q>oMpKfi)?0+f(V^lu^`cSv#)xf0NCqr(iC2MWTz*5Gq|E; z0cPn+xjQHmOKrEYVW;q3T{gq_>+iGWoRqRczRHBBN&1#pijy#uAU+?(`Zt5uR% z_!{<=vFzxrRz^rjpYD0<2KxgIZ!f+K{O8907tikqgnP8M%Sp9{rAk612nw>F^BV%b z-6d04kkb(pb{0h`^GZu^t?jPC2zFe*xiG`B(&Z&(G^X!;X1n~Hw@>h@w}^bKq{b)J z%jDsyHB`rVdVl4HdyN{2l}KJc&(=P6k0#vXfrN-d_rj|WZAJ8s-X#t}x&>m(V-ay4 z58&SD+wy$hvP(x`V*PoJB%AC;`k5@7VTFg)-|8w$?J+Bn5Yoy;$WVF0OmVdWy44_k zw(?!alWMSprFU-cBzQVN4`wgx0W|@TlU(B0@%G_xji_1b!E{{30BokeB;*{tOickM znS=Lu2qnNBv$8CPKSSUF`kwIk)T`;0S)SmI*^G4aY$e8rwLGS6Zmleg+<% z3d{R=J2mixEl#7Pe%AGarxvR;MK8TzOG~sYKkcRhk1ms%WhQ9*1|}$P<87h+bEG~N1z;AFV78@DZ<+~@3qdB_VjTg zT(TeTfXQZSPwlB&XS@sZ;`Ow?+&tKaR!@W%=}i$OuOm7*73AK?pC0GdH?k0lC0%L<3F^!em^BwrHwqtb5 z3*EW$3E2MDCWyhZ<~*VEkSJtHb<6e176K_CsxHME+4}te00Q!99hE#pulihU)kz~BzO0-~p=?eX9Lv?LbkLJKW_nfgxPjVe|mFmF7*vic_-j!Q-4atdUXCI*& zY`NBU5UrrX8*vZ4!}wIpG8|XCO2moWr45`;X-}pTcC>lu#`)#*FgbdipZt~n48v+2 zM~THSdmeR(+a6}})`-$Hbpm^y@X0E_2kS@b#0f~9o%S4k?;McJlII&=fSsp@cXm=U zW}9s~-sYxVL2$>Ze?)lE>b!9{ml+r`{|KkpEb2r4{DT?uI|%#t@Tmq{Ls$uA_y%uCu(q9D?qjnZ0#e&CN3~Ho{q?6DDIV}QljT+@boRk(zl7xI9BR&d zt?^1LMR-SLf>!;(j7I}o_Pd7oi?mQSY`=EwgcvMVzmNl-T+e8nm%y-P^V;`Y?zLcs z3h&fX4=;z+Mw{&uu{e~zd}LIbhCQytEX-%qCvs^ua=nhdqjW-V+M!?@3{rpH`9vFt zE-0Vva4%k0sR%cOuXM1=g6z5)JgmAgkg)pWR$zZc`O^6=zTtxF_Gp4*UfMNf)FI_? zkw*k|^8oBG0?+#8dy(9U*{|qrO9ncIYzSYzeR^I~?9%N*@gkmrjdv9i;nT5>@21t* zsa->C9N&D8vq6W;M0+E|-O3fP?(zMMbA6QHA*8TsYZ-^ur{p}!L~tR+ZbwYK%qBXb^kHI+ zxFMYm377opW&h1JSj|$rdLSWK1yil8mxQQY`qus2aNIFbvKp#t7+wB=&OJ^K(YF>} zYuxuBzCQ{aFu+?TaW7B2gfO%*Y#Yz%7e3)6rE76g51oyCwUf+mWlsTh4`0u9lcRH526-mpDPrJe{+5tCE z`7JI(JQEX-Bo~BgFxt4T5g>gT2qRsm+d?F}%y+y4)02qR2|;~Ax)8sIj^+Yw5AMzs z$^qj6f%UzlxYid+BA9Px??8G8_We=cn)DOW`EbppptE?dS3W8M_;9uq1|r3D>)oZu zX>pA+Bx%h=BceeGM1*jaziIYMk8!8AHWq9?t}vLHH{dqw-{E=?Tn?6~W6t|%sGoHw zyuFf)equ;n)u*U_W^ZBOTk~c1u)fV1k4?(<2wK0dUVm*meV?|9SG=6xB&KuFIcgRa zlD@nRP2=%Q-X2)(hVt=14U(+xA{9l%ZLLDaWdyA z^Tmiy;%-eLlE0T=2Hk@1yhcZ*`(Seu4VORcZQr8FYIesh=YkqcQ#R~JfDL7 z8e$xT!cwB*I9uv`I5DGV1h+5V%CnJ#&bS^L(Es-(EdXQD5iI`&H;YP~3sA%gzoqX< zffQ3xkl)9OG7PT)~SK7eYw%%$F1(-&}+n@$lWGa_8rl6ix z51kbRJ+I{$&r(Z1c+dF1ZT^TXq(BYNN;<9{-fcFTXMaQtV>~v*q^peQ*X(fK$cvjh@c7H7jUHkgjE-Bwp!yQ${?Mr6Xdx9P2nWe>{E0(ajNp^$IMCr@$t{<$+Uk-F5pI@Dtp%iZxUR*}25lBZ;sj@j6h>n2R_8fZygr zMsmjo*M-HyZpmIQRl*`15Ge4s0;?HfF5k$-3JzPhnb`S`Z`1p87&!EdqvT{VrgCs# z8-?th+N9N4OB-W~nPJzA@hp3dPF}bhi7h{5;2k%9syhGeGFc-h$~9QkOqe>Qf-ho| zCExodL=i-VxHZjd1+#QDk(M^oBzBmyNnb)b>8!xo>2`Gv#xX)nY8BbYjohmPW?Ns9 zLfP#^bk`!BribCf1bc}|8`#pm3fUA~>5{TX>0|@sNs+)bzL8iqTUtCqDYX=0zzq>@ z4bT0-m1F7jwNWi?JDankPGe_~J%`^RK*RqE>76J(2P;1#P2!Zo-59eRH^;CNG~Ca7 zs>78l?^-?3m=O$~8I*5z&`pUEm2WMvDx#FcW-Bswbn|wV&W~Uj%+ZgWE%!hOE~Q|8Cg75@jD#aF|OCU6jrfFAB#=T0YYy)$L8Sm;L3dvFOh znbiagxEJvC>FYZRSLo*vNwXAk9m+O*&DFS1Eq$B%LcCGC%Md@CQ>hqcKns06lM)br zB|PKonADJD1h{IISkSst^JtmXI2i)dEprc*yOD_U6>yv`^~X{@nvTol(2bVP&f$cF z(>4NGqN5BeD$L*3KZkuWfwVy(7ZmuSJ{gSAM!MdBz208Z(yH+f;GWRUbQcZA6+~XM z)*AXET;8H?)YBH+3Je+a@ ze$U-CSlq|>~b-Fc?QUD`xM}s`&EOmcX_oA#u!wLh&NC@@#PO*uukPvrTSL{*r&?t0;{J>-fs# zPfZ>|K4{-4`=_G<$ukDofh?ADJ(ZudxVJ>mhQp1HI(`sCEf8W>MNuzpSXO_gQiE9{ zD_hU)X$(qEI`{ce)oH)W3M@>z(gOuj1wldx7?P!O}#~=`$hRnlk-Y zu3uCK7!q+EEq8xHz7|(1xQp?5jw)S;u~s(iZDml$Dnk#eCo;iCuEGPa@5{+eu7`F3 z`IY@f02(|uZY+4vY5O)|I`METfap^v8IR2-^D+N3A3AUe85}bIv|ru`fk9nFMlG*P zU&|arQy++0V%{q?Ws2TMOE_3j@Avolgf`|fzspvUv7*fD#!GB1PA5{OeP(deG3?=s zPvJX3UJNUR0HURu8d(AI}4 z#clW3UY;_;sBDF6JtTjLAS`*0kvB7VQTmldZr4birDqU}SKt{RTlqAr7~HMb7cBG= z8erWa-kAu5h-O^?!^9UXvPQ4aHgEJYBs*kweSUhaVSZhC8S!d%Q%DaLDyCTIx1*tv zKP4SI1iPd@Fp#MHY!vb$A@SiyA?) z?tDJQJ6xk@lp`}dXgj>=?BR81vnC1*oGl!^pTpXu6^wT!Tnct@zf=@qymEW?PQMT& zSeogrlhxv1VR(27D_qI=xP9*7jyM!UforSeRQ+7fVQ@*eONlgYnBTn+xnHBxjH_E9 zWH(vR%mN_OXG>l@MWf@|wL8boI(y`AdfC6;xaR!)R_*!{gqk3MU;cg->Avb=hz8v` z(d63W&NHmzI>yYREA3}rV)=%BoeGQ0-zfr4Y1dEGdU|KZ0D@;qz5Ogdp$-HEwF@&(wXLqyft zk#x5BBt-&8_ZePxjZ8Drw=jA?^1VPm+|{O2$L~i!7t4^fk$3&xd)nJ$J=#OgFx@RP z81n#M7RwhXMQ0AgEHn!D?r33oEQSbiSsq`U!qI0AK#skhZDWc*QzG9AW{$_%ko(f~86A?bz8D_kDWKwHfPoIcF1n3R8L=D>pk6 z#kI)J+A1=y-Ls{G*JfnM{gZ|2UIrWQodt)?#JM+w18e%7pBAo0)v4IuO?zK7kLv=- zEr)C1)9*fA<>dKt%)mnHdUX)@YvcUbu$|0SU>{ZlnGct3U+BO_eyVk`IBw}CtfKeJ z;OvS2#ImL+|H-nxl3mQlB&ik&XUZ&;A*lyU8S}!|V9GK$*&ajo^pni<#)68*e0l|j zi*FuEmMhe$lpCADr4^%A#YC;G&QX`Pv_niR(0S*Z{!341qtl`*Cw zO7l~=$`rq~ZXR#yTrFwI*-im0+>@&qc?p7g{6)lGst_*73(G03grI!x@sYA719Z0h z&F!V#zJKZ4^@ z2d%QyW14TUWIP{{fLwY6NDnS5JRC@NYzpekvZ=EjD0D{kSY#!zQ=e6WWdzJ0PoBhA z3Ed;v#pg<&3X8}kCrT%u>VW5`S7EgZTN)~tD;Qm^{2o+{;}`l6(*yxyn~Bo>4}loH z#>R@wvHgm@Jmq;&Z%!QNYmo0Hwz|8!S&_I9fwQ+;&V3WLZl!Cy{$a6N5#-!(rr&6b zx5hBNc+#;#6X8k1?M4b)Y?aju1+LUe#93XJu!Mq$A+cp{hvAw^b7QF*;?roo^y-40 zeElRkWOXLBwX%5eyL-PnDp*f0LUXAQ#!@oP%a$dgn;2)f{Q1`Fr`|=|EXrJK8Iy9N zZI-8RyV)9LQKM9~Q==Cv=kLk(q_uS?F}UC=rfn<5F5L_3N`8sR9vEWsc4}7+XtA+% zNVZZ_hLaML?bEAJnlWFT({JEmK zOy`o!P2kINu1a_#ZLH3TEHzrQs`QvBn{jTxN6#})s_oO_B|5!Kp!L>4r_69^$t@mc z?}o*~wKW?3D%-ovFr44o&nKq77kYpn_Dtw(_HHft=zZ^cvNk?t6z@?)xLqP9hVIRw zuX4cK+pJkTsIqZ+tGdc1EpJWmG zCTo-I7c6(3ypG*Zwvb1cKba7|ysKd2I{KnS_gKW)4I9d#qP|!*mRcIMSAdp^!5~NS z13-RJr8YOa--MasbZe#!O$(kQ|8n*BK^sL)mZuhV72vYK$zr}1eR1R(sTviymrloQ z>u`Yp|5Rqiao_$m<)*Ccm&ttoq~+?zR!-6fTaS-rYi^K_>i;{?1!QGER-$`+-Fd@@E(&4|fxq;8BcK#%?`qxaz z-`XbNQq`cG^tupjN>U?ed}7dR_y^nImsVuzm(-1U!HYx<$&rTxg^O3d$<{mqzoL|%r@ns~2r%~;|J~?fmY9HPJ z+0N_m+lFr%X% z-P~`=cmgKz8L$uM@s%7f4Ax{4*M79_kCXq%j;Uy!w|WJ%YbRHG5b3XIHNcVS)t!4% zvBe!#NB`Jp1@OHW3VLlb56`HN;U7{IPkuhqx&wa zv;2E68MVXkcp^wK-g7?I_-3wOr8(}WCNbUv(_hQpJ_Gfn%xN=>D7&cSML?=jUv)uZfkDfB*pW?AlaT)X0N_ zk%kKW%*yCK_?`>;1ziKGyo0mtqo3OH%Q5tBpVkcj&UE-eE4aOQTIsTM+yy3h?;kWt z4}cK$Enl6C{{d&6k~805ve3}D1?Z!DhkFF7eSt2& z6KLtw(pWs{S;1*1Q#*QHC17f zJ*7dTc>UxLosckeX63YDCOq}v?waTXP}Sz1ueg3NWgf`kcSnQji_u$`=I!dZ2F$!U zge);P>pI3f?IOSS-!KSs-J$55M1wxHvT#78u0 z-3MCRM@Lt$xd4r^(a01KhFOEVedXA5OGT}G{B=Vt%`x37iK2$MID*MnWXT=^yh|+e zw{-Ght*dS^*uFJF{fqW*m)Qh(*WGD%>7^n5>fzv1G#ew%6@tXc4#e5#+th?QEby|T zlY^MYz}^9zv!Q-Q_@34^o-_|zL#LfU56kaj+*U9-fa{`G-Mir5-n#W%{DcJh)Dhv* zw~QY*-M{1?4`e7AueOs}11Ie)@2Yrd7c2|Kgyr20pOlquxg#?M2jpx5jXTM*mZ*(! z;}tlO`%!$j<>K@@1I;fQbd3pyuh-3TDzoo6O@=RzTkJBqUwNe^hZs&l%~#E@ zU0CF3BC6&NN>`Dg3^2Fp@q<^iqrt1BN}>#0MB?l z=RWtl-nE_&?}zvLkTokanaMSKX3yULxvt-?ngQIi-M`tk=d7haSRKs1ex&!Jh!FJ2-i$o<%2kB>S-ji-_qbD!b&+h{ zh$iSMb_M2jB3JI5{+zla%F({L`Rm|4_MxxyL^gEuAgHC@Q%)sbod=99r0rS4{Hz+*@`M&~<#D7Vf zI;r+``#mu9cYADh7nmUWLQv`Sm$WqIOWC>28g_GOgJvEX2#}ygv?~|$0Pp%&ON^BR zh8?w*FC3Em{f$!T>8W=Ilc_^ikN5)r$q7By|C)UOfzv-;3p5So4$u58F8^-9W{Q7x z_V@C?6p7AZ0Hq-amnpi1_44qv5eF-g{;C4&&U5sCX3YOPcmCg{=>O~$>-VtNKka`3 zQe1VkUBs8Qps&TRBsZ#8g8`HYE2-Tv0)CM5sF(j}GoSdb%+#6xAEwkx zJsy^1HwVA7YPG=q^^uDc-S$!TZfhvZsdeg%Y0)$jDr7UYKHbpD04gjFY}Rmc_|dU8%e5CH{8yImidc z2_yRee2@5g=i#vwqn7+C2_?YOS$!x*r!LtAfD)?wb5GOYX~sFmsnOBmvG5eR34^b; z82Of0{PTewm#l7n9#*bzq}pda-i4J#y<9Caac5`@`<_#!BQKu=H|v(F69o~UzY_pa zHa|_Yyk{DP#{fGH>fN;TpOV)8m=JB1NlrkP#9-s@(KkOoKVuCPd_#0XSw>*mH~fhD z=7<~T9b@&o(53`mT#mT4`z=EsX%PLCPT(q7uWbffzkx}7v>_uK(7zc}+87Y=Q*Wkb z2Jh)GV}nrh^7eMT37!0E&_}UMd3jfD$qu3_RUl#4uDHgzEOcBdm!Su^&0c143q64+ zuG(CIjuSQ5d9HVFw^wJhx%grO#5a3}oa=2>2#;~G~`<*>-eu=zDue@YjMfD}p|lO`urTJL}HdR>DW%<=(g=ndUaU?u#^3Y1T=$W*h8 zu0>hhSt-UG3P-0<(;#@5^q=OsmPEiDbOdkTZ6s?l3x+uv8?l-Lb(yR8Tj~X-T zPNq>m{F$(MvdI_oOhMD2EJi_|NsFZ1uH;i;p?SSjHS*hYWmUEb-?a`ut=Ddn-``oU z|Byf{*Co-xvIHnZUp6^Pm2MI|V_``k_VWesO(mc78O6~$n&X-;RH4gQ)r@9GbIfN4 zdXH|WE9Wen5kI&&x~`J;5W@FiT2a2XchOn=J6c7a6@Qu}VBnYZH6rV>CP!U#QL72Z z19@zzw{uRZi2!WXr*$qGDNQ@jjcA~E5>D zwi7G0Nq^t4`UTbhmhqDR9x3++to8fzw?Y4Dw+Q~g{r|wVA^=j?KP|NDzgS{V%>PvH z`RivN{(H~AkM*DS@K0fjKRmAg<1l8oNJ+iKVYmLQ`u*twsjlWHiXvs!`L8|fzt^HC z_;(wP|60ZJ|LLFpKO6=ta(CA`3L5L3qh0(m1RjPj1ta>W6U_=LDnzFKdw5^JejVjw zLjn_qV*p@|R<+p^+l>8${o=9v834#d0v6c^a8JXb%KsD?N+R;#>!GIP)C`w!TNj6= z`T?aE;Fqg@xHpN+22(kSm}M|<>LVII%8f5^Mmfg8|5&siaZgh6Jc;|7Dg&# z22gxj_j>8WBO=zOoBu`|u5PDa?+V4HSFsBW;5`2L0i(@D{j5)vH^(S*^+xtcZ-VSq ze~ZU2Cj$kCMx=iIo4cHxoWifaV5JPKc5|(n7gnE=0dsW5K0FC~J=f$CpN9mx?uZm^ z@!C-XsuTX0YZd|sM5B9>f8QyqVCi#Gj>eg=b>cV4LkPxTC^h+X&?=21tfQy(#Y(Qx zN2{X4LwB8WJvh)OK?gB&ej2@wKH3UqUeCnD#O+su2sQJ)2g~RgXm@WfIVGjM zk`e)6!NvZh2f~iCsQ|`jp`mTYq0kH-dU|nTt1L|tg&W(`1#CZ4ZH_zN;!zNIc}^2I zGc~ii{F!xs^?0yhfHb_7+?&L|z62?2>{KqF~%*ljQ{(ZIWuGFKZ3u zdW4wSkG2M-H$F+C$uvkaTaKeQom9`69d~g zs%=mLqpW%Y)a8#a)xv0Ipj2ln!5(5-up`Ua^st<0^&5G2x*os;{Jm|tHUu8e`kw2& zfm6F2XOp7o;L)nwo39R+(BsL;$#U0MmoqIM+`#R?q7d`4Tu-32t*t7m$LqX5c*N$x z{re$j2ODmy{bVxdKOVTQ4W>EP8&v27o-W}BUTle(_^jQ{5(CH2I9%l=AWQomYqkzj zn3@xa>Z0&pmi#$;{j#xe&&))Wp$S+ziOh|Uv|N-P5EfH*rpiCh+k=HpI+$(GjE>zp z4%WKI^jie7v@*(@d^X^+4^uVkk>fjQKTmBEe_`C_p00ajYm)>@r?wY#*!+6I9cWGW z)$;Ili|)~yhIgqTGgzu<-DBk}!P5+M%mv->Ecyhs6g|O;$>5Dj%0ESUIOKHG4V_$X z5A8~H+_ButKh?_h0Xvxf#9P>WJLEtj@f>3*xpRCSzT??zNmQybF2gMNv!~Wbc^$pi zA-I(LMCHmw_BK;Q$$}04N~DZpF>=dxDDw4ua4gsk66isx6{V28(I7M}e&|CA3@_eT z!;^X|?GrqKP^$KM%<&AYHnJQ2EN{P#NjMWMioSQ=ndg7~!jdm=@@;$UiVGGEZt5Qr2RgX@-?3PLf z*x%;@_BwvcSWaxJxpmH(Aj*+;CuxSk)kyEfb;iQR>$VpTaT0@7D`ho)UzCZ?B=!ce z(Hxn`vIi+z$i0b5O9mt9a2DC4{FNp~tJH2A#Gu84h`gWAIqq#0vC+I}Sqr2uQp@Sq zYoi9e+U>!+<#@yHHy`kAZwJXvfAZkb^Myzv3^Z5GvxRi^d8pRM@<<;iFahVR z{qpDngTb7ht|ZV(xUzDnLq6GzWYIDeSoFjIUh)9&t^z?<{5N z7yz0ovKudK#q1BQj^)W7FoJ75`b3wxRR$sn{osbO0Q zZcem%R&(%!I?zKuf4-}P;>D^6&ZnBdALEDmN$+&GGB(j|5qS0|ZVQz1@&^kWGx@wUR>_CLF42XC2_%DX<%8fKs^n2MyXV!%_=FtxNmNE0P2ljQoIq@@Z92TrX zLik08^*d*7G7Bzd%6Vfg&EtP{8g(1KI;P|`;XQS3?C*DPt-$QL5Vnj;M=&n#Y6Igl z2@3ODA6YU+p+iM$5GZg2m4H#AQZ+T6Dzd~Nq?32Xt;m+r*cEmJ^wZOt`B+Iqr zO%d;?ofL2;O`(~je@&v;AYBcE-azWu#@=9%#T5MKbp?(a;*wHfjqo<1W`=WaGRNH z6s!m98>7P^Jx-7IG`+g~_?Cx^>o@f#F1uZ8r!e89gzF~a*_$GB+g^5b>5U? z=}nwed2PHL8S=ssvDo5nd`g`j9?R;NTJY<8?~OUn$M}1w5etd9Gq85&Q`lGN=({(J<|gy$|eT$ z6=J9B>?nRes5J_ny;nK8DzK_Ho{afBc207*vzU?LM$KpA$kB*HIS3A>u+&`r_v!eo#0AYo?lD!&zf$TLU!BKhHL-Q1BUR#T)#$-9td7^&Ik zd$jJ@O&}nQ%LJ#s%8YN!4Ib1GerqyVyA|{V;`(U3_)+^aS*}xf^Kh^D>FnEWQQeq% z(d5Z_AzBF+HjV(UI};`Bc#Ij*QZ2E$H5=6_Pw4Tq%-_^GC@;9Al~)w_#iBaNAK>~T}zt2W=`vLRkj%rO@&fE)*zeQbYV&g`d#r`ayod1OgP zm|hgR(=o%Ci?im`yslU1_K-QsQ_+%_QDNp+%0QTFno_c)hnQmd$gSAFvguZ1%&d@I zXOWRYD5%^PoRd2X-~LEyj)g^B^Ls3Sn5<-x(c-9d9SJXjTIjIE;;=6mA)UI>H(KEM z!x-Y5@y$IOnogYpa`r~ZwJ$Kr-A2(jdKDO4gY~DlGfx9#1+I~LrQzNvrkhC1Q{PF0 z{RTaG<0=PlXVQKEXy`1?KnXIz#FvGrvQtcy&R;S2mjZJXC>NFcv9ViaO_&sKYPf>5tIaeHV z?U4G1+$)F+a)~}pA+6qly+Q}o&`PaWE`eYnA9@35XX|mC;-BwB-V8O3Am2B-la5G2 z7R$g1DNehECSyy7rPh%{3QfD;Ug{`<%;4+CL=~sps4IUe7(DC^Sk1yB)}My2GCwHx zetEO|(|M*eZ@cMRbkowe_#k2TYY}o5TY}9k#^xTq(Hw{sxx1NfygcD zv=Cblt5o9GH=4PlD^MY31t5_YBE-ofZ)%V;YN-a19FC{n`Uor@`jrp_4g1t>#W0s_ zZ6g`QphwPYcHHY9p!fh{V)I<7dpWp{m2eY+*R+{x0~%&cdfgmAweGKner`4qEJ`$u zd^eEY@!7nXe$SBoD^yF!S10#dJjq(^ z`-V9IpQHI%=_||&+=W00&_Rz2tPcBQ{r1f@rDLtNBL2>}6N=g{NHuHqUQ?Y2E*e+z z?uNe@f*LGW7)-oE83*5=05ve7xM zS|1Wiswks%1gh*Lqd50g>k}k)rOF+D8dS61R#@I#63=R32{I$RiiK{H@SkesdoOUC z8*G!O5(&>UP{AlaC?Rn4{mV&%;qMx$^^$p}n;Rx)BH1{Jp$SvCmvtBOGCqM~UZzR@ zpp}5Az?tLWKJhrsDRA?O(STV}ll@x5VazNdNawO^l}s1cVX8INUL@QFJjt>$R*aN@ zEj=}1u6;)lA1dE27IIaO%b(nv+2oB5URiWE39va=^`ljXET$5N#zDfh!SemakP1I@ zen8x!Ro+Jl;rNlipu#m-fHaQ1RoO_yhBnfUvL>Oiybx)9SvjdhCb~FQVj!W)ffuZ( z#QgsVSNiV{%xku8NO`fnY*{N4=2?%seXD#S?RcW^+fG#OCt2NVri?{ow3L4;YhQ|P zUNrJEqja|bw^(=&Cq~jwhNJXo9k0kVYi}C}VX(w~_E~`hYzh}uuB5KM0pMD(fCxsm z`dl!DL!C*|6aBnQr($=v>Ezjk7?<|FVCB8CXwbIIgib7qoXF5I60^tJAL;iWbL+U>euODsbrZScIQDeQ1mW}XkhnQ|B*xF#M8yRA z6h?DTB&11*Gg$0X?$TkiVHTO5dd+2#Y&6vG4o2R1@NDg6k(n01HKO&jBiHXmA7VX-=-R+2X=<$+QZD2=v+kyVIm>y zf3?TfOWXT?>z}1_zq?D>*?BrozW`*!yFeIQ`QAwGb`^T42&H1Hdhp~ssi=z+l6rXF z>R!3JfDx8rmrY?%EyRBd#m@EpF`9Jz6t0ohk|uZCxve{7B9H%#o#0)3?FR|i4*2cn z`;(6VFiHAi>&@kBOypO~pss>-@6x$lShtJ02sGWGSgep1kNGFb^28qJ@1`MU+H70ggvjb&9<`>m6ZRs@z>#?vw->pZtnI-By z`3T$cKDOrNh70x0bZmJI=Th%i3D(;&zKT{g?b}CAnJ%LqhTh9yUA82xu|!%!E?Xt< zx=r2t$tfGC?-TDqfiJW)OwojCj!xSE-;M=c!*fn5jTb8?uc@d|yazbt$f$#=;y8DV zHCtPZ@5^63I;ZuFW7GAoXpOk3ziKHStVNu^b8x+`AaWg+j%!Ss!@g>w?{u}eOCeMJ za;}JH?8reLG2DCVtKyN-ocu)30V(yCufS8Q*p-t2Z?%_*9V9z$&PSgADIfpUm0gop&w@T8m~QazYO>xI&eqAB!}>U~`SO6`Spwwg_acyn@RDM$%Jk!< z2IZ1;c+5PYkuVzNphBu4DAP@59CzZ|IE`8F&H^}%39?FLEkqHKB$j4j+_ayn zwC;{3Bcc@y-`(ByGcnJBKt=(w_-L_4K{avEOfB$g3;pv-aJWFHG$n+fqQ4B2!90FRI)+Wz1)p}iP zoJC5hnv!Ez&!^065*U?GG9tI69of`3ZM_2~X$;nbrc*e#eOjgS(DDg46*F6w_zgR9 z$0m)4OXe>1V{Aox#d3Z+xvlBkL|LRBBl~;v(yQ6waxJl9XNaHUwL^x&{f@y0jp#%g zb^pOMkukeIvD(wqUhc;1P#4GPq*-gjy(Ly5E!n)WtPxY8BU@aE%oXKB{mfnuIc8_? zpK_Zfru>_lrVDE#bhQjhzrv0obI8% zD3XdSYd1E#a^`d403Ftqd8evceGMb#40G+A+^prK%yEw&GxITCN8u zOwr(o?45zy>cc#@q_?yhos2P;m(Wx#Y43z%qvjMv7n1oOAHfOx;)En5Hh^aIjzJ>1 zKrw-wo<4icGCVR;(5gQXpPUjk_*z)A#zNuzaP#RvG8@z%8&l%0u=%twl`|28gkIe0&b`Ek~8e zR}}^#hSV1W*ImtSw*V#gkW0I`^Kf(gw`A;hvfX1*GdCV+0|jXQgD=Z;cw1XrnY@j$ zv9aAZzeN-mKb)Jpy1jGp_xplJv+JsKV}l~U^y<)lxA}t$-q=G+l$h%W9KB=Fqs%~a*qDgpRY^FIH15JB|%`@);D0l(jjzfe$%$C&H+9WAv3`?>amK%fH} z>eqEaAZAVwh{CvGvGC+m#VRso|~LxphnUy3GM6vFptTbu!M_e|UILdC&1{Bt zgTr^*vAXJkC##ZDzj!g`Ae^34j}SGzAf=#t$9v}@-&m)Ar3^BH7yG?eYn7yJTj z;(tB|zrNJ^=QBw6JwMZ*FVy$_{DaA0)$kK@eVSqhHa0e&ItooIZ{BZ-z>HKn^?RiL z{H`db#kv)(+sSeUXa=2RprcdPiH?hlbNcY?aDpNfl>(#AA;#>Q5M$e8ymNiSe0YA8 zOhn@I3kz>`CP?*@v6dw_UUF$f!#0=HlHEUY2GEE|@1^FGPV3*kIMis{{?+g(rUYr1 z{900j84F)f>0-?c@9m^3Iv5PbwAQDnOOfVWzeOd;k?K~wHm2foh>EO9o}wZj>$la5+v**K1T2qJZ3#PzcG`Fjkin5(}+2r=RWb#p;m0$1ioLbmkSJw`Yz-o zrTgNcMqRSW9_<$r#BFYxvT&S>)%@+pr}$?Oj+mRt^1iX2T6^~F8F4}49J{-twEkg` zRD^_tw%bJLRpY~?J>|_`#MKf;oJuhDl<@*DG1q}hMgP!DJqwE>r;>U@3eGq62^(j6 zo?eb4Cf`7A>BCVe*ruP9%ZUEj8!yyH>6c@+C;nNw$2%3&+Q?I~j=?H}1WPIiETLDV zY~+ui)wi4Y>_O83nb`>W#hwrr-rVicD>ALr&CyEMH#E%lA&$&x!>KX6@XaLzj&EoF zm5v#tf^*~-{UDb5Y7B-ejwQjpMY5hM^4&Tfei<}#!xSOM^Pv=+(RL%NMqO)1;Dqt| zT3)};yDD9AruRR-==7Uej%zi!&KaAAs>Yn=11x383w$E+`(+Y?KvpYmz*LH~M#kFC8$ z_X<6wKpRb5*|%3K`s~*WLPEO!{x$d=Q;X`~zdzH8;k_3We7COm%+o!v^M5VLz2})Z z%Nv(ppX?w;6JbAZBlP<AC|Hn*c4#F{pSqrHmze{!BRrEgyUZCiOs1q{IPi}Fsu^Z!2CG;;~l|uo`MX4?+6>Y9&@K0tWyTlpi2C^Bv%XH_ld~}d+ zWso*JEt}{@A55+I{H&AT!+HRaC2b*+NqeMutQkG_A~r3q@4IOW+PK5l;)RL0CT zPcv=w(D-xwC#!p`uAx{snULnXqBp%0G!FgWXW-YNXhYw3J)WT8BZlkQxS#;8D&RUt zCy`%&;3lHfwDm}8kv$Av-Zbewa|d_*(e|TR{7fU=1U|~ew02)FGE9IATq3?wrs0&k zDEI>Vhq8;o?>SQJDfwSx+7a!lG>X?yAp=rg5>aax@7U)Nxb?tk#%aEW#R+*(zMyIG z>1d8~eFP zfv0wBc$yFAC37{(MpnA^LG@MAbBsfY>06T$B<8a+@yx+SIRhgW&-u?)G*~^Pc1;*p zx9q3z?TZn$bm2--_1rBB+DL$gZs%7A)VKF1D+!N`$Ww78^9f&Pyx%>hI6P<15Q^oa z#Ez;Mi|%-~?dglMOXu;_lr+2R(8f(&CaHL@k4caX=bj4*MP=UXtX&2rS2&cPKe?qd zbK6V^8=&Tb&3v`iFnIwdaZj)aM&Ls^Z(0Ow^kam^%2J? zt{fQ`7vW}jqht9Fi79d`d=g$7&kHOLI!xSkZQP$q`_0B8*?bMdAf>^V`-&Z;b2nGBN(+CUg@_Xl-JFHTcSu* z2KI}9uaR41=8R5Wp_8*T5fdtc4yh}4^U*p_=a(4J0-i2EbM_=iR!(v4b(yQws#sUY zyv3&$g^6y8W`T_K#!(NA=W9AiFr;mRH{J|&mvKH?n$X#?rEOPOuS3Gap2gx|kC;1oi;;YMSw4HB%^>*`v^Ngl;3@ro zh&ot4*zfS+uk{slCszxtXs9rKHSeUMD^L9RW|i$#v!b(4dEPb&ju*X34kIVh@Vzt= zI)ip&K^Q7wk)ie`uUSMhS38|FBc*}?}jV^V^&#L$W=85i9! z!!q?5ozeN=TFsdk@kOp!bb5DOP^Ms4;b3ycR%VW&oIxk!sVKuY@U|b_Q)FviqJHIr zw_Ldjj%oY=Dyb;Xh+RLNsigNJslH^RqC}S=ca~R*x|mibM+mXyl3zIrr4MVO3W;pV zfy#5;seL7;g^ZvvO>DQHNlB;wttKO_K}=+j7?Mo2WXv3Q;dt;YKyu7uDeTG1ReBp` zeo6-4t71odTZ4VsGsVi@M|2BH6X0W*%^bglF*ypsP_1D+mnk}RTaHjEx+5-YW%d30 zW~yT^EnsUf22(#*mBES81Y_*DQF*?RAI;GH#tMPH{ZF*Py?ygSBBtwaMi#3^2j88~ zdz%~Qga4u_Vy^$@lXl3dMt+qO#wpA9{@O=(7VE#*Or0rz^Y!trVq;Uk^NiA5I{n-q zCuMeerVdmbc;aY`KCdHcks+WR=irLJj9SJfW9mv@jV!`niE^yx*>+JC=WF&m(pb$1 zr8GkC4J4VGO+6`&Nb{5$aax!|#F%fd}%PW;L^4jx{ZOjT- zM;&J4n+DQeW!^~k>Itcxtyd%IXPv_cV=q>~dqSQr=*XL8=#Xub>*2kzp=HP2X5Y0q zdi71s6yVoh4!l*B;bF9V5ek@dsMmXS-L4R-f4Bsncem+A{`!_4w0f4sMaVvzhccws zd>aW}s6IeID0gDgRqa9PN+PDxangnT0Y({Qf=r%Chb>r4%%I0yB++G%N*=Zpdp=W$ z=CE#k`0A|MdUBNbPZY89^dCZrZoj}UU0ia7k>k*>vLYqJnKG$C%AFBh*$p~a#r(nL ztd2_m#RGCd=p%1lzs}8^q)|stFOeD88MH8_OHEwI7iDk2(RGRAHH&`4ekl6^*%jORWoWeE+2RXW_NhLt z+6CjlZ-}>KQAfP<8^gl=2gDHrVy0W0bBr4=xpUoTLZZ(hsZyQPd*B26xcx48X{nmI zeJY}Bb-+xspLQu&5fm@zFb-##n%0{TqGc8NocIiy32|}}C}0LkufrAU(E+Qc-hRPe zEfSM)qYYiKAJ^@yR3>1b!t}HVSeMrcNd54K*DCFM^|`Swn;Vo_X-C}0^Nzh|Xit;; zyQl?szlQ(VHG|I`&&3^XLUemaI!veg1TeBJ=Vw_cLmp9OZLNepp=}N#y>us%xdQJ^h{11+M<}tTR-g_ zG9WM3)j309U&1>Ne#+26F&jp`XP3Q>>&Q311NRENX*yB}jiTIpIaKUS;Ossxhw<08S zS^-wDc7W@qf-fe_2;A#vl+Lps`1ffiif0Q$Q68LeDkR*%%(wn)0~8sUi+B(+!&u z0S9F7pr3ia%Vv_?eDsovmGYe}no1NfaA=~iN;<8nnR2@XsNK4}rZeG3*Rn)!As}Xm z8^?=75>8h3`*d>UzEuuc6id#gv={eVTAHG4E)-<5%zntoYRS3P-$KZ*T%2$~k=^HJ zkFwvP>jfjq8`8B@P zy-z9L7IIz>nsIAhEXh~86qZyC77|PRIxNcE;4*6^*xHyi!WTL3g+=BRx;AAT)w4&s zwj_m%^n^^9mqUPH{SSqd`+tuXuprWC~r_05s zLUexW$*qkbP11<};^5IWcZ=|FTrn-ev&1!Goib0t!CkL*^7Le6IN{T3M@f@}v2e|c zP1H4CY$u+|uy{iYYCnV}q?@>|Ov{W_!&<6q8}f>AMi;ldA6|4F9>Pq^&x~b@jp-Ss zemyvAvfwjUT0j^k?WK&4&Q$X`C7ID$_ZkI#^+J}P?<(Q%RSX-poKj4LHPA5QICJ-w zd)T}{u*||T=VC`^mn`z5f}dj`*6n?*=xPjRbG5jZu%KK#BPw5Wu%5ZrGrP;z$*EQd zCnHhf)wDK@AtLnbkR*4b+L?xzD}kz3nY2FwLp(+Emdczj{`1gLJx7VpvmmKpiN=83 z&S}VB3LG{K$Z_2A=8`OaldTX~hI#^j3&y!2o=^^N#x2f(I|OY0PawM-XK8AheS5yR zf9ujM#X=5!w?Rt10RW1BlW4u8uYZhuQFmPnS?*E;pKLwcAT#L%pZ&C~JlB@9^+0*H zEeDoTv6@rPBf3{%W58`g)~O!9>^T?!ujXH!)B|^$Q1ylno_v%NG>_a&svLKlk~OO+ zyp^#=%n-Fe8N23SINo{hZo_n{on_LEkFZO?4 z^riqGh7Q=_56juLvvSU9Q(TslZr2f8Jf)N3I?lcS0StlIEcj~EWu)-L%M-hRH<`2K zeml1NzYaitBn`A{(LW-n&rGpEgm7g#)&>ahmHrB=K%n13fM~b$>QwWuvHZUYjk?DtS0529y6Hs(bNf@L~ zP2H;jnX~I3yLbz6-!=JT=ZnDP=9s4+(Y@QDX-I|v9VsJOmZ<|hdLQ3;Qfw|nwOMYe zbkXt1M&x#TGYc9;B{ zDFd9Vk<-V>Pm08>;tGnaNq*94ZbA>}AW} z3JNaAJe)vOj+t>-6gbPfa7-|5g9+Ju>D%UE4(Iy;c9 z6m6E~o8qU6VT!=Q8@E2^pr1Zb#a*L=xIh)__818Lw`PxB8Q+hR@A&UhBN{; z>yJD3Z5&GWohU-B2TKb*^NjhC-2sx%Zc_8h7hk@RZu}hIABl(Nghf~w)Omk+>(HGh zCovCFp&mml6j`Rm+6SNJ$S>%Zdip*O6+p=0$Uk8}NN|zzyCctFziDKY;~T54Y(@;+ zd_Ko#71bZc88=%< zgVBas%py6m@5fq*I#e|HEwIZ4MOsukMZ)B!+h-8Mi@g(EP*2A1JeM6(1{=Pyyjh*g zP=r$LBVFa4W=f}`2jLG&x_Ackl6{C-TRCHeSSPG){$TnjEDQIs%g|nm4@upXJm&D| z<5;B)-UvoZcU|vP9;w%3@m?s;Iau@Uu!tcLmF|Px5X%Rrrk}1&E*f3DqQ*j=&poKX z?C|NVBHu!A|he=Zr;|Un{q&C=gbl0!OFUi3gdFMymPaY@vMBSi!YY|Ch)RhY( zPS|&-FVpz>R%J#GEW^&;B{^_3Q=1`mQ-I-H%)3#3ZDjMY?F%r3MxM>J2=ncKH#1h` z3-^dlGSmX=G`Cn3p(AAtSx9*8vx{_7DIkbV%)%zH^?m-ztlPQ2el6}5S5JX4PgtNm z_pzmF9y;*@TNluT2yqKXmVeW6rXGkZ^=Tp&o zpWRoO?2I`%S{|okq3zASd8cCPX5#pRIAT4rcH!miE`vH^vC!O1@gHV7fr%JPJV|T5 z7jLmi5*wq=@250z$KYPo!-$KU=|Vo{okB9cAN3aNNix;>^JLfFvoomrTE<|fas8Ac zR#E)@@zg80qC)rL`IrlfMivL%k3uZJ2o=D+NI2L-!nmuE@77A<*UeRo>)b$wMGjtZ zs>(e7W6?TxU-3j9J4y;b77oSSmVLMbG(zBF%lu8`SF#f>tyvxgEl!#dGXDv3Jby>l zeM;89I;OCh;aU8Z$+!QrsB4c+H>yN>pgQ69#jzI8lhwzg3m}{9zShWF634PyyjJXU@fcVdM{?6(2G531jpk^6Lf{X^pr|8tbR;_Ee;Nx^D8u{n<^f1 zV!=YM=b0fKH1)??JjU?aFU{zU7m6naTi$wh)wKKKD(NbbP-A*N_HU(eU zNo4oBfAPIhvw}B^_ZL4|{|F{OYkUz^n;RN;bNU#5aq^r?3N16m<&u6ARn^Qs_l9PQ zX#ZHleXpq!`2zpDXDe}xGZvS=>2)TN>mBdmG?ZW6jM%88BAl|BA9rGGhU|IJO+oc! zcY_am3dmEQ+D^T@W}FswjTYSfA~rBncv%kRLOd?#>4d^VZPO(-0(+oQWx(i#}F|E*1j&O%iVt{#e~Ssd<`8ac2}w7d4OP+ zF6e>eq-H?FxboefW_YbOOi|Y-3_OGeL|J%BPAiP&YTRXVLC$c>F`fz4OZYBzR|qDs z4dmh%^G6GCBlX?`8N%z4s!bfpV#Npfw`|PVhaWFcd!+r{qD($d2cn;c)T|@ zMplvq$?waHBEy*J-h+Hk>{~wWaU3Teqc6U;oNb18>pb3%$<=vj2wh53w5WmIb~ykDb;<`V;3u7pZDT5C(a(XVb&IxxTSSaI`Q`z9|E zLXeTvS(yfdsrwTu@36Y`P!C9rl)^#>>S_`&Tb>~aGH&??2r|~*=b1v;Od5~L|H9+^ zr$O-x7ygdUQ09r#Y2* z(bDa0J{hd4uoq=hlj%);KoyX4?@=7dprp)KbmviLPC8ZIy+0}Ch;VFnJnn5@GM(lo z%Y+DXG;xDZx+m2*4t?gss+@e{VqmD>+U9^U^R@qUnI+$iG(J+H4Nj)43l*`-bJUkx zRgOr$tfp6bdco(6<^#9kWLIT81|@m65axrcT^{^*Kn;vWF zDGZ)2qC922rmaXeg8>}WPK3m_6G(M?#%}3XHSI|gOr?r|?TRQl6SCYLu^q>@(@+Dh zul z@TQsj=+=wKE(=~VjXgFt?*WZxAfQv|4F-lbjr?TMKyDH0(Ib`UcpKQbM4D0hyIHWl zLpm<8@S?uJ3_NN1wxvr=b2WHEr7{kUZz2)0=D=?7)&7Lijz_qzdhGmkuW!M!427@> zhGesk!_9n?5%n2nnRY2(2vAcy*7s)O}_r~L$Jda zHKdch-rN_NhEY@wtRdOkt)Wm>^)?1wllgv-8gxIaf#y@=c#ZaetSf>Wx?xGTb6R;~ z6A(1NIzk7NH?%R%G$JNlDZpybgT54zBT4Dk_I`Kzz-pIGT)yqMya4*>ZO&iP)H9Ga^z!TuP>9FCw-l;<9oe-C#gqCt*iB^>O$0}^z^-S8K}CQ zwwSsENhU;`@_%@4j=)f?Bf3a0WE$L-nXh=Psb5c~B`R*H;}-_>EI;|(5vis0Xj#Gw z*_^Q@L-H4K?W{B$1C1b)#o-LG9pSLbeNKo|N zcw!RUadDn0-fl1po{FMnIJTNj-RkOu5RyDGu9%B)DEf%E_kGB?$B9RBGuFm_;oRl4 zyv40%v%&X_yVHA$wMVHbF?S7Uq(M`Vr4tWn(KE>DYQtRJ}cUqt%`F8DqU z^i1|Fo))C6eR$`ZlYDK)+7FMrQe7ZF8Fq3k`hZliZU0T=gK@Rdq?prN-G6+L<@Dhu z*gn-dsIwGXdk;^?d9PeV!tTceu8kGD&hluQle6Q-{@`UABa>Vmnz9 zD=v89W9HppG+~Io+)H;vhT`6o6naUy)(6s;k6>vZ&^5AnH;*m@6d4blg``wA()BBB zEKj7a*%NDcl167CD0?yA1e^jd?kLm48CA{* z4-NBpZ3t7KsxL=N?NQv7EsKi}XJB4Z7;v?JcirTP&C)i5S}vr|yJIqlmEOfgxBLn4 zVAZgUS+k$8U;vwIz*Z2J*!bKPHhcGkyVjFOV9WJ}Vw1V-RO5vkSIY-wfiBd;khMPZ z+{Jaa9rstB3U)nEpr%al(mgT?%%!lm73;#euWZmoX3TT_x^b6E!{vjP&5`*Y8MNhI zPjfu4UA5q~nfPZRp5h#@m-pTQ{dbf#96EARo0p4HV5rQ^Bewv8lIKU~AABmCht$e- z7jsEd)uDmphWUZKS}hdGEYB}bgi~{rA3o}SROWsj=!kf`6wvZmW_6%myov@JO z?wec^W){)c*c8#XG;tz#M!C6C^Sz|(H(%7&TZY4@#$8+hbU(aagChmVIy!1)k}B*!R_^?mtf4W}Z)XTI*Y=V4nSaHWH%|*KO1iy|&-% zs`^D4;V}29-&~N4sesw8T>+k}7ZTP#+7jWI&;-ONH+AAI?|e^L?V2q0h(h%Pm(>-J zeqDiyXPEalWtS?^FM7Gj+R5p)+Qu1RzCjBf6i>QS+yM*^oG(i&EqRRkfF95SpUZ5p zz^r^j=iM8?q1H+*bCnFJTjWu%>EM)k{V|h3#`GTV_)8iIzxAV}Jk)HF}P|@>Kz&9?eDWC1pcOASFpf_3}QLFG%Me2S%MnOI7FeJq=wTnVC2f ztZu5K^Qyh0gWeUa{6&*TBcEpb$LD~wjwh~71n=!+R>7aj7s`-&Pm?~QeUb7Wg^TD6)0dIIGJt+EOs zkHLqQ6&!`6z#kfx|5Q?tRc~t&e}g!x2Bi+r=lkgVIGVxjuiWaH^Y`g4L*t`kuvA65 zB()9G8%NH|xwSweONbe^NrP4RhzhH=oh3I(P@DO({vX*%8;=+7+9wpbI*6x*;~q7t zd;4ejA(4K|J#rm<{xuBaIC6kI(1&1E|2jY?GbsS{oYM`l_fV|nwej5UBdU22nO^?i zI?n%)Lp62-+}>{;dXP<5lBBCG(MTNos)~){5%s7AzJq8-+hl{0Xw>rW5{dtmb^V$8 zM9{*gq7QMr>NuW-3eue{zwta)Im{>7T5e}gXcRgKin9DOvDru8bo-;q?6*FCo|(I? zAHCm~v{-$YGL>f6)tRfRs>19hBL|BF)?_^1ggeF17J4=$L9#q^m`w6H61qp`Wg$Zeks{ zl+``3aWl>jIWyI8&-*cz;5iB*UBs1Fk|YG;cqxO%i$5T=yxq2B%5$4t`ti6#J4*MS zmFb|3|N8!qkAPhRd+_!a2T8QxiZR|JzBQRI-7NBy1<~0m*|Br^%AKpd7BlwiL=kT~ zJZJ6^&;Bz2EA7Uh+u>?G*m+=9eBKUvX_0(&w`R1cre{;221ctculxA->LDKrU<6*& zjk!W&C2kHJCs5mjV~!CT?&0iEHjeo1VLJjymq1ZE+nTUu6H$klEqVIkqEj9*A9+yW z2{%V(>MlwKQG2Oay$-K26XMw}E{j}?h#GyP$56XQ|NGtx3N3_WO8XSGN^i1sH@^+( zdixv-Zyb7jn0L2T&H3$h0$i|*FE+$5mV}JQgn=4ux5~ZH5*;yOrCErg$+!6Yt7Cps zMk}jb?Q0{Rk%RsUjaD0MU%n92wCQ$V-&Vzq-je+NkRvO)sC7$!QN|!Gv+>ruNq7HmAm`N;=%qk`3!I7wSGXT^hq8_w+Sz0mAVridm8~G$_XTl z0ozsnzM0M2+&9Jx!zm7@Ry+X9az~$eO!B%o8cS1)IF;7dS3a`qi5J6s>0segH|^QV z^V2rhkcUga7}{;JZ@u60o!hgO**=%}M|`ekW!Z4adR*_LaJzjwGa8v{O%1L3PE7C- zWS#DgF5e&jK}?{hW(vu$j&2hI{mTvmtL;6=vdh0N0^xdG-UhtwOZf<;8O3Yjj`y=xXbMrw%R5 z7b-QrCb20;b**p?%t)t;uupooy>0Et%242`6D~VOvRm~K-7i*NFV-hTII|b6vW?K* z=>m#n>qBmc*1KhP;*ztuxWLK*Bfg-*18F1!Xgd3e!CX7i;$`jWI~!y+i=a|@bM7fC%v!r!+L^+^3- z_VL22>)6{fTipYszGY9ta@>F8S1zvIV%FfEd4YYahab4x&)c)Ut8=w&z|*U*=(ab` zso(2f?Qb=FGxH6jkp6?{jrxd@$`ENdBzr{*bpwA&-k@KMSTbm){ozheX&IM{Ipqev|U)^>^KE)EiNJOY*J zI6%m|n}@G-H;6yfFGKZUxO^+WOP^gNBnzwsGiT6>Z;q0$>SwrB>ts+a>V{+{Wa)V? zH0TXXyxO3y1Yhe!`@ngmZFD|pq;cnUA1|4k0fxc8V0L@qyfi9AN*nw-uAr_9>p>T628=$; z``Xxb&00Sb$Mc7s^dRrq$L-1$-at8BOw#=c=CHvA%o5_r$=U zap(i(=uaBu8T&@M0lyY?JE-vpD46Z*%M-G~gByvRd*6q2n{(Q?PItdzrCr4DS@PvD zy>W55>=dz#IF&h|yvg}}s|)7WC^gr8&}=&X`)J*%M~F*P0)rrx^fmqNyeN^hEvl&h zo7;x5+&4dzv_L19waR!$A+gt3-#gtB60V#6aP6O~cmIdr=pVPfjxi4n<;_fYXe?vj zL+U3hb+1FxBRMTai-JS1ift;>zbvtWKpw|;{Iv46pN_W>y`auQy(iLpPgy##2qtuD z<7}L*#Ez#0frhPIYck)8`W`L0kgEr&W4knfRPZnCB;f0tqY zWI>HZFEBksIUkYW2&S&cJv+2zK2ZZ8HR114m#Py1ojUU#ETho&bpoi^)}YW%DgC};9ryxr{; z2;_hyC{O>(VQ;#|a-`yN2LJL~feMabD-9c~keSOMQ0oapcOW&jdlkFv<(SjG$~gWYM}^^Gwxxp$Qyn=8^`{Cc%eCZy9`K+`mYn^e zM=d-ap;#vRT!4$!oD>MOeDtS(cbfH8lD;mlZl222m?vCc0RZn@mi;Enxv*`Gvo|Af zgGUu|e#FI}XZD$oY^?pYY(IYm4RYn#QHhh^*RfUN##Hn*7LT~tPkHpP$tjSh9M`>l zsmn)TAhE#_LY{C=^aa>$tcI=C@5vp<{cDoHwV38!SPq2nc>aRcW)-+MT5axx+gz3gtJo(~we!{l_tg1lJxH;g_eQ=S zO>sCYu3Vuyic}H@`w^!6BIo|M=t9gBSaVcsR9V-asP?xv6jRn^FrlRzrEc?09np8n zGM!}0^j)z8dX{Hix$%2aXjWnLQCKlx&r!A8LWv){&?SlO!jE*A|8d2ydZ|SFGwkZw z0f`W>Kyq=a!02f2!7(jUzc14GaNj%9zk@Y77eXy z9;KYHRkr@>&gUYnGFfw~?{fcXd}_r%9nCPnpRpU8jsyDj|5?T1J{r1pqu|syWtUxz z!iO<_m8z^2E5Cfr@!bwRr*#!Y_t|J<^I7Iy&5q&pyNR8+INDLz>`0O0KAU?@FnG;F z+yN*ri43{V2LcT>bBlOzgtG0jo>Mv(%C=@5@L6~-@{J2*RF5Zk-)~|SC*F%4b$fgI zs02T-JJH=2nEslJ8S7S?ykeW{f3FQ+fLUK|z2 zq|ACiy6nD8ZIH0{?Up9fDw&wS%s8q)dE5dO{%5`0dGFuE{P)g>9){S;tS@PNTU(*h zU`iaNLKuO8^tRQNOYy@j&qV>40|GsK&JJvxQ9Ikc)T%rvPt)s?cz=hejpvO$QQ>u0 z`RY^fr~5-+%yI2~b~VJST!QDj*El4+T~agm$8xlN{P7aJrjHfBPGFDSW#bfA>uqT? z$u1Bv6Ck9ik>xa(rT-}Qc9>M?>G4m@yfXiCWBsK@<{zDfSgfYFkcD8vOJ57I1Im2X zpk-CLI7pa&>Wsg*;0xPfpfYB&83^5f1Pj7()~~UlFo>;0rnqsVu7*-+rsrIidORe+ z1sGQ0#GSe!kkzqm&Di4$Vr8+~&#|s|PlP^(@`eA{nC51-yhQ4cIhBgzG{wBRWcpVd ze!|4RJ^dSa1BjST&k4M_7Ka3C6!{hEx`LktS$r!u*AN7FbD#GHU|c=LPoy=O&kKnghzy?W2Ge|}};xajY+ zmoC7k5`VqPtBomV;WIyTk;kk!HLGC%wx9IF72yuFqo__3v4OT6N6`Q?~*Ut#Qa zzgCL9uHVv+9oJmtJzStL0^Q?2ZC(f6aS5=opChWY?N8o)xOmYgt?0kRq0H713n`6+L>y z4c~$)Y9&2on5}mwzU1US!6$$E-#G%HbS&5ea`2-*uS{7N!)^70pQ6-$kXaTXNh+^P zIGik((utk3pV`x%nI+(v4g-$|npUl`{M<}00|mCN7hbVAq#qDh7uMbd()H=~j+*zl zQDz+rw0?0CmW zWTAE)!EXanZB1*ktmxku;kk`q+Jd0t=E>>wAmR)eZ=2Vso+n)PVPc%`-}uDvcs5XQ zUBAQFr(71N_x`eeyFszQDwfEK;ZzIr=I*tZm3b61;$m2xuvW7Sp2r7MF=SSAO ztFB+AfguMkuhnm>9DjI}?c&#Et=UGSS^isvq4KX-T#fJTQ!4%@*BGUhckt3~8!P_) zzRUJsZ5mIH6HgvH=Db1=X4C)`kUVVS{7=iwb^l4lNGfp+80~w!xnVwU&yRcX#8Q5# ze?%)1<2kIJRgP(wcW^fc+&)+jX$i!2#okhIJp=z}5B5x_-|-*2F0ySD%Qs)9aFFIM zN`fqd<|HaD`?@v7Z35zj#Fojj+`Ipk{`{l_VEz6Vmif)ZolJ93YCK-L>^?nHM?vG2>jG&x6ye_1_q&7d{=^4Vv6z3-n3q7O7LV2uf14@R@T7m<~NI zG?rHqvC(up;mSSVN_7&?E>Ki?&%0PZ7K^VunNF)8*5#NEd|?^8@{GCBtu1Bm70zB} zj=B^Y=-pxR+b!#p-Zke+Iz&{Dx)@qX#s_>7_XDDdC?1F8w$Fy(0#@c1z0vqvSVTC* z5Mw4YzxqnsF_H%97YQ}X@=C0^6qANP+&Zfk@lF1$z~8K5*fDbL`M9;>6u1Ad`IYCA zk=%dA{$e5`{TNncIMuBe(w}be@uJwwe)U)~)UDDY3{RR$VuNUBC%1*<0Fxvx_s6tq zITJ_CX7xU~U+YbPh>6)&d~%_I{R)r(cQ|GJz;xsD1ENGtXm)q422+B1A9KB=Enjl& zB6GbjzKp86ADO@kR2~Og0eJHC5;JEV@Aa}v-$49+bq%mAs$2`f2-dM$7OAi0n(WZa z+das92?V;q!C?*3ee-cDIv-*GPB4Go|Fw_XDJn#dJYG;M&F~CqD3mh{%<^{!vY@)J z7Qy3Z+3)z7@TS+Ni^={5nu}^DBw@3ng7veO731bi4(qthR3pX^nJ#c!F(!`qQxLUT>d1Fg-RU%|iUP_2s2oh*KT?vZE{WU4q#x2n*8bE2{LjMD zr7D2<%HLN%IIsajv; zgde?q(Xt7MZ|_I2q7cuat^prJi3gO~jc0pIxo>VG&u zr0s)|`W;?PXBygN4l0eM7NNWUEM!%NeiA(UvO~aNzUbmjug!F@!#kBG3`!~5aTTY~ z;(&)Q7Q{1nQu}T(Zx^%fHkpl_?-69m;Mx7cyX$FdXuvB8exb<3)&*w%$jp_i`(GI| z?}JPdgbwBjPrPOqyvh#0ZME+LNIf(NnxP6&pZM*@0ZgT@wp7wah+;8E@%G%?LO0*p zIre$JmaEV|0^)B`J$U6&xb)t#&LjJ^ooOsrS(tZao_XekXHuS;f=Z6q)CGyf2)1{v zepX8+oGW{zU(T?2e?%96pK%}K*`hDP4NtP2DzHIA)hQ9fdYF~1^nUF?P1wS~&)EIfT5t^lf9NE_XRDsecg`iD z#wu&S&yc1XW9j^Dxgw-#reAo?_Bjo$7V#X`dqql)xkRNYruytYWWHp3t$BiM-C4)n z$ja2B7-ch;aQ9U{KiX&NJ%~AYTf#0Y+!@L?*TT;P;&0XEwBCz`Op4zu+k&4FF4#RZ zO_uHU9RJ*4}9N|0!@B3qf=S%V4zJC|_WBv7WVJ5BAEx_D;X=`?N24#o~quVTI=4EEXC z*-S*+zyP1544~+suQn&H+Ye`Yjh#phX6_S03VciZ+bKDE{Pm& z1~Gr$wVlvDKnLI|Xi1gZUcH6SqjyWaJ4^c}(_HKv)9*=Udq7oFQN{0OWDS@5I${C6y~Fte_}}aK&!)WhN#i#k&9^{3ivL zfz)&IiKlt!d9Zsu;r8&)EMNGQe44_e&i*jHe0by^G!r{9QgH7`uIH&mt#(b+6Y?YRrvl? z(Dg%{K-SyZyoZGc)ba3A@Ry6*pb>E1AbysO%dJuK(2ohb4zDt;zk>F~rphLVa?C|9 zzDuHdU2pd?LbT{0@D}Nwg4b!d0EN~8hp}7CoL0ZJCz*7MpL84?;%B^HpDjrYv&SX^ZZ|h>d!Gi78NLC_T!Q3lfX{o<<^}+? z=F(8^0_4yPw((neW`7G>tqmOK7EbTDNhB<(F(u<5U;6wC*NHnG;- zZJ+G|QCo^(WQyi_JJoYvy&FTeM>6Vi{1ty!@zf}GDo91B&pY~F39X-SD^x%BQTvB| zu}y9gC*cgG^V?41k2p8M-}W4OA~TW+fFt}T!rdx69W}G`ws8Ge_hqWQ6%e!m-#2%) zHSts5&6+xWE!3KWJ^Xxa$vrx+F0p+;_A-YRK=tV$LZybOl0qQkyL9i%xEb(^HHwjt zrkHANO5Esj`lUH1eh0u!zyvct{nd+|Q&zT%vS!)oPYq@p{p!Rt`^rcFYBQa=*nf>8 zk%mpErkosp)2SsE$;28-GyWOL?Qq}WL?9L`QE0qh2L2^tKUTP9ZFhNnIAtC$3t<$8 z9V3#)0sK54)J#n|nP>iVDjFaL_vNwiesfq`@2gzZy<_ak@-W!oRPg7|yL*)metkJ8 zp{XgbAz%-um6{&`fi7K$pNctTfnXdW)4*E0K#f&bJ~Q)M8e0mriIr_hcMalwx6@F{ z368IY|GvKH_tU^5#|FOTWer0j1TBOYXvPnL86|=3>1{tF@*mk7wf!O))>EJ)0RR7$ zUpSVurO#{-+Lsb`t18gM^$L&X;fn1>0et{k47$H@j-Tb*jl?^%l@ZwL$*lVunf9Uk zA#OXp-2N2X7o}6d=FJ3C$G*!kU@z`GVa-#2OhxacW>xp6D!%ubMgmz;Kpua20WlOvS?cqThZw$ji(lE>t44Xe>l~e(t5yqpBJgS132>mSItq;v`JsP^{O2z zpRi5kJLgnc;IWreD&|JDZ1&yzc}9&Do96GkK7PBweNqD9%=&5D$8KMlANw@YcJXsD zb1d8gxRdueNyhj8cV`=9t<%%8V&0=OUE=O6Yl@O+Z!3N*r44Lq1oq;#7G;}E+98O5 zGR4tU25e-lh7w zu6Ms53M^n-NKOCS0I1l zyrW!6oe`$zIRlFF$mT75ZsG0qvm-2L2MTcCu8E1nH+f1sZ=)k?Kn}b;2_Q{XrrfiG zIWJAF?NdMOhNvvLSQjyw0#LZEs(BHhJ%8hf|4jzBx))G&Aitl22K-W^V_={8E>P8_)~NsD z&o-I7S`c$fbPX=3SDMB<|n#DvaRC9uhYfkKWIgG z-oEaATU2y>i~M#4X1bMEdW~*O-5paH2dGF1!&zel<2c}ua+P#olpe%X<5+M?e1H~sk{rMHt*8*v8@vb6c5_^rV0 zf?3MC9SNg$!+DC%wiCuo1*Fli{_$oo3Tw;4qHTPd=Udr`*6Hz)hvnVkw-=$P&d>N= zR|&E=!iCN+aV@{ixd#*(&(&%DZ-*19Sw!98zM<0bp|z|yrT8GIx}wO6k3PDnrGpcD zKKGvd(VIr$5}dt))r0Do_owbmN$Ra~Yh$hZ6+75WxuqdcBI?D`;}<{P`s}t7FOVUY z(g`8Ms&Db8V?dLA#hO>q_B3C^OxhT~wWNii{c$5_p9;@=D5Q0uPE%^P(Dgc1bPUjc z4VaQ{_#EysvVzq_c1x3DY$l1 z^sRH!*Wb}A=3U{X1%5Gnh%d?e7KLd!S;XstVpu0TdJIa|;D@#WxhsOBFy-$rAgq8w zvHpIckK|=J_%XEc2(2cy3^+#%R9LO))cZZ^I5(6 zx}`upC?7E^dLbv--O12|`u2-;hxs^x)Tc#<8!aGI=5Eu5l>db{INI8i;h%=vwqb#_ z?N+M~%=Yxjs&BD@hrpU zI_PGpYfVSYqfqmApYpFeUTepB{Fg2FuZ8%%X8)JnS>Vn$ON4{FKokc1={T1%_h-Z@1~5 zj1&WiZIy_etV%>AZKLP9H>5IqKCtY>{9@n!b)&C(np|rwiq4idG()hPGFhEPCElqH zeH6QPt|-F7i72+*{rqH1TnXs*UM{@Mv*Ti41kW2?pdUy@(^7YOe%l@$Le<7^z+;#*N^H)Cw|@bE*c>d3v~xD>C%H?$0onSoX?e@eFY#>`n`H$b3^m~tQSyP$<@)JfY);0CtrU%S&8+B){3mTjkqd- zyF+J@LTR9NUBkFM;GsQ1N%-$Anr@HK;qdailhix@EmO=_?#$tpW^$8}iADZB$4iN?}i?BMaSe#rdbJ+wvU75+BiuKAXbt->qV)3_&R6zT? zzoXtA!D3}GOC)jJhd(AQBpLh039KDXO&O zt9X6yc*!(*I}RV!G0IMG5TP~`aW+%BjKq*M~xn`l| zub=$O`u(u(|Jnh+2g%&?L)sd`tWwhTwtiT7$NGudj9(@#J%0nRXb&YPY5bX^KHV(% zA|77z=NKMaY*5(lFS~^|_5ZUWz)Se*HzEQA+h)#v55ayUsv_X)ZZTvkS#Xld|9k~R zRVP|r2rb;6cqzuKe2uA$3l`Q(-XX#8Q|8VlB>i>#n-BkZ46d#^lQf9h`UgK{jlcC$m2wUnvrL9!>8pGYmdeg9bY%v}U=v&|zZ7@2pKFw;rZ3V|xSAV9A(Tyt` zV-!6W1s|#F^C7sgLYEpzZj}aiO+rB1(CL=nV+^e3P!cjr$v&{%(^OE!M>X8KI0>EE zYWR}{pDopRjknjPF<5pNKP75;C+8n+Ij@JjM_4QI#+8S_8eO$@hdf6Vu8dVj7m?Qn zwh6>_WpaMP;^*j%9K!fk(J^0 zUTOQaF*Yw9FYPz*h9Z@^W14HqN3kSZDGg6Cc6JhSCibx`$qw$vJiXNiLy~*cu+Y7W zU?yozfTxJHbVoMvw(g8(;p_@)@TE5Cs5hPpFn`Xv-bQ1|0(E~9M@W<+(b_r{Y9m(v z#6(P;dnoB^bDV3yz6L8{U4z4;5t~^N@MoPx9IV14I!?arTVg&36+(3t=%>^}HBs85 z`9?F8HCKIozGNi#?iN+Z!w+W#G^NAAf?jAVcy-wQ@9$ zM^&(l!i%hT1)iC~+G@B=P;Uj`O^CTHn;AtcEx56U%e<})zjCReR1tp2*mA#Kt@QQy zbBL|FC8+l-JOR+QKSPuMNxiuWN1_01?U{G_8&I2g800KdT`FU~rN&vf7Lo^TEVqKr zlyBMRAzj|v^%_(uT4`=dn?hSTLM%5e6B0eXua(Y0ZHc~YuJmqAPjGCokMXhY^Nv>O zFo1T}z?E3A#IBje)03@@%|z^AP4n8N%}553${hdkSDRfEPeyL7PE1du+)WDwQfk~? z3PVpe90q;A*hyKPe$C*59ZFZXm7CeUPYD0ARZ4u543zbhY`IPn`zXA7akEnEV9K*k zE?_F|(MH0WMw&dC-5%Snn=bq@{53Rh$`#7DQZ)=TOGsMM(9m$}ceznw_6`Z!E1d?9 z7?SShEbNR{0j71{gLrt-;qETboNPbApwgizX?|7v>4?Q7S~;@V*n4ec-38vWDM(IA zLFP?hw=xXsR6AZr-@5;-Va@xa>fek*xHiIQZY?4ad&FP~lGS~1U}Yd-v2ibhh6?F} zcbTK^jWr1TioGL2c&^P#zs5nw9kP5lA2izaL)?7fn=T?~G51Y553*hX5zD1UIIP&R z2P@ffml48yM9LFTK@!|GCOwrqY%bn`y@_c^^Vvy^-h#U<^?nGcnNn%(3yFJ{C&@-B zC*B0bJtpDB(NR09U)|9Z<6YsSWO|!%IM%OFURFE9c|>;2d~s{hCE?WU!M(_lSxb+E zXMw(aGO!`7X*vN1yg=4>d7zv%6*&A;TfJ88m?xURu^nckYOYe9{FuVnrT>A8RdTbp zVvhd0S}$kB$Y7m}vaO?pIBJ6{d79Vr6HJJ7ljq{1@l@)?wdlt*j1^g7fs1yN_DOBO zumFT-yF)!*|MrjI8y6RfSv2nF%V8>8?{RCD(@b*MsvgchbIjU&D^7r^ z&Jk8jE~RgxMn&(tLG2*ZvGFyf+z<;#`dKp4(p;iaBZX_1ET$wvGb;Br*A~zF6}ve0 zTI#H%kq>{1OxJgq?$aI zu=m9Rw_~EE=hiuo-WXnUbj`cFb@B8=Spo%6wcp`gGDm( z5?&Q%9-tW%+uI%z!#zn9&Ry$CWy-3@O7-a5_!HB8QX4px!%i343N>@Qm3e$SMP`dS zce!r9--6gS8FjS*ndOituoHLnz3gn-@bK`O-XF3@H`v(N07W~{QaBnEpCC#r*gc-@ zB?}}8&g}N6^>o1!`*K~0c5GAJQ+lMG62KY&6v>EJXu>_od84_*&20p((GS9f^m+s> zs7rq@kQUfEI5-gB=QOsHVSOfjY{!b)(&!}6Lw9{2A;5N{);oSJUH8x{W~u&p(Txw4 z+n6pVdIW+*Axm?5w#l#?$pWP~dsb>{>jZaJpjt9{ZEJgr`xsm-czIi%zF896ySxf;vm>@aeffI)b(}v$nCkh7LN{v!1Q4J z^#^*bwf6TTTlc^rx?3BJ700D_Y_%sk2la;BT5&?g(N$uwEFS5({#cnf+pQfT!bcfn zL7K*PN-QdI02S|#@GkPBwdqK%bZ4i5IlZ}25=Bn4399em>~z*$h#QTnezDQur8<-& z|7741nWf_thK8Lu(dMxS2p62G*O%IdfEAQ3?{$JJsxZ^DvLcd;x0F#`Np2Tm3MV0) zZH4+E7hY%$S4jFG^IVxJ609Z6y|S{R&)wcD`iRe+IqqTs;;`cJVJ7g(xLZsSL5V4< zn|G2`K8VW6;Q{k51lhjMFn&M;& zWT?ylRGWpCIvNbFeOrVh`Q$?cfcAE+q{R*K8 zMltsjZ90l*%*Jo-TiljPGpna`USvqr6o_vfm7?9IZUH=0pZz;8#%vPdMQkc8r#w%$ zWIAWI@grg~pX?ld!AJ(1$A}>K4nWkWH3i@6*sK?>*hzx0@ZXVM;XEvmL+aXlQ( zjZW12>>=n@$lMczemhG9N;k-3!aC089Yw*fG8K|u6B?N9<#f&;X183QigoF!vfI+u zynE2;z|OPJKleWB6#2~K*^>CRM3usA45GI{;DUXqUPI*dBN+Z7f%n6%nN>gY^K+u! za=&*xw7euMhS{aovxWwma*NdIjQJDX0M~FZh1sC%B6E}_zqiy42lBokU>7_~!cw+m z{LDAu7ViVu3BRnDhT$(lm;{L?#<(=uzdmS5-3b3D`4Yf2eKzGNhUns1`CdL(h74Qu zSSv!Z=<%~xD&md($cg_-&8Qp$u{^GJN1Xn*fNOLg!fqBQv4}qTBb25T<%+l|@7Vop z+lDhj_ck!KUgfYju>x2M`1l}!esBAOC+$X)5MmNb-?#kY_Soz4NHJ-}e{X0)@ zQus@yiyN57$JLa4C0#Fi9cVV0u{W|$y3V*% zx)WZc1%FXe_3xPjzbGJeBNWgP_QVVu)|1~U;iW#PgQUM!TOT)AxYnD*qH`5&()yIl z*@l0uDyb99{pyMH)MK(f%bsS2H2)i2x-%fQ3J-S+;nOshYBtzsgX%Qt+UvOdFd zJj{*mDFjn8vV`c6n}0+Ixb8mpdg-y`5x3Lz49@1X)T?CQe!$Qe;scd2Xs;4=#P4b2 zWdGEUdwRoWDKl!{l_89+Xroz*1N3Ar>1sZ2Ifh=f0{syrVp^*XsZal?abkOis(hRe z#IGz>)Xe}QlNsF&>6Qdp<5B97gx1!0--tjwZp$hW0fk5YCXy8usr3oJ9rDt?%OgO?a^*&4ywXh)d=25 zfY@n;s+bl|HKRwUp9|xqFkz)>kLD(-W?e$*x>`#IXKJXVk+_@MKceRjw^&@lSIoJ; zQVoCoh$6UrvLs-Pyl-_;UCdG?(3E74mzu{%TglK)uKJ$6^hD#(9gue$eX=4LC8ZG| zoJddyG*k;&tdbs9*+$-YTK%%laYMXLT{XmmFBNmLCN4UOWRTO2Eu|+EqtP!2i)Lp_ zO2H3{#%@}e+E;Ng^?24(Z*yq)vH3tajdTv?B))%0;j8!YI+brTD{bNX*;%6y&s->Bum?Gx;%f(tWS9<=v*~8B|*`L(Ub3$n4J0uEd zgMF4sJ&R?3gtb-^Y>-Nkl;j0pCJE3@BSt%`{Hb|DH*}yGa#k3U<;ffv7zpw&HL8AE zRA6HUIo;4YW$9&<@&|d5C$4HuMQ*S{@@-McN7H;fCWULLWt_rkzm?5G)ecML2KZh0 zTIgo8NWDYP7P6ItoTFb#oX)lkxzt2H{i=S`HqKcfqM}oCf8ix37vHoyze_5~GnyU) z^32-hlBrN~^s)=Me%eB#e1Z=(=?JkHrvMGegRA14!A>*LJq*(boL&d*%yoNhR7E4| zvqOw4vYdQMkqy3J*(nXeZXE(7VD6u&0L+$GeF+dwoUz6RDmGpHR^We#@by8ejkHZxqA_Ey* zNQ?{=9fxV*!g@FqaDVD~d)W4*Ig`q?XG&2B^&&)7<8$Ui0c}#j;M9#q`@3;&2T-~i z(n%i?HX_@3-)n9|3{htMy$k*r+~0UoJ&S_0d&jM|mI`^y*k;QK?oZaU6=X>pX#{S% z*{DTbp3JI9veDSny+3WW(&$j$c!=&6n=1W82tuu0xi;MMebT1XnWCB?qA1|uYJ*+J zQd=m^o^2A7b z62*J&Sxb5CD$r{C+~gk3Y&@onUUF$vP2Y4-D7Y*3&5l-1A4m#6`UF&BZtrU;@&D~q zy@%^FBMlEiGm+%Bsxa7-!^j)RnON*1$%yR7Bh;B&;3obE2mh5Jp28bpSKS~$X4dq+ zdfe(HsMrHN9modR(A5+oh#$HBDAmPa^_B0U%O20;KAu_kLukq;nP8^G*AK%5MtYbg zC@;^l=c&g@`B&piab9ZJ81IzXQCyxWyEOZ}*`{qE<0YOzL09L&@LM<$?f%hi;iicw zQOT*EO?LsG9{-&5;as)lTN#gXl|Sh$SSndfqbCunIr-ycVrhC^$KESemiyE(1jZz39bfAxQzC1X`MdHMKEfB>uw8>}@L-`|N z>@jned%yk+&#-5)PRXH1@@i0|dT@VWhAWJ&#jYJd-61am!k)hS zDO%^rfBI`&x>uzp0)9as?h*={XF2j#8sG}1Ai@@Q6}gb>_!SSS;U!+v)sCePxx6%Z zaH8^BK6E8Kv7eHZKJAswvJp()(gvXuz7s5ibX=7@c8Fm7@xq1~ru#jJy7Ad`D}PuR zF&H-{{+0f)-m>$ASYp4Ua~K5WA5_pr6}7~sBY2aW{RT!!Y_&NF58mJk`dhq4XmED9 zPm5~#GrIN!LLp(!*-AS{yS`YunlF(18`73-c1a8{HNFo~$-T$vl5&@bq`aeGiF-Vs z_xGq0_m(LrQbXo_yVM638@!(r+AUe=8+Cn2Bzpo>X;q8p`rxYFm$zhQS$XEqgfI+9k)Ft+lOrH90t;ymI=ax-u#jModPyMMPCT`iy``mvCnkE? zxAvqONl_UqGoyF4ZqwcAQ*fMnZeX1I>RYr0qDHYA^1JYN9HA znsJ*v<-5bnZ|9{Vvm#^-KGw+b<(z4Cpc*Y|v`BPTcxR4H_#jsB)W~kHJ#1<$$M7L% zu1&fmiExSpl(Mi7ta8{-pn${r`d5ieJh{)~tDF!e<$`9%hcubs!gR{exq)VEw{Pp_ zrZKiLu#zQfbO|$84&wT84D+Mqqe-PrFmKqQu`zKG9!y3+c6U{RYyL?g|q(a-PFagnZ_dT0(hAjG&v3Q|pM5 zYu{p$Y<@38WDPpaAQFoW@klOC@os8=WBh((|IksIv&uq6(oojJP)OvIG^&{-0nNP- z8{mh&^W^`G*V#j|#x(9{`Le*)!=@$*-%%5PuKn9}SGbJp(;a^qHhUwsWK#iuuAZtA z>P;4{NzLuaJs>FmKC(NK+ZL;^nG$4z<|v)u?{rWM!E`Fh!$ZYO=}NU}s}AlcN3(MU z?^f1HaNp#t?VD>?p$Jq>ih3GjqFTUJt~*oIt!uN(ORs41Y9J)8nbeT=W5whxgU!uIL?ysFh$^ACu+&CuL^_eUc;FX+(h9%0ts zfA-W&+T$%)$#1qhp3(pDg3;z0PL`O0RjyS+!+xWnTa!Q$vXRu1z$@dlW@xkE1R~L? z_VuQ_>yBo9&WW|FJjI2vrqR(aZ;TJny8zZ^_oNAvYmzbvX-%bdbf`5z#ue8!@4FN8 zE7afNAU`WQ+uottg&HVtD+U+4$#TY9%N^M+3LME~j2;zh?OlSN^hvr0vng%Nb~p+y zJGK|CST0RxTvmMz2iK^TPR-VP^r;l8rL;(KEZH`NXh~W)U^)c8<~3+zpM%skv&F%- z&6AWOAAR@zW=Yk@Sedfm!Wmw6XvY1;-QO(4nCFvuG?hkIOEt!mJZJ6P2&pM3;*)day-Q)h=0%rHV>iA+UJ9xlMk zLkutj5!Jd^2@6m}8%u{v%`G_FrsAwN7-SKxGGRYzFrmes}Ri zLsgm7P~qLK)nThAwq4o^g(@k#ITG0B+L6#v%dsb+i_PJcDE=zcOv1=bbPuVz(&ya| zZ8U5KYgoA=j^B@-cuFo&QN6C#eOwLl=)T+q&aiDcRuEV3+p@W+opAd_=?xy$IvW35 z8AtIuO$fPxd0YvrgPIq>Bm}kqP4-*KErmwsHG1MXG<)LPs^;HI+qtsERKr}`D%iBt z7FjhzrZ@AR1K=M;>fv^M1e@?Om^% zAQuiLTRYdlf7%zL>Yp%<|JmV(p#qEslO9K(<*a@`x|MLauDZF2AgY}004g-#q_ti@ zc9Wmaz;nGnC2Xh&zcbErL? zIBjD&y$PMh$Sbn%A>!Ne=(6ptG>15^S&teG>&E~gTWh_QO;3!+>{9|RmujT3sugH_ zNhqckEkkXUvI+bw@vHJQlxyq;OwN`}`ATtCePQshpTsct_1N~J+ZUzPM887QLk=4oe;W>ICboeZdURMN(b4PIrz0~AV6_#1-7d%6!Q*7u91 zJ)K7@IS=&-R*cBjp=)*O4w-8SpC=YiLrxXHugzc(O~j68RRKRsNM~pw4KMoHy8>Q%GT$mN`4VzeI zNG{OAZr9bBx=<)upX}4)BF_Tdf{m3dN>`bic8hFmEkr(f0QBuw*(U2z3!P1_nY?U( z>h1|V6--)6*|uJEo`R36#B+lE!OGrJ307IK!&Ix7D<*EGt3W@^U2JU;&Ij)R5Z(hH zZ9HL?>dxttZ_64}oA75Kgv+KenifV_qb_^e_P*Aw{@6`88thMZppK8JPZ|1ge&R;W zjLvnYtb1Nm$8fW^3dtg3q4@28$7RI-d_dc+J zzn3VL&~7}NAX5%b0d;?rIgqvwzS|e6X_BbUhh7PH-{s;L8mQ1^S9feHP8hi__!PY5 zuP4*O&rYAtmg>g0`u_dZ`w^c7LqpZujtb0{6|#u>TTpRKAyF%B-%{lwQJB}lSPL8M z%H(2Z-L@q~2(ed$=Z`lkcT4puHtLzJO_JP=Y9)^S6q5B$s$9sUJi_gR71M#k^HjdljXQ!9+&SY}gk4krT-HOWG@j4o18WFe4ipy05(@fK zxa1wLX;)AsI(~Ym_SETv4BU|Xq{%PhS@ncr-2`i(6jMUv5SqmUgq4&>>iYdwThP!J zaXkb-W+b2Z$wk@izV4O2nd%SYs-!FO85%6fp^%fkDglMwTPZi^V5g1Q)9P2vV-|3J z;S19j5O2<$?(kW>Bg3Y7-Y*WsJdGrF(zUZeyoGd8*t`$C=*)Uy&>W(jgB{NP*@o)b zkn~8LyH%U`nVDJg8FO@4mQKu^%6TD^NPL`pw>V7KFX5~7@SsW_mCqchLsP+Xn1G-D*c66XuXANz7y%sO0WpSKs&*CN@tDM+XRKRtzpwyq zS5RFsVH>i%HQ$!$$JU!$Do6%^cNN1U2@C#(n!u&=0!l#{FCwrq8g|107W#i;K>R_L zIEPdIm3P3LJ>7UHW^gbT^X1KHA!fthC?sGrep%<}ENROqc00bJmFYl*kYPaAv3PgGV$Rpwvw7}ee* z`i(C2JA;{e`!#J07eSqvuV&PQzW`^+#s8MTGe8NZ>;!*KWaPkE)xe+VY(T1a)>-id z{;u}>je~_UZ+w-0a+D!(7nqq}IM*K|p|wa+5Eq|)nFkcO2&8^OuFrv$SH6)9Q)Na{ z6Ys;RwE#HgKVBb!fx|@38~~8XwJjU}5;5l5V|#{m{RNFoJ-cJ;X?acalK9cfJObJ| zsz2l-%+0wt^+kXT{`v6!QT^>qrqIS^H1^5P?HG~0gyNq(*1c@XPWb^GunqwH{fnqj zTm|?uBH32}4E1cOlhm(B{tWA?Qsxsbu)OvBHgwPi{9c97D9pT9`PScg7X?N-94!% ze%j}FpX%=Be@3g2*#LZ~JIK0=9;?huXA1`S`~$xrz~^H~7c#z?feHb3DX=M^e<3wJ zjDK@m;2#2^&nY>m8LcrwagQx#QIj$v5He@(TQMBK+TQ{Q z`kdYbz1WH5e<78SDYEvtgjFi{bqN;&uf@@je^=ptMUj;o5h34SCfGghCcjKq`rFN00FDu(0eQGNL^sWe4 zdT zhF@Oam^-&D;FM6&3xDV?+#Otjf^WC!g8muY1@HyV$#x+%&@RTvki%l;4S*M-&GYZp zjl#f}8S3nBU{Y5bF0l~=sZ*~SFM6hE&W+dTIq;xv)fAi_l%wJ^a=X{=KDFQq5 z-##DMnPxZQ&hw}6fg(M5-Bgl+!oFKI{2-pIy_FdSb88|+nXsK({vnpn^W=|NObw6w z&7ZdYLr(zM%o&5^JXsR{=AZ1-H?*LEUw6$!HfHFptJC>P$rkpzvIbxqIL^!a;*Xv8 zTnb&v>1CuzdNRtJuu<>UukcrYVaBoC=*y_cdAEXNXoE4UWT?{IQ?Iz*r%C`ozsM z<3%jHqe{HnlY;w!RA?Vq9Ht^+IV2rDR<#SwQ?l! z8+DLDpz;UjWuni9tyU+~75wVS)qWv8tMc`)XpV0oKD1Q7M2_nG0~*#(58=Bex_>Np zS#+Xyh91+r-tjD(NJIQTQ)b-V?!+bI#qK=BV2_S;z0=Slq9Q#+vxqSlOzRr&5gQ%i zBoaMLc=)EKc}TD6}>B8h~`bb#Jd7 zGRpaxx1rd+e29z`l9QtV^G_$);@&cztfDtV9|cZxh4uoOGKo?X2e-hcsqTm2)NPPY zrgv{U$t-{Vj3TE(DV#8j5kL6nt{qx*0`=tU?cBB*Gk^=cuHNw>l#lJb-EmaC&B$`- z-I+AJu9>>zF0JhLd3lk+dg;4N&QG`M*`p@VHGz91BF|UZH+fL^2({SbS>X0rt~zlOIyQWA_KVEB2Q*i)?LH0DU!!CAiw}=W_wFO) zb*EAI3w$g&!aF6J;rDO-H*7rZ#KRLMF(*2OkXoq9AH|MCj01Rw)4`T2tpc`;T zI#b^md7d=<{YvBylKAP#M1drAWQ!iqy8rP0Z@YeeNA4Xq2OadYQ&5Q!snIq4>1YZGy-WRP1mAxnBme2%o&j9_A}KYEGq48#3~O*P1O7X| z?I-&gaM!G;iGj)zHuC=sh4z1%%ro5ZmJCD_V{Ut<6`v*Y=Ku3KPav^=K z0W@^eqWPD|`bDY&IQCZ_`I{ZD#esPWI3Sv*`F9%f|G7oRe@GDhj_S{ZGz^f@-wa-0 zbbuKB5x@c~4On)ck~*4LQQ84#2Hn73Ra|xZ-hi=GJEdl_BnZWqzl3^zSAHWA&J``* zo!^O*vu`E(+Fs_b@BU{b4?O(aP@KQ|ML*>q4LbhQdwZv@GfLiL`EXNa?fHCFdA4hR zwRtD@(aB8C)bx@HFk`mhp_Q&Yvyuypg6Ebn_)D$VC*^GYEqP z$xx=!ez~M*-`8_1rcytx+lRr&X zZB;`DT(?JDSv-U(Q1Cq?c=G9XF?0v4D0nK7Y9b4%+7YL zOq7uIv-B)GebscUSon@cI)Ll@TKX%|35R2b5Ei;VDs`a{U;ESJg^Smcr~L_w9kS(% zs5F@>V?v|TuW8WSL|culHxt)5ZLE~#kV~2G^=h!XT{3g%4LAbO1utb)o(3rz~Ui8ltETXq`i;N~u|UoL9>Cr1yQFS|8F_5a!L)#HrWkH+<|neZa4C6`$O)cO6-%v#{>IrBby4 zwc8q&Dft2?>DGiq6Ei0^&gm%ceea{oI5ih~`9j5K!oFf#DcKoDRu#juzeijz&{V&b zAdN!S8#%w^4Xm&7(K`j*r|43p-)zACG=guLX3;{tc zCm)gtk^8$V>%ru9Yo4%irxB8FEuy~gBCD(knAhF?rOwN+^<-5U>w^!fWu!ak^=Xj3 z!YlID9V7Ycw_jf$;PHN)E?)HRWA;$C%JWyn4+DyN4 z?9Y36GsIv^w(W9k-)a-*k68Wa{d*GTPML7^@YJa3vqEm?R(O6rp9i zP|1|GRTj_>E!rRaNZx6@3{NPxf|0vaH#ydR+fqfj(Ra8G6a@IK<#MOjaGsy0wOg~;YGx`yrqdFtzbF(u5U4!0!yrdoy+Zq72M-=om*}9O zJYy4)OUYUPWbRqn%-X4iYt`lU_Y%uk^8~(#iIMUG_FEsBSTlYEoO-?UQMzpSaU#= z@;Ml!-Jm~);;6Ndj^%C3CE1(7-w^B_3}!eWmq!=^SD}nN;V74hHh~V9`SXW}j1tBR zl^=~C`OJ(ePfrXh#(73sv8N5z_YC7f*AChR3lyjulv~WEKhj_f4GTmV8C%p)zFLEP zW_Bp+(sMbE7pK?Aj*Q2?pIJvmXgslgSsZcM>;hM0KWO6U7I2C%`iawC;;I(vq;cIt9n&7+jo zZ6xB3dRJ#S^8rebkW8L-XOUm6EmI664 zC#?%uZBENODDQPC7TKsf)LR8Dosw8EQd!$Dq!U7L6b3Dz#>Z6=0r15BLIm5syby_l z6%l33T)8{Suw~RFy{iw+n)i8?6I-@>>0sjPD#P@Rq7d~gPH;va znl`s^I$^C5hjxA+d6RVLqoq5?mRnx(k$q(ds~o0^PEc4FL(B6_iR9X~^4avTDc3R` z`E*nE+@gl&1k_rt4PVUDA}Bq->Dv=S{h-JbskQJfA+y1%4WgNd9W#zP5dLuW$qh~C zrZ=^<%bs()d<@nsyUW`FixUnempSs+84Tul%ubdZCh%Ts2YcZg-LJAYK?&#D>ZUy< zn-l2pw75h3fxnN*ozEfcon?g}X`p7sM3JRHa1y(e4zznPQLJg0TzFv>SQiblr z$91(~UvVBlEA34t3rz{wWVYNY+aOO?ZUYpd$el=hsE*Z zo&>~OG7FFApXVCy~*9528>G9liVrvKr6QWbaUHH)^n-#PO6>+~!qaj&XRH zWJ-hX4TXiuKHUpSvii@f=0?GppTVXpBRuhR4>}I&z9u>B4fiNOgcXO)ZIiCm3&`=M z!j`+J5`_udK}(TK0`7syT7%+SOp_T+B8O&8oRGD#_L+OUJQ~7GR|#<)cD_=u~&p2mCkAV5q6A)tTAGX}+p*fiHWD4IBU5Dt?qt*7&av4=1MQ1eLjjAE4 z%1eqhv3CfFqx4NEA*mF41S&Nu^j#5`+SOkTIXcD8tX3$e6%`eIKi1@!gMPVTp(IN6 zPCSw1I;Q!@HOu8}>W9OMjOjivQ%;}DK*sZ|>Q2@3Yc4Giq(yW=6`&r2ik1tbF4f8i z@3$R6^`(ULgtTb3FzyKbfp;*;^i&1O7KGeQ6_K!uE6?%-GTlGbGH!h5YjOeXZHXBWnOZw(ITyAKCIKGmtk%x2;$%{BXfRzVCq`X@j4TDCPPdJ^D z$OkkV zkMPN!iA_%ee)_>#@bLl+TxJ2QS3^(gPk*l$q*;T=?@4HcTM=k#L1G;Xr?dC!--bZ* z%M*BW&kLQ738T)ZRPieD5vcDJRul_sInLi!{`mn6y@rWjqWogTt*D>@D41+WF1a-Nbu8QW1m%0bre;_Kc&lIgh~xG@)<44 z<~J%!4h3Z}4O_gH_pr@T808saJSC|;JrySn4V6DinLlVvyl_xgTFO+6n(}2 z0B@x-1HY@dmq3UjH0wCGDwL8y3F+akuo_eB;@erx7PvdEF~5lFHTRu~rPzm;D%Ea+fV?HO65Opa1u^1Y*}($&dryiBjlmA%Ug zM(&F6kCC&TzpwzG$O$6$S6^=IuXd_d6{UuDcPJk3BXEzcPfa%hpU}Ih`b|KOBegts z)f9IGAi;ja_y_y)^9QKoG}|bX{A5Ax!R5(_#E*E-3vITXlt;@wv>3vZowQD-Dwujr zYUTR!k*~cHl`y~O6cOa*qX~^H(5VAW<$#F6)~T@BOpTlmF9!Qwv4@KX(A&bFE`Rr+ zdO5^M>)Rt`MM>7X#03S~d_|x1>iRpqcIahc_ini?D&8_BZbpZ`)ri>vO;kkb4I6#G zQZVMKR#jG|=EI+l+jN}!!X}0?6uXx=6DiU+ay%_UU~oyXPK#&ysC~~RRrzzkn2Xx; z7mMQ=@apn`Z38;OM|%bN7v-M^t_)Yu$jTYRR*{NzXtQuClPzjDp za+|lGd!zx)^?zO^K5^B*?mtkcW&L&E)BMw)PonsF=-Ju%c>!3zp7dY7U?+joDtY7g zyEVMkXuYe)^W(%N;3KTbesx#{{uqB5_T$Vz;J*INS3mpF0$q<8@BHYG3H<;0m)Ah| z^q<%NzhB^a=?(I5!(}xm>kbi7%#wQuDNp7@L0?)RpjAE;`~6itFMapI;s4e~4$f~Q zbCoPEE=E_Pj&|l(M~hM#8yne;dJ{Fqv$PA%um1YlDhIn=%x2I!_jrEys(?Fmsj_Lp z9Z;xtxc%x7-LyM=`WU%Yf3Tbunrj8Et1OZE)xq<^h1VDEFlnfeyYGh;R;|*zAFpJ& zAQod59jgg&aX%q9t7YoZr`6Z6?`IpO0B2_$uCTVoYE0hy^|_x{oBi>t_Ii2B?N{V( z5wi*nwhm^$#@KKVGFfo;*g(42>Oe*y|LKt)DUYM1`|*DN_H2`4 zg|*JX+9>nrVcU7X;|BybYXYO~VcN!mZmZw~`L6%P+FJm%*)D&eRQU=N+F}I?v=k{` zpt!YApt!pgw*tkT&{Evpp|}&=Ly+PU9D=(9Nznj-a6|ij$L=}*bMDN|3^N%ZZ=QFb zefHh`?QeJA*sbj(H;q}d{%XjZ^Rtf;Xx{$qf#puTtRLsIA|fJhjJj~*m^77qG4Uo@!I#mDNXMi(J)Z}E-PBrBhWCY}QFpki zhDM@P977z;YZ9mreCKwI@ld3c4Pd(WE$<%Z;)`Fm_4Vvb_waVuw6 z*DnA0&k%^c&5oI*cP_hl$@N|4Wc|8ATR8?EMLK9(no*76xN zqVW%JX31tG-9#y7h}HQIx-SZKzkdD7?lhOz%cIj9O=B(5Q_&mK@kyeGt8(_8v&Y|W z^e=f}TRPib=V|;$DXcl620}A8jZ@QZ`lF*?z2(VwFl?3V+;)rsaNCM;r6<=MPKC#>3kbi#U&<6i&Cve34&#ui|$<_U9zt z<_}tHtK%j6hPa-rZ+!Q*6!RO8ckDCIXgCm9CTHgq@4eaa;^D}#1E;^l=cA4uK>m$g z`Dss|k;5vADdX;QVHzTQdt?9-J^bZfsz6%6zt?QJ zROH8V({pF+74@B5T)bDNbCm84e&D?~YU`(oe1G;($7n5HoAB{)mV1(>?|V%^ij{u- zOub)AQnIZ7=SjGB=HtEly;tGfxWP#JwY+6gPf3gOo*SoZ!rauQ^dc)mszGTXoy_of zHpZH>_VkmNm;Aj=R)|qJ3{i*5&ll1vNMp;LSj#gY6)uYSdgqBvxJIeGzff7l5f|f1 zbR+C^THD>|?Mp%jXjmFiH<;qymzeyH$bWn8{^3}Lml$tS_mB_^RIV8E+B6S##>`8^ z%^*}E;t32VcJNReNY>ej)=v)$CzuA;#4T&HlP1Np5;`Zi3PA9UOR+QRs_ZuLr92{B zyO>8(DK5&-NReZ5Z@h7v`_*O5Ez$<+KKuRZzjPw$b`AO%b(gCe_n0dP3m>kX zuq*a>6ox69dVadfB!@eV)%4%r0@8aCtVQSWFayd;_ai8>*@Q$nKOcH0MX#$+wd$)2 z@M>qAG6L}dAfTB)pg_MiHB!D|1BPsO6`U%q98KMMR43ChE0C3)sY`IM$v`gTEMqC~ zVRfNd`XnTMb~D{A`*<3gqx$k=Nie3%T}L# z`uf5{mD+Cq=8@{d=XC})p4o;obS-X5^ z$<`R$qH|UaL+Va+y>$89#W)?Va{|Z&b5~+eqm0(K zsXMnIW?I|(f$B9I^HwT6^VtjzJO_Uc9LFL^sd}o!ALKBK9qHn!QYv9Pp~t5zOd(sa z-+fuCc{JB3R9#x;b^h`MsHW;7qnpWTrDm=K#u{CC{jkxh@it{r?n#r2`Sw}7*7*<7 z@RN0D)#j<}Rso)Xj)ghAUVK7-SQcpYcspNhsB@ESut!gz+Wjzaew}|_B$G0hc zcsE=8pm=erYEgAO1Z+E2mZn{^GMnJ&wZ3Mi@w3z|Lx^JJ-IqPR;Vi(U`APfc1RwNi ziv*@HWtN8-!AK;W+X^z7aU!#=>AsXnKeN{m37-mc;@~beg7$jCRHX(TX^j(V$?9*&RnM6Mg=miPEnT0?@q-84d;|q*_=SSe)P4cCxu! z%5t&;VzDpz^7=k#Vl_I0a|glk03lea57sTP7xXB$8I2+O0UyuX^Dc65J2~1cdZh%n zSLLnO)TRoZL)Mw^Bxx1tHz~B2`l;l5Gp9i-HIWWG7HjOmIC`y`V{Xwe|M~I$4@U5B zPk%^itY6ri276FT-OFOA7lV^J`~qM#DZk7fZ5Tf|F0g2WWla&;2NIkSG;56KBq`Z+ zA6HPM1jN}K1yaDu#THq4sO1?V>dUjEVeV71MKIRhy049kUTImIgOiOsbwn6+Hr@9}X* zg0YI7wrYZtxRr~IXxwlu_Xlbiv`rB8E1_b6x2 z9aggX_Lbkwi;!7N)Cq5u(`f;QE)~TZ1BxVziqGqvT(1o}nLNa%YCmNXF>4iwg)pAX z!CQhO_(~nSGrXi=mHjN2sS9=ECJc5|Iue2uALo|!G2UY$%Lwg zWmocKds+qELr^6{$ej09?lP4h?af8&DoJTE=ls82 zzrCxyoaPr1+|@CM{sPrwwsdimCxs3csBL@8M(6mJ#g-31FSBuu>MxhnvJa4oEF`_u zHe(XG{c-VtlQOMx&xUwb{jvZG(yX{0Zp(#iC&GBOAq!#2{m*;z#9pY2`YVr`{>=iZ z^Roh#?dN{iCnx9nz4A%N6{i%(s@v=|Z>(X@I2*mH^H?>CH`AL%ujXRjY)#N4^Q<2o z&1UeK`0G6IUDT(B!XdLm=~id49Fm6aTP2f{;eJhREuWSv;+Jz) z&m${WFT};J^f*9WDtb;^Xne0D9tJ}YS)N?fxbKdj+@DWN&>HZ!w1Fmy`wYXpY??O! zO)5_Ah~X6r`qOoFS*Ne7C!3)zaT;akj_o>o%=!{FAx#9QJMa7m=F7sgSD#dNTI_V~ z9Uchg1h>^w{+w4zs%kx zjIWV$KA`173UXiMKBwefcx4yLZgCn5G)e{*)6ID+&m}M9QYQVx*Xe88Ep$3ZBn?*EE`_4cO=JhOq7vX$5VuG z@5dAmXbXOo4cUxOGB=XB+&I{Pk&?@9allia%Ev-Uo$D+#JbaQ!_Sp`!i4$!T_Sy4| z!q_S>2j|+<6E7lI+1Y5jm|Szpw%Kh`g1EchLjc3$mWWDC^0fM~oVun#RJpcn=>}ek zW>Z!eojdRx1t^snT%b%z+yCY{IFp#5)=eX1S7oh3tc-}dN86RkDJ(oXJ@>?U&6Dz} zk<45Xv21a_N8-Ys$bev#d>S0#h%PFOBY`$Hkkm49rKz(Im5|I2y>a~*&I@DfN}V@e zfa?y%Hk}Gqjakdg^%2YT(_V96zYJyTvJPi<@2h4a`*i>MNz55m5;MQUer>>=c zau5;%VnMh6NVa>~F(5qB^>md@q6IWNZetHVx9rx$clngma1tz)*OAD%p;P&x%G?}Z z8M%Qs=pX2cU$HFe;IPLyFf10ey*89QN1=>3yyi14dHy?wZB23Yh`RN*ZOK~fp6yy# zCvgsovQeyscdPrr0T7vD`OZXUvqD?;@_c9B6jB$FDCbn1#Gq=GB!rJ3tvg6G>ZeV7 zH^s%q$*9hyYQ_0R{nTy76KU&7I?MII_pEds$S@XewGHN5`~l1^FdzLCIk$iUX{MxJExP@WaUV{nIc!SpMTU)}ii z{?!K3tSMdUsCP>)KpMKW)!0!ffIZ~GhI^pvL^ zgB_j3K=c$cNv(z<`B0TCd4~eo{wYi@dij{)XxWQgHce_>cD*re;EEE+^;oi)i8prE z2*zR*nvl*y<$yMhj+bY4vurnk-uKqe4b)};<-1FJ3@o;#SIqG<;mdy<$8i{2hK^2R zewt%{XnT~1ZhxoIL54K(1h75J3h^kmG!N_BM!QX z#VuC2sRym^W~<}Ft@C8H?%et|aErg^X}R+;IjkoM$BoK6dtuw5NeH?uXD9li#%q}l zM69L6!q|2wZxd0d{2SP!7DX$ejkNXYZQqTg?r6ych;!7f9;|q22A@;`a{vDtA<87N z3qn~BV)UBR>P|e=5|R#UFE!u&860x_p1l-_BV2tqQkf|%7MVD>G@sauL5IGV-?4Rb zyt3Rb4n_|-0ZFsZ{}5;i!c}w@_@KGpe|C98q^{kKPyPEDz+O(c9wPP)qasE73!#DiULk-_N*JTvaQ~VMG$eOCR2rOUD)cKS7ou z`P1eo$5#G>=vZzuNMKBr^bq=21A!xWcdQDLm>z4AdmCpH?uD}05A`V$_SFQM=nAxZ ze3L0-u6CpJ=gTa)<)6L3i+9eJH!}j0X zCM!LvS3x@j_M7T_-rn~OQsafEM8YyOvYtvFV0xnoOEblKHBv=NO{F#fub}oA9Oovy z>!J}atylF*CKG#y1uak#z`lQMKaH5}7E@V!K4vR-kDe`{ACQpQTz^Npcu)BGO`qFwWITi`P&M9aRAp zt7axt8tluHPdud-QDiCGUUErK^0E!QRB{ooK_^QO8&S!)mLnVDpyU3`BWb4Ggq_`s zLie*|f2=Y!-3i~F;to-LiwwGL`wtab=o!Vb&>HQr{ZDz~VaeP3+n59yh7CE@h{xHK z_wVn(=(=|bwaZi!YSp)bsew}stF%f0CJi8CWA%8OV|YjbIlhzfe7L(?Cy8YA=8}42 zu{ZX^tCO4(+4r2d>XpWlvyXpS!nbxPZZQnE!uCqFUY2sYb*reEov4{TsMkZcy|H+- z7LFvaN+S$I+4kot6ZhNdl1L;3HYo_M0^Bx&83#B3@5%7%+Co8mKXk6zMXH2ntg{f8 zAJca~H*8;@JYHoRF$#?O)Oj^16VvU@8MQ5d2xLVj6?wG}C`Pc+x;K!FFih)Q!}MtdSQb(>I2Vp_EiBWu zp2XSU;)A*d&MlLmWRJ}RMvwy$@-^I?BEp;=^IcEzjfe!4rW{G?27lxywHvkP&l~r} zS(~LJk75s=8d0f(4Ed(^tnw%w^E3J##s}(|e;m8JR0SPAT@AwJPEoVwpcABZyZ(W) zPPdJk&flbN5}es&8|EatBqP8KfEB7lR!aou(4 zt1?Ytzy1#w$GPg9kh&DK+h9J*$O@|hO_^`Sq#Yk^X3&4PR~NLi)n#@?CuD)EUaFPO zPN3ExK3LdwWkOYry0Lw2b|xZR8sjYc<)L;g3)lyd!NI5)}=-8AdW5B0p>1v`a#-D z_{t&9oLxawbpB#xf-N`<{c(t6;kzn(OMRiYEE(+=2N|VU4L@k^y&114ur5*=kT3HI z=2IvOhn4CU0akM8m4$@CSA`_aMBZUG6S>+OJv8*?2lGX4y;OsGt|ArJp7|sJmOB*^ zS}=BDeXqLOZ~p#`oMsz~=-@>A9O>b>yXfS8v=_vVP7uq*d>l-6H$Y-{uvBvoA$LX6 zZPiTo8#1Kx+1pGeDyo4wR9fWtIaEQwso3pc-G;Z)#ZHqWaI>C#C6|-3>$(N9gD;^u zi6$H;CMpm8xbPy^viScf(sifat_IX7+o>;5&RXYit_Sh(TCKQrL* zeA+Rke6}9HmZ0fVqQ!!HjwYd5^q}$2Z}ObnYWvo-6c=#$`54p_z-W{2K-fBC@{DZE zF3|0za{hv-={~eN!(%iFXT$-{F#+@({3IZ}-fHdKJUgM%vTB7NC5JwY^8=)IP1|$L zUmBXdMaRm$%L^4+fafdKY)MJIuiXyc;0x{1D(AvCH^%+Kl6es-9BJLw+-9S_gchMe z^T;YUua9_RS!yQub5!F3Y+j(CH<~HEkqZtHZ??gDF?8~r#ps@Kjp2*wKc9^Wu?!)Q z@)3#d331#Y;dvMDlq9DSi1Dky3k2NkKSyVO%gMBG#jpIu1rS6Sn_PL@_NNod4W(xs zuDoB8+eem|xfJd?W&RaZa{yXY1Vzbuh?X-)xXYBFplYpa`F$B(cLPBG^+?`Bc#-zP%nuK_hE9*0+yGf0m=J1SF_0uHCBqxn}?4wB5!Js7X z^Fe)be$_a5Lt3tz&WGrrGhJZlnP!b`i&RrLxS&CzBrWXS6FTqTDet$mYn>n2Q<*E4 zepEzpl=U||S7QN!MG3?H)QU8t} zo=kMzB{)$!jYo=Dz)Jhv6<2nrW>>F1&QSzh4FXS}Pw=~h| zLQ407-2A%$RiY!b;vQgta!hTVVuT!x>MM{=`sb^wE7qAu6fYx+%cWxJbF;i#4rO`m z_Zc$3OUqe8(#HxXNk+Z)N!Ctxb#po&?>VZHgO8?iopgFq$Fqnj$6Q{#JXx59Z4(_z-Xz{{po^OgQrpSHwKEN8wyOIR+AmrjOd+SHA}!#BN8uwdXE#FCLg)uw zOs|r-?kc|IX9cG(^LEzx05HIwWug6vKkW3FX)jPN$t!P0=sHP!3MneeKdH9P@WOKD zNYbm8o~jBTE60b(-F@_r37yZtWYyxlE|(!SKQr2$b6l~p-sNn|I>BO(p_W3cStr$q zVUIVx`9Y*6$4A%3P{@f#Ca%}`E&_ABQZ2CTS%vx(7@23o43BwN=1P9y)qKAim~E+Q zwH3_otuja~QLLX!AiCKyLCCk|zDG79Gg0KXwIPX&CiWPemv9eV@S>5yoYhUc+1Uo%#n6a4^N#8i0&{*jwZzqn z%4^k&lUm_7%Z-N_}2I80TZST|+BX3vsye~4I&36JILrn!-S#QFNdnQi=GwnXXN0#24?nZc|ijKb^^m26|=a zbo9-KGBW-#wY#ko^+gk>=V1~(yYZ>U(PVDoO$^rldr@dQj&cKA$gNj@G}jc|a>f5& zL$8wlur`&8c?#R1jFF0UW@wf2r=$2?=uJjCT{xhhrqg_O3SzaD2s}ZcT;qydO7Dk} zWPcfy?u(n5&yI(sy#QKlz?^2P`9*5dH46OXbFN?r`U=V;CtLmsAbFE}Kc4~dDVSko^ZRqQmbS z-P3X_AbSPlz)4#JeVBPd_wg}joJzd{JtsMjjF&Xia5WSY9bUc=BcnfVX@O0amG#}t z;hS2{TKiv_0-OND3dVIB#)y7t5<=4GQ)E3~O0>SEt;}g%-9eX8*ZY#mZake__c+Fa z!}T=IpJSZC0@uh>*FB`cHyd+3Ws`n2rH~Z8@yo0IHL}3P?^9)sQb6lK2z*O(CCn>> z5US783sN-#Zs)jx;>}SnIh}0u+BLmgTmsXZ9g8Nzc5*~41ShMc;VxFi5PsB;-^#FL zg61pK^VogWo{pc-4Q6-PHC-1<(yXOluT>(;9w>(N@P*@_=OzZtG-P`rz_j>*1z|gJ(G@Rtj-%%$ zUtTcsD%%KiK-L8y27(UK{53_ox)ViHDie_#?$&N|4SSw^YE}M=1@Se-1v-APMi?rh z8dg0LOK-qOIw_%Q>-x?`e^GqO(K45I&||ABpDtBfmp08>4)wWO$h$m*R0UXa7-z-k zIPEg?*ny?WW0uFMa7w@KbSGvdOXC@NQ!n=T2KTTV2&QM-uS-j|}i(Xp)n<2|l}VW{@PjVn1yIWW|_xYBZTr z{|S>P-?%rLckZiK3|#;;Jkt7~NjZNb2M~|%@}A`-vSL|+`M;nkJc3?m5T70W(|58r z3P+QC05-<*0(l&b)F4~ATHQ+H-fJE1+S4vaR&?Z9x8gRIb)IdCibDJ2%|X+k(Gvb8 zuC7!z0IrnzmI68Po;2b?hI0(Per6TP34(r=jl#jc?OJAx zF`W(2l~W}Pkvv-MIFXG~d(Ym(hv7BhXnNt(A>Y$aR5X1Zc^CA(>_DpOZCnb_m# z(Q17vyJuusLt*JH@W@DDgnw|#H#ymU-Ii-C!Xxx|951uog_q(cG1rx7UbUA^CNpof z$fmuzItYe4awZ@$3{KyZ8O@muwAEM*lvQ2NOJAPW4Nk;eB$j8Vf3p(U(9ob%F6?)$ z5)_)bplu!Ml{+V$M6si{8sifIb@oRwWcJ z2u2i2pNrVvQ&EPu)fLKB#>IK6mQLw5HdaUEVBAB1q^)Zqlb5;_=jZ2)r^7_0v)=DV z%BUEozGoH@$(eAQQ8|f=5k5_Hwb4(w9YPp4^q!&5m4J}2l&UkhC-<9Cm#Ru<@Q+sv z49lO|q5$S?jkK`2qJsaBU5>V;z2H;!>?@k}QBXZiSksqPuPx5m+o`2z@eMfVY*2=S zQGr-Uy)1D-pxU}}Tcbfw90T!E{^*`Zk?1n>OnGoatf zmlQF7=F9FJ1{YB7)Xe_mtV^xh9^c*s!jE_6@zLUZeK3)-Vw$3g%1ZmCxMGx9ZdND3 z)}i9Zj|ORB0v-lXZwIv~vpWP&U2TA73CzR6?z-dqPb3dj)AR&Yy_aRKNS8-~^i5%i zAAR>}eSVLo<$f6kAqxTe z)*R*J9u2>Pc-sSmy{>c0tR7`CHVT&D#Zy9R#z>6C!?8%kwD6{?r&6{vx@U{r*Zmv! z`la8v!ZhYpPIb(Zduoz74JwJ?(y!Qml#WYVGZuPws<|)2&85^W?AGbZN1WvM_@Bp}SMiN^qPa zbft~-wNoKF_nrRvTq1?5x!8t;@Yd*z=|R7vX6w5>{?E(m2O~(t_Im}AxWlNtp$j^P zBrmBV$6i-*Ay=Isqo3&=m`*%UpJr{$(_MAXc70m=jMH?c%+XxWoc5Y=WP@Zf*uHoY z;-QnfDVRmPnR*HNUT@nugGJw{OIAmVJKlYhP-f6-3TL>uC^SujVJ$Xm(hW2ib)`<{ z$S!lLa8JuCm8dbFDXRh-m2#hSU3vL>6syN|CZG4q4PHAJ!jAVdi-e*X>AcdU^ES5< z5sKTBc$RbAV2iOy@bSA%FZWddel?fSs>DY8v!UcyC6Pivi_<Tmg(XSO z5BD(nPUIWp(tXfE%WwnZWy*FZxWno4?0`BUd**l}jv=<{d3e_`Cz`k#@H<)Ze}}ml z`p~1SM^O{I`_|Z;N5J{uz?jPr{XF&rBDC)pp;8aJSa4Ju(@XpgM#BKXQ%RybH6NGn ziy8mKKY3F}GAs^i65k4`%d=3s#N6mS(#!yO4HAZeDE$6Z_2;$;)r2*u~Vajh6O=#c-aI6`Ez#GBD|@!bc=zQRg3Q znR#+%ZFWlT*?Q#wlIKb&CcJXb9%_|Se@Nqt1HZ=D*VYwupBlEM6wH+D-(jrw=ya%C z{|O=A<#&N6^!(PcYaxKV5g^XkaJa3xOKe1N zTyb{oRfhVJ+%}wh(7Mrc{A9g%=44zMrhM&|cF35`XyY!MAvB|aiXPQI5$2^-g>kE` z);=7?FSVkFjm|Wp+Vm_1U1B`Fo&db}fnD6Xh4TM7cc=C{SO;;nd#HD; zcy2n{5nX+%^`Xgg$9W68&V@P3GnZEZSjA(yzGY>vDDM?@9A&^Nx+%xPob(k`4)_{v zw(?0wmgh)bdKS%>A{G{kCDLuOEirY9rY~?o$c6c$jh78|EW=O0;qJxBwv}_LO$fEL zgp3JT?W&X4`45A$Ea<)!aEZ5U0zY8;pv{9|`Cy8Mli%WJ${kf z>qG(Gf&WZG0)IC}oZ1H8t65BIMKizCb^J_9?Y&Y8GZ)beaBn(O`DfWO+#b<*)0gge zrebmzg5IlEc}8gx1FURl-wloMKl;=tJ8eDJ5YOV(Th%m(9?O$N)PZ8JIIq4=?SmT$ z)pd{Sb|qd4V7@QI#=;ssSnak(j~hiZxo^K*4v5FVdS%Ln(ZGsEBP4}Bl3xpjLbEyn z7u)EeQ-rS0AwnK&L}6G@bJ3NRW4UEduU?n8ELb(at-@66oigzl3L2Y)Qd%na+<~cf z3ojz}?=}eL4gD2`6F=z2`*gd9?gm(}Iv%bgmfQCXm+owgm;!cq9U~JZ9N~ib1i<#9 zQ51z2&!M|6Ov=dNyifmyAf?&|7TXDjkB#?_J!OkmmFAZ8^+j8f^KMNjGv*r)M`W|R zm93nGx#vUnE{rAm#7eOW_ppVxLBr9NP&5JPLpwmGcLdt8_d9L-H$MHp8fWlymAcNt zh3A(S!n(UxHZd_r`Z!Qf#c+Z^6L=={OtpBbWF*-*0dU-1z^GdA!Q&y)uBLWxIx~%* z%km($d!og0<+Y1X8S-Pw#>Og>|0R#9C&TgB8X-N>C~UGMFrh-02rmx(EvT2Rb*JMV|W7#I8;IKI5$%sx&+eQ>wP!XWTI_(4jDt zCO1cw@?WY5Qn>a)GSgzY*D_^OP64x$xy~8E{n{R4ax>Lqd^Tgo&&trjQtivN>HiOz z3pD>pU1PFOMPrhIa?Duv-JT2GXM5D`6hU7+jam5m?O8bP((&b=D9#6eGzhi%F^I7B z9s8Nj`rYBr4BgBLcYn#s=Q=&&mQR(Uj*qgU@z2|udaHdQ|Ao?xj@lN4UTOX%B#2G1 zk81^@NmlMxu?4kcw|Jb~sS7#}AAeKT(8`4tSTkjR5e9B-FP=vHJKwR_F}GR)SU48C zm^VxKNr5AB8>9Kw-^x2)a#wA-u(kDGp?lH)rz($oG#)p3I*8%tc3u)JDKLN3O$Eph zG6jvo{o*^+|6!6_-dcH6{6S24vjX+LFB0eyd)#P0^de-w#-JDRwo!xYH|qENn%AKA z$#b*>uzs^0Dr2su3r06tp>CgS?Cilegoc0rj0U{xNk2A*1QFY+Kf0JN{8a>EN4T8e`iQZlpn2)D?uD2Cvx*$UM^`cgGl){p3b266K$4TG zCX4(cfM~S7efimLX3>ydnzrrn-&MG0?^hwmY39UF*pdo7VSYV6+W!AqAsD|Z|FUf3 zz1%M1z1+|*na1=30hn7ZXn+t6Px{; z2e=0r24-IuCKE@}(p~iVW_gn9?`PJ?6M5Dq#`fF0Z>0#v{(L(a$L+ZtpOI-kC*QBq zkDgZ^;?kthRGXbO@BahZy?IvXJOgbTbmP9^t60S6E3HH!ze+N3m}Vd3I2@vHPs#o{*$lhr>USK=-~bEG!xp zp5UNSt)Vn$CA1o>)Q58m5YG_H^DBpTpo_RhVJJo>tGHeJ_=9_~E<)W3xt%?=e z?6Hw>hmP@WMC-9LZhI-)aIjYXf;aw|%80f%`+JK7*uSw4em0L47k0EP-rrObfm=-> z%b1_kx*RLBf7eT)t>3yr9~2v{Ch5yYqr!t?l(kmGl=7;$2c)_nzr} z%dvcjNawd*AK`_8a@>#sYsju)PbzsNzi?GZ+wMwFY6i6PqqCjy5UaNHi3=OFvY4%j zhkeuRw3Ui&xYe0h;uLMM3H(#DzN)RG$1>|S>=tL+wH64-*=6}0J1Z6UQ@cH_09fq7 zD;(pzd3^6xjLV_#jG8-Mn(B$PZgNr}(~nj>4GOv*8J?IIB9~6I7Z-riFIZI1t8d+h zFx`DA{CQgP<`eJV6KFE|ioAC}aD8Xm_Rjy21t`d<@TJ;Dp#ZxXqK8y{VTEoq#eV>LtKo>F>FEGV_`rFRF3zuwU^hXa=orIyleh1X_}=cPx*61` zx;c>Di>HDiU-nqSchST-`VU%naM~Q-T)@7Ozh;O~PBjcvlkl9Zw+Dj}yJjfyqL(1N zZRVuA8re(=-=|)TBQcRYHxeGX(YKM!EAoh|JMW1IzTi!p$3keasP!B%ivOt19#*G2 zENXx9e6dG`nz1z8;v^`)2k%komq*3e8&?$ldpDPO|Gv$D?#1JK#Y}+5(zH>Z(Yldi zu0z9uPm+J=3R@;qBwj>T+!l1^fuwMjJ-Z{m?iV-pD*ft>Lhp0^y%(!O*<5rkQp1Rm zS@9@ZhgtNdv72G84WV`N^)Ib+W=qt4mUNWD>+!t>gToB(+sy$JuEK-_3W?P=@lUb-C}awf~JK=Eom3zKem~4fK5-W3PS~L2#1(p8!+W)Odl){mI|l#KBCSx zWiuDd%cl;<$&NrD+V+~Ma3XS1#7eViX&7**(9A!i#~JTUN;?C#2r{MfKn z`l4pYm2N&zDWjeI zHuKo3cE~nKBKc%DCd%{rE@Pq>Z8EQKlAS18xd|kh63~X|Qcs>BI}2@+**{U=He*lx zrbd@_vDSee{e`xJM8X91%9EecYCY$(x(9ND25R+xjp9}`zA?%Y&mWTncN0AM;)_H3 z-Hb0(6Z6q~`SlU4@9M=W5lQz=L`V#X=J&<_$a^34s^yeYes+g^j$`ck_W|U?s*o2B z&Tses_4)F5ThKu)Mfpv$GC*Ww*XQ!a4*Y>OKZ8~@?+=5G;NerZvJWw;_43JMJL6Z9eAl~-$}@e?sJOp>pUO2fgQ`9+M@jXTx(?~w{%h`^uWihZAI z>%;VdU%j5z#9qcBI%@)g-vxcdWNe2Di;x)q5qo1qd(591KM#J!2*9Jx!pJ(iMaFpL zYmCd3kfTi9-}sG#yi2_|sq#`xk+Gl3l0m)z7_f<<9S{BkKct(B^3$DCkL8{3&xXG6 z&5iO_%48}fJYX-1(ScaOceum{a})qCexeRGb`b7*hz}26^;9mNwg1au`0MG0wlH_& z=4&3aW-Q>ju$Twye19GrA0HI{h^XVRiOUdnFZ=Z}LfnW#KA@l$q!cdSof_KIQtJPB z{@T2HDo2G~7?MXQAqwr_diJQvz z{l@Hi!@J9O{bHiFuB>uNi(Arty?lW`BpXaYENX2F8G3E?lJHdk;8XXPwSAuDz5`e9 z%Z9D=&p#0pU{H9|zBh?qN?H%^^8L%Bnt<0?+2jhRE6C0Ljx`98!Fm^IDxZ_!0{D&W zR25%{*-HAsbytM+)W@mEE=yox;ox@%3nQmXRcsx0M}Po>nGF{^ZzUfAKJqg-IggW; zPz&m(rK8&7AP66>$9@+9w)!=f~(`JTWH1UbljhWnWBT_8;~KBWAzM3V>n z1{k%@Pd}r~@$p_`_>fIBSw^|c6L^AL3B6OU@NxidWH#3b)B0QAQN#isJN*Ssr`RR4 zXMz+xXLvSVXN)SZFg{9X!N)$&I@ivWxzUk5+_lL}u&e$0f$b+q z=VRE$*g&>#CGnA|cYqLadYGIZYlzahFhLm#+uvC`)RuT+$DOA;nD`(`TSLThx2$%>?qa^tQB2)(+yn~-R-Z6=KvPTKk2~00 zhR7M9ooa6<5 zo>uU8^#md2KAML9g|5YLp?jNQ0;F!|+{?X~=nj#B7t2}P!OM3sa)|&#&Dds?v)B!~ z$fYx|e3!h(i9Y@Qf)F-$>g#6+fbtZ~rA7MmMv}7OPc1eI`rnA@;9YTuu=o74%a_S+#|7Ho+OsHlmd`@fARbGbB22;?SOSi6beG50 zk8cwz+Z%PSbiN|9Cn=*C#yy}1eO_QDezDWtpfNst7+*TGP=N(T#ed-d^4;N;e9%Mc z&R9lSOLBDG^q8eyvBrv9=MLltR51FZ{I(y51chIbY>MI@lrUE65&?CIbVh36NFF|B zMw#P479%KIwDA&#@(#LX;8P!wsROZs8aGZ91oG}aIhB{wPqg1~dVbx)Co6cJpD)Tu zI+l59lJJGkqdpBaLTl9I!8bkuow##16X(e{zVb(~E8}V5>Tq>&ICoo_*JE4~gxhad z;a{U1^mFGht(^%fy4*`4e0FO{ z`73R`<;7|fW*w)4`b%i{!RN_m1G26JAwrn?O{Y~+?OKPN0hCTe)xKk8GzZEKMwQ=Hg)<+#X3 z36W0>JK>ecN-*N!iuIp$D$RXRtPj8fhq>QXcNCnPNJyEb*%cUK?wt0~+w%J6LTpIx zedWy7nBj>PPH9K=gqVnGToOZSkLVM0qVh_+4iu3|*y(4TQrGUsbKLR~M{Zs>5GZB2 zT%Z}i>!;23aqYEh5zPeZ;&%F?ASqsI+_p#L{Rdmne6rdSy#RE>=P5`iTpdKro6Odv z_iJC^x}Y!_+PUH?!H~Dw4fj*bnD1v3n{fq`um=*s4A;b+G|1TcUnl{y!3fjuoKN3# zIB@+6B&rkvl$D2wqYo8zJKt=qXR}%yNEVMddxdbzxKe5Mne+ZxP5O0 ze3rTO!sn_`AtvDtua&w#eW}+oI@sHGBB8Jm4lk zrGAOA*$&TX$zS?*aqvoK^*!osX_+{G<1>JOz1|s~X$cQz-AQ30am!zCC z*}QSxTb*?#>HgGKr>R-DJ1QlL1)>p4AL`GqN}-QK-*UXY1i`~BJp^||pUO^pQG9fc zGX8&s9%v_W+1QqWUZCEft^@Zu%Mh-|x_miw_3@^C`}#tJpogU*-;Ov=KSaXYTPPg7 zEBmRIJ9E-!^r8jL&8x5QK;5a|C_Qz(oJX?dJj9qDrscd>VC&~ z>76xH-UnkAcQBr22KElh={^fRd4$O|-@VdCPhGNuL(R>swYE4{H)E<~DXis%tA{LP zO_+F|XD)990Ne`#?o>jJjkxNmEl-RR1pHvL5uMti;O+$OP4NRMt$V7%f42@bg6E?$W%9&zo-W!laGQ1NBOC1t1U_2`>L z`DKaKxs(yacG=nPrUct73Lm2fU7HypQ+4i6@NUX5%$94){aM6^B>}Dfhpo4cit=5% z$3bLJDM1A3M(OS@NlEFh0qO4UP9>#5KtN(7q`Om^0fvx{p*wyLp7S~HdB4B+AJ&4! zVtC@d?tSfR?|oag_QdqI#I}bxIp|<2qViX*rmfUB?XlhpoiY3j2t2-E?j5^OY{xvY z6(1$jf7T0ET>GG>kX3Av6E;ehtu`0S@u<@m-$xf@*alUSltr5eH3{#P42Tq#)PZhaCBX8(f)v5{&P z#7E&O>sBxyES;Ky)_A#*#e>Wl{c*lJZ)?q7Z{%M(FZ$Lmi}fGdvAP{Nex$u8HE3=w z-!jv^n0d0m->NXPFDECb47oL^_uMl^^Vw6@okF#+w(k1I2t`DAE{G8WgwY%8^%9h4m%o#X>BIgNw^(*Ol0#)=pg2gpwfBwx0NA*}_^P zzcc3d;xG4&3&)S@>c&&wg)7Zhka+mc?A(oxq}+@ByxRm2AC?A4-tao3`fBNh>}Nf= zeOZQFnZ0rDsH)`VGG6N$mL~Lka$RwhpD=;1^Fp}S z?zO^aTm66#gS+4X+vbFyR?H)wCiHX|HHzy$m|4EbVKDibv$hCuv?*z8gLr0^i}IY& zcxjqF{K>K5$Tb$Eei8!Ab>&s%KqY+oGDZsxAPv}@9pXgT38IN=IQSZI;jMClQHalc zIk?j2VrWcU4X6VGGlySBTx3tbmTUpDO62VaeIoQb9Rfe2@nT`e4b&5+_&lTBn?RmH#0b<`}MWg;r%rYRY6wZbK#~?)Om&;Rr7^VMf!Am!wXv; z6-aynQQVrX$CC2hBOxzn^43asb%yEQF*2T1AvnD9ZL%X{@^#~$d>x#q;Dzkx%R!*U zg$y)6q5N=9e3*^HYPgZf;eu7%@}z<*Ld@lL&rk!0?hJD4FHlwTfB(;s#%4D*bA;}6y2B^iwq#uWSr zd83=5-`%(Nmh7SiopC#SXYlTUOPzZhv7C0u;|9bQG zoG)?QWBIDy?wGy4+D>+G(@s15fzX@ZS~bO}+Hyx?ZS{y}{m5EA+YRsfr>>WPMLJv~ zfV9#xR#KgBy6^q@Es^Onkz^Ga%W)#paFCy0T(lo5@wc-T@aZ+7r=vy0xi9WW%1cVw zx7)-l&kCKBme7ETOqKk|?wGb?Q@2~`hmlJ}c;utW0&yXPtY>*T%2!=P(S)CIF3+o# z2adMUQw&#L8yF32@84p^zY#q|VZh5Ol3pPbM^Gm;MfjtWEo#LG(z*v752Lxr_?WR+ z{V=p3Mmc35APwJSZF2IIg={wq1O0E>E8rue+c5<1I*4@-m&uUQ(w~Fy5zdPejvm>e z^i$mx>tI7GUF6jg7)gwRKt2S8aser?Z*L{?Y!9G57=1fDh!j73991N%{^?T;f3P>F z*z#EdRNJCoG!qLKeT*K7?f;itl;Uqp@OfeFb{9=hhM@g}mW(p(WbkVyT!Yng1fwrI zn;oCy561yU!bK{+{5#r5i^sq_pJcLWV$Sf|z3@ruVCA z0!7|8_!xBee1NYjMkK z=q_HDR zv3{r1{scv%kQiE0u44QjK-*7nI*p5|K~>awsgpWYj1)1X>XE94<~Mh@pR{C_&@@Q+ zX^|P*)cVE{%(%5)8f%iX7C9{8@-okuvRJf7F7LF#rkNAr#A=G&iW3Y09w!cX2)sGf{3yjyhQ9+_Pvt~hT-3L-FHPCpY~`P?#LZ%0VT1#dt% z*EsF{DO6`%S&cLL!w-9xuO&*0n7>nx|8@R!c@MSJhYm*C8y364W_R6RuVEKLukp$6 z%q(vXw?j)=-J{Ii$;nUZV*CKXx7qv z<5oL@^-{GQ>GkEjUkIP^V8|SZEu7vEp$TvB>XO(Y8H#@u%rz@{UHE47{)*$XKKr5c z_wLBb)IUhcs3J+@JW1`CX#?MbWlK*uU*_X3QLCIRz3rT;_H#p6${7Bx{!>tB}Z|){%oJ)9NrLpWC+YAcVsU@9WH!v+3RgiE!hS zMaUDF#*ZH5Iltci=Mfg!uDn0wU;)3rWGqV%CzHh8rfav<;`Z3?xjE4&}=2drvY1P`a6&PMHhG5DcEb8drSAtf!u z;NmWVMlY@o&FMRIwPS>Ge0T{YWo8h|z9781OCaUX-=M5=Mp;{E5J)&NPeDsgT4#FE z6Zzes67|LRbh>3(K`e7B>JHn{?qXNLs)}5kso{${@}=Z(Dldw}CX_b_ZOLIqpExfa zV7O1cOWskjokzs~a)@sa11h01{gnCZfOZm{k4enf7ehxFRBW(Z(ieN3I z{=%LkId2GtymLT2YbnxCWxhu9nGCNPySedXr^+2B>ui$|cUv2jQ2(G&rt&03&XLom z6PFs#BSPoMW1C~h%~@1m1)YogBg(t9KV8Y8nOmt}gBtEgjeloxS|lyJrbXAOQme|> zn3m+3JEGsfY+tBnx`3>$SfXE*#c6(xe1Z_0D9G%tM;hD50XveoL@V zLJKfr)>l(+(eA5v85IlM1knsGPNd*YgVP6={})+yZ($lY8KMlfb88Ml1@_x?zuP+| zB1U*cj=lpz?bF#EzwR(Ezjkdm>_p`_ZMPgp&X{7Sw|U~OY`&$bL8IqzQ88WYg#!>r z9y+LS)5v69LvznQC->9yrKLua$VNo;%6z$N5$BRC5X2I*ZDl_6S0k<=JAtxYpL{66 zWKWGKA^gGZAp-dZx*A-o7e5Jp_hLb=GG`=YVS#8kOm*R`SPDCFahJ8in*^6@Hr^Oz zM-Lql1%GEjfvT4}$N52b=m$fOz87{P@S8|4Q&n$0Y$=?1>#I~O5B zn7v;9u0Lvgtz5Ap-29^>0q{oOB|qevkvkK5n$-kB)uQGNp?yz>?tP~^fO&Kl%s6D2 zqIZC^<8cC4;gXZm`l<*R5MX6&8-|w7$}laMV^|(#32VyPgn0}qa5-bKBXffF1H5uX4B7k^5|ZdAgroZ zw157(c{mn|dQ{zr6zanFymQ}=Y&d+-d+m4p4xM=Bj32+1U$k3N>Bd z1JlR-8Q!xY-LXchv6oZZZZ=>kOdVP}(EdA${m)SC-*feZK9cgp4z{{R>HU2zi_N8| zM06Cq5LYhic3d5eQ-v2}#Na_ucmW6pt__@;@p7l?S1vYhzaFN3xfMJh%Bv}$Tf9Z; zs4d0b=GJzyfG8r13qiWOO+nH4z6xe^w>;-w)Qk>Y^IY3fr;ZK8%brB_c-Q%j=IrM) zyy=h3qBfpFpm~HG^ke8*XR=S!k&eHkj6=lYSf_euVyHMhX}w%k6)n185)_%pbSusK z={bkBFvs#r&yVZ63*l%*#DwDlj$M&{5R_ImT2LR)Tf!jbLb7xFU1kR+s)&ky`UKgwZQ!{5L7$>7Er!p ztu2afr zQ@g%hhXBSf$lz(KL8m9c9;4)aJym0{obbUQS7&tFy;hIT-?FT9F37cCFMe4wv?SxL zkrC9-$kx_?D)=r%ZDs9j#!!DlUVeA%ep$r7`Z;s?FXTZ!U;nyl3=E8VLg5ZGt4RBP zR^}D$;r1BIp*bFcSJoHHNm-pr2KVon=H~D#h)?`@+MT$~ko0vf-fa{K1~WUx*)T<{ zmSu!GO*6G?Nj3XdMRdD+F7n`*w}#DS@~w>iE_Il@S7pf`MemC%?ZAW{bTHPK8~L`D z+Dk0PUG_}9Mz-N2?^cV(*U4(*Kj%MOOfb*Mf150Z(xLN@7C~^&a z#-6@9zb>hw0>iTm?lri^V$5FlQYSSrW=ud2W@oU0P){n+=r|q5b8-w8r9%PIQ%^8S zFq@_lD>-4Qf6gHDl_yb+S_rj>uO_Ap4&Up|!i5nPn>q2KHYI;hX| z+UsQ0i(kw|#&HXWDehc!X1R0RC!Z(^%rl*h`B+t1UaYx)`;NnT&cq{hgV>a5(uIJ8 zV7fdM+q+gMh+0+DdA0SlZSm(**vypi_QuJ$7v#E@wy*d{59b^{0R($~WzROw`0U#z ztK}SfxFR3P!go~8U0g{X4 zZI&$hh$-UOdoasWzA8;MP2+0}amY`vcYjM|DFj9J`#bC=Il8OC72a6Q!bLO6|7)P% zIzH#~1wRI-*2{i!SMXjoBM~Z(y=GMyf1ePe)^RpYXNCL%9uB6MWd=R7wnPnTs>N&w*Dt^x<7L-Slm=PTQ$~W|pE03nJ1A-yXUlXfx3r_Curq5|lCB z)T{M-oL;q=M$+F_s&zf_b2Gccc3a9AJWA5tb1Sz~dO~bLcndyzX37fIPh2|2_;Kcb zbc&UFQ5SN#F|rhfn_SYHGIP<6v=3g6qos_m+||?N*pjjCvq5pwBdU($L&Sq!vD`bz zro>A*$IzvGR{c2kT{o=cJ&dvqM&|E{8+ak3Qi+6;TbnyIsE!q3I!(LS65ELYy8+f0 zMJkZ#l~D3Vi$)XFeu|vBecSxYIuSEL+dW-6Nk-VvWIy$N&k28oNJ+UU<2+e;%nr>t zM?oQ7F|SgXx*bX(E{di9&K|SQ0jL&OOEOQVl3rWK=47@Pe&3ytqvReZh!w%Xq z@|inSqjqjVLqkK8w~tiqb1>9E@X(%QVh`#mpDjdR)}8627eZvAW98qDw%=o8JJ_-x zrv*`y@8go>`bSmtS6~E%SsSvOMoreL8;AgMsGt39nM-jG5Y{_=#|%y{>19l__uTZkI1c64U%yxHV9U?al`NX3Jc%M10!ct!4SsW z6l{}ydSGRsa(wi{LbJZ%;fRj~;Yqx$Lvx%L9Qm+vV1o>0Hj#8fFRdX>n0xSn@5 ztE?529vO4FU4FxI-y2YOox3psRc<^q;URQ(J#47U+lHPfpLsLU83++`(nqQlb`maYJG}jF za1b!C8D{uUXVAW`4xIM)WYWi*?R(asmoM6dY8BOYz>yAmw%xN*~D`BFK?@ewjl>4*BYy1eov zEem3e8G!c zVGBmsd>z*@`@nNlSCVbGT4ICr!eQovP!b+g(M)%TKJCy^`8kkWp&g}@T;kV_g|e*7tM)U^9}|za?q~P z@GpGBxY7p44sQ~tccVMJz6B8;z~G(t=!*%iyYEePy$N(tZN)onH`@*19IN+vyvaiyW zeTK>gH;6r@faI6Wu-98~Z8_I{9BhGM}{ z24H004H``D1gZW=@GyDmbo^2QC1=_i#SV~xI#7Li7rM>M)V+F?4k!VC%j*sYNQY}O zP#Q@-ZO{IL0ZrnGJ4o9hUdh&hAAh^H@F4m+jgIA6^LNa%&Cg+BmliG+A;e zmdlQD?Yv`NVx$JBUO}HiiT1J7enX$?*rABkUk#dYnGh_yDmd@fOIJpu15S2Tl{kOleP1F8y53jgV{cqx zGC(c#Az5t#MpyJJvx(usS-q6G=9oO(49C2bl<#ijmR-*zbfMTB_m=|c7|vnMz|@ZJ ziQZ7@6iB-j$-Zk{`k<2J1EE}Qed)4p-AmcHgzz|3VPAngExna_2-9tAf>?);>I-#w z3^ss2Pu&@&IB|YczGrq7<&7b|mC1^=O;1%ee*k{_7ZX*3Q+#qnr(FT{FGgSHf64Uz z3V|`X8q=;Zj7t_{@)2VB$jI@F-$`_S7vssKMcB#VdE%nSE$Tp>Q|rk2wbVS39{4F*I(bFhkPjN*ZX z13<3HsKL~K^R#V-kg}*4q4b3u2dPE_tv@KD%UN15?o-64R0&fa1A`rJ;#Q9)G71W| zsr4}of$5c!fP7w{Al*mu?OgLEA%bEL6LR*a@wg4GH=|Ie`w`nxQ}^)q=6 zOL9t~O@XzYqfeHDPr{NaTX&31b)ET$3~rHK_J!WxU6w|gl0=F3=CGn zQ-q{jZJuE7ArKj?w8=4(9qb@mOwcObQE@K}GPSoP4#qoNz5aeCr)PiXiF*!jLE2{) zz~q`?F3$ACv%jy9-v6dHy%issqI5USjxr-?;q_{MN$AM1wwXEadU0L4#fc^{5#gPV zvhbQI&o%RVD0wC)NhQ_?U+A*TJAFu=fL44)*2sgg1C@67%Ru z@ng3|^()$rOyA|~#Cp2%Ug-34Qczv_ucI-&P=7bIBCoiJsHU7se2S9mP5L##L_)_j zhCT%xpiaStXYiKeb%;RL-!X|Y8P_bkSG#&MqAlJ_Jj@(NLEUqGX-ho3Z`&+8E_kPCEWzo`#$v8fqz1ec z!}9wi41WdRKp?2j6;B~B6X(PC_f*Mu9&4DTVO;je=;R>6;}W+95ZrsXNGhUP3=9q$S%%S^WP!GEj=iHELf1vtVPV)#gp-$HwgZq`sv}2 ziD_bo?e77k7nUDwWkki`Lf7*{re*eDaeRhQLx%Q&(I3olJ@Kayksz_^y)3l@Nc_)J z{-l5kWUQ;Tia(iIoQ9J~IBZ!Qk7K?ls>j7iqb?hgYBt=}r=0V-IX3-QMVs<^U^CQ3 zS`cnTRZ#NdSGgzpl$`+TjfYjjlJLI$bLtBc9u0ZP&g5Yc6=ABZ(-$fzXZ+4)K1jOs z2U5dv2A%7DA`7gFWHys9494j)k-2j=%N7r$SReFCvuKgyG-k3wtI(055B5wv=ry$P zoW)8Z6jFGcmD1T6cX{04Ik|k&b**t z`C1?SVGUPyl2<+nzZMa%PI?#QK?cSSrusO3W(oqJ=z+Cov{>7#c7k}m7(h)4QLIK~ zj6kE_{nGee*Shm$HK+q$I(*(5B{3S3pci(c1>cdbs`*ptyYxq0e_oJH2 zM}Q=Li{<%^NH`j~3A$tcNR)@rf=V$GdJ71@i8Klci&ee@QxiWf3b=OW6spd!f}shc z=piA)kNO{r467FZ?Gh?AOIf+Z(5zTAqxg>v?Vnp=K<}lX98e+`cscMx?O6K5sD~5P zXt~*Iy zqiRUM|CvM--{%TmJvcyl#3E@PMvAgF! z(_xVxUz&aSw~?70Bd%Z*YN@YN#}emj@hqVy;;}IkPKqDBt6#xd91*;%*2b;^V|ng! zYb}7vpGz`GIv2z#N2sLyB|2%ttv6?(^8)QOy*?SzO;>xgtDPEp`F{;ec`b(pLLPgK*O;?v^S{EqeCDPQSHW1Pkrvm%=az z>W8A_m1`}tH|a|t)FoNbAdS{)*bp`JaI=Yr$ODW$&}6%&s~%Lnfb)}aDaz&s%_4ih z@STS%%5?2uPq?D0!_oSSnha1EgviDaU^N| zT#}BjXDticeGWIgvLEz3&Jqp2M4rLu&az+A+F{;&n5(?jDRk(plfAp89`F)RrY+SV zx~<#ng{$K2tK9pH*qWtG+;H2PL6ZnSW9pYGt4C{945iKNfXc05`rmzm(k;zw@87Sd z2xH!nqjSox9G(pX8Z07`LL1S)!=QOho-T#eu)>D%CAxKpsLp4g!+S_+ndvHLXs*-r zc=!UMw#NpP0Gl7~5ec^%>(csfuL|BBZ^oqou09EgCE%nZz;44WQ_A~to5JK1m7PG` zRMCMj^zZ=h(;Gor#9d*h{F$k?ihR29Pp*o$HE}(}nJ$+{Lu?#^)318>$|SUA(Eczi zg^t#muWjH>RGmF=EvGQ)IgD3&mMwe^yg#2xy-N?AfGveZBNMY&i6SvI_J*Lt=EhD0 z4EsN9Z}E6=$L_A&Y)=*@SqjaD;-f;1h9+I5)n{ZKr%hHo_zg2AQF|E{BjaYwR~r1j zQIbcWE6bj*b`BD-)Uyz}KOn3!TSwht+VpIkc&@F|uhkqx#OT|w@R*Z=g^W7qLNXI} ze_3@4c?*3f5NzSoWs-qgsoWjldRGbnYvMOoS?jnn)xH1vld%HHhQD{@{n42uLu$$9 z-#%;nk6o2H2Fv9}v4+1XVdXE7pRayU=47ngUCZ@Et2=-Gj;xDBhE)I+VC*+*!MnZ z8J4;tk?7BBlON#v20=FHHe=-#=r*V-3A!JHi1|n-;MsG_p%b>^y5dN(LUUm@Isuoa zZCdb9SJWEYpau!TRe}Zkr@)e~kP-V%EL)EH!STFT2O9-X8Wja!o@|Rig9flS{V${B zKTF~t*K4)e1=>46)W~{+5Y*?YC|!k!{=&L5t}T_+$^K)*lOkg&#v&SP2Gk<=#@nU{4Y(BEvnnO3SMX^ zR1TwnR{WI2_P=AVHQsQuaahln8{Zf`cYp98 zeBY!O@*_gTd#!4Cbk4*r7gluoS>ExX78Ne|sh8KlRicPTkp#uJ70h0%KZc5@i;dY9 z^8wSgYn0f@VakU#*FaRak@Q4iG3p$C-c^}zBVxjc`?UqBR>p&;Mx@cruOgePexn(! z!0XA?yOaVrr*h@lIQH#A3H=YE4C`|G0_q2Uvwo`MUKO}10JjW*0r~JqUfqtF}W9B*IeEuy>}L(M8}tk4Qy5f zq#QIRYDNM?vGus4CHh|Nb{qGfwzPG^#FJiP%T;_u>I((9TD?AfpM_C3SbwWd+)uF0uuiRwAx@gC3N^8Y$RsY$EANNx-YCu2%&$5;?_ebrz9#r4+ zX{=xaL5O)-Cx0EWNaIbza=kAK+(MWR)%@0gf@`T3u_C+bRpSZ&+RwpPhDh<3DM|LL zQBq{NEGTgOH0Ta5&^LX;^(8t#3Xi?r@dEJ-aEQk)>(=)vpN-Ebu@BG zz>z#@IOzI-sWxw1(1D^ubWCy(*z$VaUDyvv=)NtKJP9(+Dd|EeDSC&2@}2$*?k{3&)hBAJ{Q!mKX8C=kyNcTzw)fB{N0{+9Qri=O0ZD%FlSf z@6DYRPg;t)X%)&E-S}$_#?Xs0iSPh1XjLCdnS9~qJ3gL15#VqB7zVx;fD?pXQXn`^ zz1$38uIluPM;y~oh@di0z|>5OEyW=QPIY|3rWj`QZ>u+ZBbT4SQb#6e0LU8nZy(ts zy~^nac&%w6UL(q8LkHwe=l<)V@(LTbZ00E**)ti7(Ltzeb^r2Y0*r~uQH!T_TX7Ta z1J_zV4uDg~860z|u@HU@c)DjtIpPM@9G%6A;$Hi&TZ2^A%A1CIRp zcY4FZL08ko~I9?bCsQ@a*w^K%3;sAt&=GyG7 zXTa@1V9)^mxp)R@fhWVJW2#KOH@aDypO24ggey%GyERXdxQdF~PJ4AC8UEX6u<|eb zi?XzV5cI3qT>6m(1PlNBr;iT!WE(GFYO{j>vla=R1(;A_PnvkjZ|f|q62Tb!nCpVP zhy?|1BJisn_-}1E+5fN}!;jGp(#bLFViu=^*zx5JuTQn=&*#VUOoD-6fWN5~@Ju}` z`*v#$;SlJ-d%eZ=-Kb@MWsh_XYYVfBGXnW6)^FXdlKSWrC-?uwGTKe;fm_FZKRVGbzw+Y%F)Vx&sm{{fpb@Y0y-KW?XZb!Cjg|tOHDz6CBK9s_9tbUENIR> zTPIW-*IX86+`4(z0wTL4Zo7>pvLH*UIz%bk5(QyL1p!)Y*1#at71Rw&h!SuIm+!5< zA@W=j^sC6F0+AHG9X@2H4pm%z%e=iaUcRGegn!xtKvC6z2D`PjhiiMVQHagV*+TpO50x_pS&OzRUBlKnNUa8aE4|7jyrd0QKT z22b+A8+!p3W|$kdOD8@eJ|o-Bp+VyShYJ92pq^qWxcd5`$L(G5CIy7|2xyQ(BqRieNG5)CCL?|cnKP%+LvN-)$ithuV3Ts8QE)TGw;FGUa zV5EdW-)HVx4cmwRVL{h2cx`kOB^0vQ2F=s=*1Vb@Tw zv@2V;H0d*$p&7Mmu&^-OcgSpC%^R_9#IUX7B{!ZvvZ^;%{$I+Yi9_Om1nvLaC`!K8 zibQEo#SKYw%rGqo3g54a)OZ`|b3lY5Hf_OT)wugVFG=gt-cGd?5JED(#}gUi%1sH} z8{-qN0m>5oirX)lr`^^zq(e80{Eb@}cZRZbY2}MS{~c}M1(@i`C=&gzCG<}5URctm zM>&E43EvW)06T$zd&o1agkK@-m4+WZz8H4(g(Oqq;}24n;5%?O-~$mED`;VTfU*fS zBKI*fE0XbRzlemXaR9Cp%~765paCm+<5Vup1Q7r-xPbqO z$RV|LZO$fcvBk4}tI7Z<-~dHf*ZPGn7NNWcl^sR(E^X4c-qUSJ!CpbDmyNKgK$Gq~ zBFbY#$6c0D@@=l6D{J%+$-dTqZ3t{w$&!f%JO*TE&SWKaYkGVUs>%`JL*k>GqLrEN z-!l@FN};Jakv;FzcBCA0Ae+5_e{ShczKUHI>@)n*N}s67)=y!)_b8O^jddSK1ibA* zsOoqn%m{83`(eQHc6i{N&@LYbw&m3~i&e!fq;jT8WtE;0F-o8}WnD9Y{_2Y8OuB>wKP-irfWl@tZG z>pvg9J&ry9lUV`Z%SB@W%GTC>gsE%V-(DpS>{^Zt6(=@~uUQjRYV@jDK}ansOPss7 z5Xt5Rk5+`tb%%dEw?O0Q`#UGmVu}cV7wMfzHF#|nkSC?+ftIWQJkBsB6#P?dHO;&m zhfXY$DWbmMCKz7zS73G0B<%&EL+PV!cEhOq8h-ZAe2)OG{() zZ7PxSsecS&fm%bC1m5<6`+96n>`Fag;Nxi4Q~?vTgI2KiN#Gc`Z|HAYOI7Xu2SLd2 zgmV5x3&~>`g&pRbFPkS^;7ceVx5%#>JjOG6EF!VA;~q_QQ&D^<+6!}Dp`}Zk$Id^^ zfhXSwd*=v+$=fMrq*9x6)ZLY@Y+OCRIP%%=+<9P^CZoMJ@i;li3on)-g5v4(erXjn(C=`5Zvd!bk7w+U9yPyBqS~Sct*I!I1 z{WxIXkyS5u<-Q3?R-ZFB#fiC1XxN$R+iU+3hrKhkydw(Iy2!AH>Xn+R6tpU)9o-RF zu*eN-_!_Xk&Z`kd>5R6iNcp?Bz5l+L&zd2+;R6ET0btMxr(jSo;!dgxykbMNZ>6Nb zCZ8R7P-?Z`#Cd(mm{G9lamM07`b;a8!HhF+oObYp*Jh_ZOw%%7NzM_uaTL_SCQBZ< zf;kH~awkZkw9Y^r2t{PPrr>sA-?R0>r!${`Z?i1WS&HGn0by;Tpu{h8e7POlspuCz zJcV|wtx{VrqhO7JzYzMj+L8T6#re8{y^vo)+MOe-zAcnvF@})Kn1^-;gWa!C+cE>MlS0Jp*RYjT% z2z3~D*E?%+6EF86Wy-33jL-w^cHN%O2qZNzsFd+sJ(7& z9(86Z3+gWpK+_kbk6pUsA43Q(F4c3@AM;W!P<(O(2TI?q(^yKXWz_&vY~)f6dF9Ox#~P~q}ZgeVpNtSiuMhF+B?z_r8Z1| zIm+b9`@Q<`4?fAy0@FkLiyw2@=Djn=tXx(B& zTh7uedwcA5jZx_nH5|5Ub0M-{n&E!c`DF@dBr>Zv-H3CWBC0?niG}r)~xB0l@8hf;@q^ad(;J zLOV2;YxCNZ&)2)gtw1g~q$50_+rnk6T3DQj-WwL>3cPk7USJJUbFvQ_a^QC+t|wl$ z%S*hk?s)!IE4%g6;10|y11QIGZ-IE6mj^jPecGMc#8)EAt!8j`Vh$kg?l_esLA!YF zq@LF>#@w>MY?tYh!bA;3f5cfTT6z zo;-r#0eH+@H;bI>Xo@xbH%PlMX(&O`1;gqCH}*iaC)N%vsr z@}{-!3I&0J6LG1JjU<7fizOXMd7yVgNGlQlSgNYibJrvOZO?P?UB8$Flu#{M>Dyfo zA!OI&)I91xlSKh{H5#lC@##{HceNo6sbB?VQKxOH(VU?4FZ{USeGR9sj$8YNXdiJq zqRosEe5gNrZ?m)zd1W8@NPbr)mQK(V@dTFg#Lwn335?J9!!X}Gw^|jBK`O-C1Ecp} zr$|z_F5;XunM#mHOe-U1xXsuyhm#=M|fVy|CLns;07qlzp-w86-=T9Oh+c?dpp>&_r9cb zE;7_EpQt$v_Q4Vn1=|zmSKes&vNUNP+2fF9NZLv16+tkYiEHz^`%tPLGreg_O|%Nf zypRggbM;v}Q=I+1_ZUq7!U&8yOwX4;i&Oj#gW&baM%PDb++BStOnfe3YLjQqs=4o8 zQj{Jv4DO7QD*tqUA-EfBdt?UzjD|w$^I>MRunr+qkAAkkm-Gdmm{qze^y=5Q5jb#@ zSRni4zx&yKcXwX@Am-rfhrbF-FQEHG#B&9r+sqb#!B64Ui*djtBG6 z2mtTgqn3wXFVj}+{`~ESM_qwNVuQ4qBCUwQFX50YqURjIaDb8^J_3J!xD5K}V+FH> zkC^30yepOCEy!yAIZ*?_hbI!6eI|dh^dfjVu~7UaiatT zs0}eGuv~SPciNqP8F~zxqrB5cCYxc!9MSnF!%%{JTHkvr9~qLuta}NYcY_c%21xcUu-MHolhq)D_GS+CHl%wni$7%@hVx5! z2^C@B#td(opyG>CEC{}-&@@8%NrsQ`1ulCKn*T3?tne#ui-yIXcSsU-gG#gH|0aFzOP;ZA9@9RXkJ_|Vx-G^ z435J;ap8H4DppKeT3gc@*KaIp_&T!I?gV$QSGx26Y(GUm#WxQje`!>B<*%)SK#Se)+obd3wBg4OJgedV*4RfDZp1;{WxA2RPZXWD;CR6dK zpI^U1>#nan|6m=a4bqn~i~Kjn<-MkHlzXyZCfvFh)8(e8)d_^qbbP{<JXnh;8|nj|QKm@l4D-mm_N?Rr=Iy0jCA^b&tNsO?T=4n#f2T%}L{lV(1DK5A2> zEDIs-ER*FFPO$yduYf|7N`3w^Sjbk%U77y(39kbMlX^yhX77tCeN{Tem*2kYr9U6) z_P73XeqmpI!V}!uVo^c)Tlf906!&?TxkiI~Nldn0iI9QW&Vt+YPq`P4Ya@ykpIBD>mhV zG5(6ZkGG^^Hk}~g?j^80c_5H;o4#-k&KzjY$*-24R&i49471-B zpov#;MUX)$bzFQZ*8>rnT+aWGxA%@`v+e(fb?C4<6h+ZN6-BE?ZMFB_Bh=m$u}586 zy-<7a+9G1_724Xhg%Yu6f>;sTb84^azV7e${@uUV>-pn(&ObPloH=tGpZWg0k0bfq zje0G}Om148c3*Hi`}6A?S7*r}tH<Qc}M@zp?A~nQ!dVzMpHnA)A6rOF zXAOh-8KsRG(S-{5vLQMd&PC+!#+S=VC0wCo7u9=k!knrx3#!T)2HomV(O9cvdDbd zH1AtUukR$RyQWMp#~!wr3ixn!IYuCNWqedRZBaClCI+azZC`i@l+{A?bJ+b zAsPb>$QG{EaQL$BJi;4m?IXqqe4q4g_ue}_>tM|q)t<>{lDj&02|yjIgb%$!=&L%8 zOb0|L-fJm`=Y}$q8$8J~{VvX({5s}Q0x+&EsJdD8H(7I+74y;_u&J9$)jqj$)l-F~ zkTS)(qQnKphrDc0l42Zc7c~={Ln54?QP+cL#h?20j}94h@96h3a;E3VBScuBVI+4Q zVhKvOhp+R^N_9V2+##fSPoYft+N?Y7aS&u~AH>0RbwXI}o&%i><~;L9%Lw}BnQX0s zn`5vwj5#f7ymgKIL-+DK+I~TTa;D?MS`cZls<_5k|qHA9s&|ooFUTn1A-PMa*6u%*R9D0AC-=>H^gC zR)%%V&yy`z@)OcvX=$TFeqR!Al?A(+Eeu*!$(=E{lOlZblHBh(G`l*j%vGFyxFIs0 z?;yY(6gz@x`_79UeW#WWH%9gJPB38?RmN8&inS$`@7dYmz1PpXR;t$z7;2&wCZ%NzBBY>%}M`mJ0XR=DQW3>eO#skhXlh8i&~gTCf>u zTJPS8rR#q9Zi#8u9Rwq}lKe0l`o|yF-?tr7d%`c@i0_9cH9IdEyyjE7{mi06HrQEP z=0P3q_^s!eEVyeHV z`}8qErjKdoL2{Qvr(3e8e-C6lZtSsy$pW%rXAo}F-nznlhW67sJQNlP7}Ny&xCftk zNeUZ8u1Q9}G3~rn7jFPxyfpE6C}?W-%|oma!Q3!ERZwcnXX)7fLyGmTn#U3cHOn2R zx>X5sAvgS-l7yly@Qm5xb?*c(H!(&Jun0;8d#dm7FYc}dk`a3xfmc^PkUOk%eKc6M z?D{@0UT2Qiv$0RSHyG@}yatFa_TN;>)N~DpffV3&`b^)y$t1taEs# z{bn1#6?nT6}ex3$DVlC z5_&zxmTJUhKM*0hmeAD@Im-1&3l>%EeC$rHP*f?15`U=4S|KBFc=xRF5X%`d`IPaF zJ>S^tQ=?#2Eh4vL*EdoCSiW7>!_dG2QNi52OcJ}75B*?sym zzmKhHD>-)K3H2XS?n4U2P;awp>7In>D~|Iu4%fTflz%{O#|;mByD#{2cBO-720T_5 zHAFV8#byaNjAyvjY^D;3^pko?$VCAU`C0FWiCir1`(9lnZL+D^I5#3 zwjS`ULg{dt_LG}b`Zzha3APxo@aL8GwU2FLXvb)KpIhzjq{8S`8MAb*dc6yvVcn}7 zBE_UxB)qcWpOhOK97vF47=iww(^@}=jS26KR_?zlGbGvQ|T#u&G+FBe>x)eOVid!1I97MZQ_QQquxy*5Y%xBGj;7>El==OBCK9BUA<&gbT zHrfQUo0RwdsEyQ2x&c=@aH(>&Xy+SnWrU9>Y~0f(`D|YIh8VP3I**PfDS)nM2pjRm zJWAIpx=H@jZt%;cJLjB}-6pk~L#7rUjrKi`d4*9W4y@4|D0ZY*q5Y)e)Q5G;4^}FR zM1xy$UxKDu0!S@(UOkJgq2+wkxLX`yBFhL^WCZB2_#Lubsd(Lyq1(hX)dStLXI{xH zkoX7UW+}`Cvl33R){_ycMpEqYswvHA$K79WBK>~f?04(HqzU$Q6F-p|Wk7}J^sl$d z{=~ntjSB(-h-|0dT+ZF~n%*j|yJPH~aiFM<#}ZXFw6z-g(ndnf`!Fum&oMK|f1+G1hPzm%q&g%);HR%*i0fdc3*ryp6|NZJo=^Ub~us8g{(~1j5GD0HrzTlBt4%}`lvYR*z{o?Lbc)g-O-;fZ5`Ls5cy$!pYd4uM=u7@+L@-+%Fl;f z6{!nLC+0JchRa7<13zg|QC;NaoYko3oF(|d!#^(|^k#j<>_$-g$5{`AtmxWeJD7nL z_Jmsfk%0`?2UAT6_pI>i1hqHdMNh|MgTE*?$bYy)Cg!GG!}KSP|0~5e$T!*G14XL( z^$5$ZF*c)-zyU^rcTD9$;rsOrA{CElMOQX5*ur#VyK=Fm5b5YgK}jNAQfO6Of>~*8 z<;T*3)|E(^5!gZ6HCva4uG?#`0?lSdv%5^fyEg`vqaV?#2;~uH$`L$&XMLTvG+dq6 zmy&;*?(^dy*WpQyo6-Ce{cqHJ3|@cO*-@nj;^t_?lh;*HAiG_QW$N6(2-9<}FgH>s zr=fa6LI<-7%Y$=+T}_j01;+hywZYw0T0M&!9erJ!B!bK$IZKiIXC5QnLVU1e$!K9O zcYS95c;R9HI`i)hG@_8%1hA7#QDwo-tB}8AtIGb*$A0~vYSem0v5%B9*~0excusum z8tVK|oq$kCq==cEvT@f4O3R12SPXO3h?BhuZ$5btrDRG$wVt;AndhAlyPSGtG)c%i zjXC1A&KZXH7GzixGrE9}1Bh9~z_Zwu9#gu=?5Ck5)StzJ_%38-;jW*pYZGo>-4~On z>MWM8AQc_RE4Qp_F8cs!xu3mtv$f*hhDi?Hr})phwIlf3oIjAW`K}iCXo|CpVu*8X zUn^Q8gEgyFFXW{$vC!w@M2JB>_$8%@Bw-LVPWGGX0_v%HYM$p*%_g}GWU*#Fhq3JqwjFYy%m)HA z`**e)JU_PUW)g#1E$x{gVVlWa3V#guormX0At z_oypK*yDyf*%%TCX0Hl5#NLgENCi7P($J86k5!Bw>Y=I`#Pc&dj)XmyaQO+Uyb@qV za8uzM*_dPbBRYq;CeM=Rsmu2iuWiH_K1~1i_N&1&rrur&FLfSG-pS{9Wq<36>Ar0j z|BBRT_KA_9kyoIwJZF#*UWaotcRqDxV|3?*(Z>ClB?OKmT39W_H!$9v-qi6EE&M|T zDrs(iy}ZS>Uf4$n)Snr;zIJ42+Wf1+1^ilAxVT15K6rc}UdndCE|1VTyQvB#`BgUf zc}L+jE9Z6=g7v6~A(A%}uMa7YY3r1-v4`f;Pu^8KAH9reqqc8M4ui837?6aUKLZM} zVZxC8D%HRD0z963Li-0^Nwdb!qdP$jU#@CSa9xJi9QlcfKsUPoaZp_P$KZ#YWUr(x z%SWDeZzgg^X!U*Rntf0+_v5=E34#5~rl4wpyNLcY(loYX1pu8`qVSrNO!e>A=3dNg z+`s!40RDHoH@^eo=}EwCN`rtFKd&lSd~##MLTWVRB%6Y26hZjt{Wp#_(70|4s&6U^ zWvljbxXgtO*Wj?a2?0Q)u=ms0 z!uorfNav>FX2_(uzFgCPwsCvo%gfa9n*_RdpoLMPYNQiFDUa@s5C%(@8{_C3$%T=A zr7nbZ{GZL8>5-NAckvwWbL;J|+gX`QycQvT(py6*pF!I_Sg4jmBRVGz6?x9w^1xpz zcTMPN!jtqbH`Cvbu=DF#CR-$+>Kdv8wXL&GE5-txp8qjpTN{qxEn6}1Tx_3SFo+tf(20OR-J zr{ObKXm|fAdyOjT#oLN&q%U@ZJq7h*}hhGHXMyOXiX^UV?h@Yo9_v2Wq~Vq zQ2e7pP?IU+#74(rd_s9eqhGEGZ;SDhn*q13&(yllAho4mO7>vm{a2D3P<89#z3HBQ z%}ytsEiqHOhlw{zOMRddu+L;}y=RCGpj1oTwX%1o!kR3E+umU4o2~InLe@}2pHOpI ze7_=f?R)&%H*cFegarNai<0IQu~ISu4}0T+s_diJI;lZ%tA?x)>-g{PZ!^LM0?kQk zT=5~Ay0h3Tt!f<8ZPE>cj1yS91BI&YFRzx4*`%)N#)L4>zuM-x^xojRpd9tad!B=U zX!>vHHv9YsxfbMno3Z5Sh3qt(4gtzkRJn`Grp~=JQ7}VaGR7QL>lcw;lmxl)o$h68 z8LpfoA1P_F{btIJPuuqJCIfxlQ6cMl;tI8c$#XflTewi!%4wf)s&SvFUziuL#V&fi z;vj^iid(Qj^~`hFq*Fr2a~js}`q=ihI0vLs)xu}D-WuHI)2zd0-oX0Aap4OtYBPAC zMbhGH!!3Vil5^1NGB!B5Y`VD%D50D#vdG*7tiOKc8b}YDwR`g#ywUsg82VlI+Rxbz zC@E~q){$UKfccgPd9!}Urq<|-&b>1M;O8rc&YaGU6&|0p9KYPKoto)eZ&HE%_;%YI zhjZ1c_3>O6R~Rrust8LzCvYZ=+ywL@9_i6&U8};(2Fon|JXIz*52|qgY>yW#UW+EV zM{Sa-L-s)_vzUP3wT^X}tEz4GU{qI|SuxVQQgZ{Y@lwyTX+yB;r^(9p$Rn-Y7gw3o z&1XIP=!CqW(HXiogoe#1LYr=}WNkP-IogwoDM7<{u&mrdsenMA9CSukn_j(VYp_q>fgp%D2zV^whjQKV?FQLSlY+NA7=QoAh}#edC%S#_Q{c z?h>Jlsz2~h>f|I88!UFJY4aQMp&XCFqk4WHA#=WOe@ng`sBx|-E*|S0oTgE-`Bbea zFv7``C6G@(Qe8@$b{s~zheVS&e=v|HesPtOps9Dwo&62u!OPogt?b$c>E`v@LnX|@e217oi0O)Z*;C}) zWOPLRlQdtt=m;3B$}OC);Su5)SL@5C#H9DA2p+mJ`8?*PV-d6a3lKqu((GP*wWDjRB&`%dW&q=uSdB!8YN zr?TFoj#5{qy7G*JK+OG>k@*W23Spin!uc9H4Y@hh8VBzJH3D8W8Y{-IaLGbY9chly z_avhqxms-T-yZ0$!QX^AUoz)*FS|*{+$lJbxw@e1^&HySuKg;{M^f?`v%&RFiAF}M zuEn>SbL?^Jp`(;6ddW@Gs2_iun>inI^vN9T{U15k6szBa#tCat&kL8(>WfRU`F>!q znsPpSB_|w-au6AIMh}k3Z3i2Cig-{ynZRn8yWX}hyIpeMRU)vhH$02^z3mQ`C%Yjqc+mGD_+W<)&wIE6U5gVdOf3{KC{#>1!T~X>QTSy8x(ab&!a@`U{pwx>5k(;Ay1QXJ(2KZ6b|{YtWX}HpjS|(fnn|(VOcKp$uMd zu_NAVq&$497oku+0s{A+{48ncAVoH2_w@TAbKn0A(^Py+hw(BEam#Cp zH`E@JSbf(4)JyGtKb-SFY0G$@X;MhW*kr~(n`HF5LZ#o3YOrio7K#@lI0>P%7tapA zTb-ylK8YL3J@IJ! z^6!GTGhV!P`95?%OLQoMO+90aZSWhGR>)a#Nk9)sUEzA%RY$DJTT3SWgFo744E#!T zF^~4-C*)!+tpQwp2TQftr+rJ)$rv&fyl|6#omo(z6K!|#P6G^o^wJ=Cj^m-w+hhw) z&PJmx*Po=AP>TdT%L&rntf{EZ4FI_KwJq$%+`$wDF!TbP$cqe7!(y|eEv$F`Dl7SflKj{9^EROPz5t+u68C;cfYrNS%bo)du0Z~u$2LnxEdlFv4M)IVl@?M?~h+&2s6No`<`^>z029hu@_XKn15$c>89o;wAV# zXQ*7=0Q!Q8br6ZZsC1ndjSgzm6!qsCpz=5M0#L?t;TCet3!~za-mUT5-to<;lZPM9 z`o5ln+W7g4DJ|zIDAgx8SjG%VoH-l#2?(MtubbTYx{0Ua%kBcE#-*JbR3k|?IQ(wV z3OtN9H&)0VppK-ypSG zx(TOVr**OdIm+F&DJ}EYJQ@#SHBvcDgrx!PAb2F=^oEm^*A6i_DR_M$L7x zp-vghHk~2wIQt&mo+e^xVpsQ6C~{LdamZ_(T^gYMAGiAzGtE^*`KZY5w#fo|j2gNt z3~|h^GpS}$V?~Mr(XW~u!yFAy*JzJ@SZWyPWa0nOjf&!rrV6q<)KvPHe@*#q;K+=_ zaNuL0Q)rj9c8PQCWJMP@ls(pz;>o;l@CfA<$**Viu-h!K?qNnLK@7Nx%kZhx(q{cF-`CTE`4O|_Bhxf)eqCnlNVaq_i?2((>g zBYkm=AQ8MdzB9aCd29>kkDFIUFn6OSMOc2GS^vn+LbP9vg++@qshe!=tdRa%WcyWD z{ql_13o|og3V7_`HxeFA0u*`+6T-J$7vdjpmso~?rQq>wZ;MI#!06U7d3R>|@tdIg zh*`?drd=e4);E6-`49D%rh*hZiWi+@WveyQf4B!}R`Z48>XMs8a&FQMwaV?S>hb|E zitS%;1)g57Z~glql#5TaOHN*Rf&U!AO!t>fn)ooXImC!N;Q^NVZcn^yhGu2OG-^`3 zTL}yF-nz!Oq;l`y-wu=>zvi%jJE>9tx{d3xM6=;g-@DbWK)lo4iD=xJt0VS3*TjhP zQtr1$>8&mU;{XKxkrZT|EEx^-N^Lbud&Zq4@Jz{l?+@BAi8RBRxxk393V%BDyZwQ` zt@&*bRVWDnqAqdX`t+!g`d=OdK$|nq382$daP4cZceBZxxXneo>Qv!jU(z*8Zy%L? zaB6=hAm4v8-QTvx$2{Z?cTA-MI2u4M)cp=REp?Ek=#j4~HCEr^Pd_hqDgG_qk4lc` zWJ~qYB;hnXMcd>YRp@WOLjA8lJN@F!R_+oR&TT0GZX;?>dsRH6r0GmS}JM<-cYG@H4M?8+$#H{i-!FqGm0N_x3odE<+`~asP`<{vTq7 z9zLO<0T!jg4vq&8sl`|9Ze%vL-TY-B1j7$CCW$S2Fk<#@u7JH0{%retX|6rcB(M#V z9hiQH{PRUt0InJ_V7_Rj+ocSQrM35)*Z&d_5Q=i2_!JS5uIXbTH0`bKW`O**T->{n zhriZCe^EPtDDQSN*hk)*e%cM;r(OU2=NF^9z)hnpK@R+TVx3YMy(B*WvPoiHmdA|x zWhRUl-G+fn>;WPJD9H#29=qCpmv|OR!ZEuv2NW&u?}qW^foa5}16Tmm2wy%!0Q z;edVqtHSxmROLL*tl1O);GIG+X4T03mITR;IEHbO(SqUcusx?fL`0-5Bm5%fV&*Tp zHh|(Og%~(}FQ{tn44D7Q|1y7|YI;KzZ7RC5Kytp zJ;-s<+1dGKZMAZ?lKOu3FJk~gJqIPkA_g%J5Cy=?tx{9!*3JrKNo^N-R{cHQbFO*M30S}XCnx@vfU|y$;{2yRP z-?q2^B-4d`(Z{a?#mLKtG=H04bk_aui~D=Vk;7tt&r9~2)HSND9q0T1DOgaSW9{JV zXd0RF7P=v^%aQ2c!`E-1@V5}7F5R{91BCcpf)B`2zm4h%HSkIANupN&y!LxmX=49v zR?<(+YXPIwNX`ACsEY?l{vSh5=}IJu1LBf*wi}57BV9ACz4W3d>E2~IGWaw{*eB2~ zku4p~#T&StqDrm%i{#_oL_j)Iezn1StO+XWCL5IkewmoPcZbIKE*oyK0Zw1t&e00| zW$Rx(;YaVm=!cNFijW{oy3<6c59(tGy!ODVdrUtH*P$NPi6W|gWV=8Os`VfZmf8y$fHz6d}B%u<|On!d0VX3pW3#K>W4A4-V!sWMs=tqwkLsQ~F|QqPeg zxp(UmtIk&Kz$4`_%|`7IZxZUPGg8sPTt4kyhMhPsLPFNUv+mxb3?&dfnZ&;bh2L!C z$c4d7{d~&uY-Fri2k>xCtHh@C-|G82wO|f&Y7~fyGjsiYgbS5R2Zqy|cRWs9j!95u zDgm%&zv!pwdZo*BMJ?lXW|4!)f**s8IvZJZr13TA8LFD`aMGvf)awzdXOmXoBavFn zCvDQjnHcC(IG_ zij|e5&~2A;W6%9YoQ*3)Q&;o;&X;=D=d7v|%j$%ThiKer-Z>vA_9?uiwm>8w>H`~F zxS~8xS6L%T`V*jtlYUdg|B5F-WZCJTiu&|-y0+v;0tD})TfM+uev~xDjjNZn*fMXV zjaI!@H8gzi%yCr6d5#u&`3y{c#j0xc&V3#qpD+4{oq-s^T9P#U4nttNra#reN;Lar z8PPgMRlU<*_P}vYYdULDd+#s4D?V2*pBY~vAF#i(>b4;heLnNY{Jd!@-YxRKMzG`* zKf_NSdHkoIX^b}`+k09TQnP(5{%h|4r7iV#LzMR*BqgBTu-X0Xt3$>^9igI@>q=_a zbKk-_qusBYWlC65l!A_Zql&RGI0h}JzNFKz8x_lqkKyFT#Uu#cO1)t}N_?eZZOrKD z8lb+Y^utV>U*15_|F6_R&3cs9d+39ix|Gh19eSBk;|ndSIVsfX5Q0b@lMN=PyWhLd zO4;;9aMM$5Mq6IpfllB{ru>+rL~0418LhNNr*PL4w6tuRY>YKD_WMCv&UoLY_1mLk@2M`8 z8m~g^R7Tp2@PnI1kwb%ttl*xUQtKblxFv-{1#syHAH(_^|0Mf=vg$7f`rlXpczJwR z#wl^}&hH#gVD(SppfLND2Y<~$%WgV2kb=l4EdlNzJ#4UCGxzE)oB$3HWW>_9aC%pD?on_h``|4 ze>qQzy~tO;j-S9f%irfF#J?cRuZRD)^YvVpHcz7otnS8mR$dDCS~jhvu=U)_TN7YPWUKH@_v!&)ZgNqC|BtOZwH}N zYylPQPinBI)~bKHa%?kNl~?p`^v4;6Y*_A0>AG%*=#YOz(%;@GqTCgU5{ z&ncnuF(*)Ni`9q1YSYG?zLnylO?>hWqW6p5;QjJ;(izCa?#B4T zvs#SUN@;9~iD9+DRT`Zm3cV2+j{yqkGT9nv0Y zSlD*XF;?xwF&6q!1FUy;&xrd#?o>AY(hI;@++!M7ZZ^2hcB7khh!HrchBqxlL_}vN z-6KVO8RNy4r*3CiV7sa3%jd8JHZU<9AW}B& zl|GN^a{O(Svzr~FAC|-0IbFy`2FmIt7aig)42XX)Y|R=jgkklTT+xC4fC?zr zkCP$q)&6sJ*irguz-S(NYstL1;?E(O_i_LopB8$UB6Mf~rhXyjgQ&C370;Yqlxs*t z-zdx{7EPYQ&)x{}+2&%`Z9@F$C3q-jdcqJ>VX=I*xoY_#si>U?AzYlLAS9ycOpb1} zCRQJTEQzno7+E#w*F5jTqG3=$Ht|n42w3K!<8qzpEvdnzNEHW8oE)oWV%S+8)e(2J z%JBX$m)595R>LEvm9(#qDT*{xdoK^sQ;HFN_kmXcvwCbS93d<(r6ZF6j)5*a)td@a z8@V~2!{Dg#1z{O~4Y29WJLjiGhWn*rM}(S3h@gh`2rPKLdBII_C}Jkwfg_d(11W3Z zNXluD`l!BU8BdrirU&WK)RE$GFZ&zn5NfKBh+qC;!sy3g3L_w3cp)eGM)S%#vHhSR zc|K&mZWrt_5~b8VE-9=cAot15sldnsQ!H^b1Nl@sr9lkxk_e-2zLpzp3@tE(xMGb9 zMlz2x{m*bzr+Z7U1keHB+|cZ=G@nAW)v|VK<7^eW;`Pti^H?>a(G)J8*K$=(@NCCA zt?a(Gqj-9y`n<~J=|O|^{hta2B2`+QX~SxVqza=iKAp17(r^C?Wp2c)_z67p{C&5r zdncRsYTR-_M%o^v43wp*UBr&SdBSVr9HT?s@6r2ylwuvFj7R)zODL-PQIPEoW_dwy zP0jqh!&!W(&HSFX0C@JL?d{#zse&ebFLkZ>`|pTyHS!WpoC14%(sJ59RjZ@Y3@K`a z#e^6E&YhtrHZ$kJHcuVmP6eKVtq*kAPQmCN0x2Z2r;+McxKSZ84r!| z2=MT!DZz)?8&rbCnl?UO^*z08i??L8D3DqpP)R6_jBdRC-id3<$o_+L50ecVkJ6(x zGhi>K;pssymKE8g95!=Y;OMzXyD?oGDKPwn*jf7r-mXPp|EB?XxjEO$@-%x#Obn^r zH~OmdL1jVe}=Shi^7KyK3<|dRP)ly(k%e>+=G!;5HL%Et;kZAkW zCO|v5R}|5AJp*=_=$~yP;SN)S73p*71vKtlQaX3c^GD8W1dXA<2lafbV{c_36r}8z zWZM1UM*)b>pQNq#KCB(NZ%`f*r9yk7gSdA};A?|V1*hxJz?rLUw9=~~Yoe=>`s~%` z6HmZ1>;=~N%TG9OcIkGv7*D`2uaV@aY#Yg;lQ1aSU=k4P;GLi4s05<6N(dy$XdUo*SALteJ;y0i0>*fE7;r<)8`~UNKUt#aP8%bo* zYYiUQlISNgDG`6+%7=sroW>PvnlGL|>82IdkV%(p(P# z%m4>z6euIcUQWGi$oe{L);W ziZ(V7%f6I6vk3mD4g>Z6r{3YzucWcf_>7VUG%FZA%Hl9UdND7^-qQL z)0+mRHDkMG4e zC)QwiQO)LtYVh70VY`!-ckiz7Yz`?^6Ytr_FAC>WVx1L;5bzGZlTJuk4A17Ry$3DYaylK zR?QUgbDOY8gn*j8S$gYy4_$y|3;B@(m2nCk!z@7if=35i9bLfIeD`ENNzVS%tp3u0N&yi{r>6yp>F>mZHe$!3KJ!g}h1Nkzr)XMs{c=5@=@&*LpFBe7JInV(7a3L+#;hRlrTEJL!E20a+oWf~_TD zii(P=Y(}0oAIyj8H@HDI;phGchz7HT9vd4Q?(7(g*&PraZ>KUY9#Ixl`uOpqoTww5 z?W_bQg{mq!jxFlpbbrWlAnikE8eo@umU}%gu=5DY=yRq zo)iYaPZ@CV6MZGGz08|4Gw?YDCI5qW&1XOsKFd+BM)PPcEH^^Fy}bhd)_%S4rxNq( z1D!mJ((uu)0+F$C;sk4l_7HFP!%6}EBS%>fe1wpUF+zC>ry%B+T*`xhux8(`j7%Ai{el*b&aZACQZ zm+qf?!zL&7uAFaYi)6r6cR`JMbmtxgN5;EFV}$Ngz!v%(@H99R+M5(v?ba?7E(&g@ ze~q@{qhra%TYx9?nRb`^QgMS4x7K>tN=L_y17KpUX9CSD<%w0*g{fmTv~L10qNJGo zRTn#h7IuJ|{h76p;bVPJ#>Tx>Jc64mFlKbOI+t$-YWuyxRAU=03vw`eNCV~WRNRU# z-J4^c0ak{U2lC#lc(v1ke=z0XMqz%VgI}rjO4E8jcjW|N)0Uah2?d>YCnGtdR#dg& zriG*PG906`0aTbtJ}SHRuaJi40ihf;C%OK`p}vuxNL7;sK^p&QBYpQpvy@8TWD&Yr zIOXTpDmfxkO$(R)FNJv7io7qQgg>VdZ~nOP`ScPuDcrmw|8sf{mUTcg_QWCOa7sZx zV6VAh?I(cGA)Qfo(C1U#DSI8Z>HcyGOQR@-0@7)P9nSI4%f!`u#%6TRo9zN(@ki(| zp~D237Cl5o2+f&ibcxTNiPGA!Zr8bPSKL;pGe}P_8RWYyB{zH#djhXq*FHCvlM6XJ z90)-73t~r$w4iQXk3LEIes12MR0yZ#8-t(WI4_)!=C$(|^cXC4XWbueOicNFFzS(n zTMtXYYIYch`bfSKxqlkJaUY^#Qzif5qYH-vmPEi~5I>&TVW`{pwqpbMNDX1iZl5-x zOUl~k@&QaReE{g%2ImMmQvvZzCZ@)&gS~ULp|-YgwJgl-ZS#cpS`K#4z|j>a8)Ug=wg4_V60-z*no+xY0?LboY=Y(A!5j)G?W{kILj+;RniuMk?bOUNJ@f!?j`Z)yFJG&`(;=;IaFg z>mzZ5Gf;JQEw+wt6WY~^V24O{hUXqGd8XTcoFPS;_`4oI|Dh%tjD>+qZ z7Bga9M&tNELrH8pg{CJ@(Bs}v%g9EL(-^lIB<5ZrQu=sfT-jjSUy`$=FlIgdvb#3TfWF zyU8ZwykH~n`Zh{4O(T1gX*k$3V1c)dIkXzKUOr-6;nH>$b+{#{kNDDf1akgU|JvE$ zq{WQ&Sr6$Bn|N>L)R@4*4_8Ft%M$eW)t0Fgi=H`@Im~4q$Qw6n-3WD%RHf@Job*$ zb;v;u{R)$ER>6I(M07Z$rePBWT2f&j9PZIT*lhD1m3)DgI8YhJitwy9Bu?6=Wqq_e z6)5gAF6HQcEK#4JNK-_c?=b{(%E-$XkqhK<;D{#*Ba+ZIEdl;%*3@f4s7W>QEXbWk z;kKkBqyFr1$96vhXuIR;5KtYq+cyf08r{`o7#5e8ZO>25bV7-Vi4i46f-s{-ZKzJE zvealDfOrZIcULf5-)?!BXZ%G-duoFCjC@yk^!b);l+NGggA4>TVitR0rTczPgQAY; z99~4wRo|YOoUI$TgAeX3FNnk``L$qLvgcBlwY@t^Yi(VQF}?h+;KI z8ajaRGyZ|tEe(KbTt6+Qnm&-DXz>=<=|OVu4T{?s7&r)FDVu8#n40(6#ZVRF1>Ota za68AgcIQxrk#7aq$1_;0?ZH|O_i1F*R5gCgt9Cjo=d>D;Z$uMziynXt@$qo{oy67o zYS+E}CgUYeez6tf-IX+wGp&>dD^9+XT6AZ=+4qq>t!xPXbrs5=H4ZYVnSWff9W&Jd zPglc^GS2yU*r(n}1RP+x916%w8nl_aN{#a)$CgSR<83$cN2F)+Dgg%jV2&lFvb%Ij zcwlVCiT;a`>xn?!7?;t>cT>ODOAat0v~P7c%UD~Glh(GAdb2ybJr&($3xI_(qCk*( zeMoyuL2*s9!7J=?kxr#9l?N?Rp}lLermo6IgvSpxRJJ(8t+MCx-*g>~ik@z+c)YEv zULWj5$m4I6?7rS*{eEB6C5*kLsn)kwm;*~yaiO^t!(4|H#iv@3Vz)*j+IxBCrgzVG zUZM4lDuA6SQy2)w8SLZ%J`b!ZR_Po`^qjv;u9GSuYHpD-fC7_ z+V^Pz{%Tr?NpB=;X`@W&U0@>=aI}_uoH_ln@3WpT+w5C3jx$8@EIp4u-N~W!e`Rdk z=V`>*)Tle7LBKteaC*+7e*$#Q2#@hPQx@r`104D8Nr?t*|URyg$=aoX=))-{=*xV!{an) zmLD8(1?!*9ym?T$6+I(sbR0hHr^8Ux)vR@*FS-jlbr|J7eP9g{sTIwg`^2LbQG-dW z#w;e@JDAfma#^qB*^IA5Tfs_VCKpE$CD$L68krTdv;D>QIUL%BMZq=mEJP>}(8gWf zJ07$<7xdts0;J|@F5N4dgX%oDFwLr*Emdft>Y;&rHB;`<{ET`L7X<|Lw$G}{gI5s9 z5DfQocbT~dl}d$RyMiC=@6|hu=4nI&U(6797@{v?254!XfM{bnP8+OPKz@3B04__! zh(}>J0{umhiAA+!*a5lMzLt&~nq~10kQ}eFs>sRBm5iyfMX+jVYHCsu-PHnWFfFLI zTnr7Lh>DwZ+UUV;Jytnp{MI5 zPH2O7&U5v!Fs)t*?;@pV!Y-?jQmCncEmJ5f{u5OH+|&g z;t4>>6HRifJF1cM^zX_orB>}H!hkhhWWZ1g>02dNRvo+P>&A94c+KRxM_ofguFcb{ zS5|cBEY`3_2K@X18HHpA=QL7Lcv zpxgD(k0n{~^Teve1oYJ& z?c-6Sjb`aLN_nPv;|ko31X;1LL;bpDI2lJ&t_yqGc{7m!=nHB$_ZQiFqSa@tpSK{e zBv14Y->cV$7oSJw1~glK-Yg9(s2OA*5G}5B$3dE!4Amoch}va_+oI?$~J)AuSGS-IrL?_`I&5!_nJX}fhZc64cb z9Q-Y?FRoOdk}G+<+D>O_WyP*LhAD;52{ctBJLG$~l&D`}9s;luh&%=fOmtA)++?`aqXv4@;=-iW->7tb|5PzZ z#7joPqt?YA(f<6j*;NxRXGU?5Tah_~kTB~REqOzg?z^-tz%e~jcjRXE*?~zsI?Hy> zj7G>iP=90O4J>6;$7D&~flRgq$X}|R%nmRwpYzfYH=t1o4h3wkNkt*HjuUZ%r!l_m zXvFztI+vXZ^h=ybA804yX;VhQ6Xf{#ez;xr335VzbpKkjx0p{iTrE??%Ln&;;Cgkb zlhat_Ni%r!y)w=D>U|}_dHVFaUfX7YWjXdqyt?p|O()CQ_nJqU@)5L!g@^f^7 zasZ~JXyO*S#fDG-x0a)69OEviw8F6S1)v7`aej+J8!c<_hLx;jTfa@rq^P}m)b}uw zyb;_%j%#(6A&vVMEzSN)sozH{>#s4)h+45C*I8L58Xtg40X93-RE<+h#hl?Qp+_@%h>9&@O)v48c`)|F{I$N$udG?Jwx8Tsu!!Y z>~q^{yN=0;6d9)Tn95Sik%q`b(kIAp12J{AmlHm^I+U}7KSnfqIPutxJ-6`k6UlT( zfpv`h50}uWMh|gvq0XJ1*jv`?8l|@TX$pA&O(pd7!n{8e8L28@_#D+2=C9p34?sD= zp~`Opy&p{Q^>q`prcYwaQyV-sqdWuO#OzFBJ}C6ZpI3V6*PSr4>#7y?oCMoe4$KK` zXJ?^jYL;zwvvW8QOr%!mwOT3+UH}Geh3KqdS86p%a-Vii7cuWlqRYFnHvO~%=*ptY z2&XB-Mh{HR6G246fR4g-!{ek5o&d##g1+I#*kuS8T(-T>T`Te1v2~^?5cdk7I5w$_ zqd`gs)-|B}aCKqjRj7!MP*wovJ4-*ry+JHzMyaySnN?>RK@10~x?U4=8@0QHp_$^6 zG0=gHVqtilQcA)8Qm;8fOHIo2|0h)gs{Gz{54u2C9KB3W&HPbw-gr@S>KvzihMb^w z@&3jkPZeuh3Fj-`Lmf*#(`O${)$~nes>rLSrk#$`nS-y<(e-`OZ((=XyiV)3?igdS z{io0L+E1VD_>0i8}r#|$lZiB{Z(S9GD*n2mJN1WuT z=%$Dc1Y(QU}rsE_WMv_>}#zfk**T`%7*d+X#o zCh5*2{+vWQrLk$Nwrts=wQJX^va(VoB_(?D$tTsOO`G_4 zjH6$_ep*S2LJ#7ke$ZA_?lKM zU!jA0bc^`^-!EUKq6Q6ge!o-GoD2Z6)ppIeGUX`J4@^$^vHe<#;C>#VbE z&u<`=>!a(A)U*3f)%de^N!$FfJ$v@l+_`hLe*JoV^wCF_?sNFzhpTbp#tEJ8be^}j zm1w-U4F$Qrg;%y|)25BajvcEz@4QpXmMzoDl`9i|jNNwIO`}GQa-_fzE+;2Pd+oKC zuDk9!wQt`(;fb9SMS%eT002NLTyXa3I(Nu5Dk#WTr#*I6VVxcG%B}nDcWwNmOdowQ zPcJ=b<7!<101{T9!|(r8hZ}nK1`Qf0FE3AX=FEwCyI#F|rSxKBB*W}BM3KRTx_9rc zXPfE`r4n6cx6%`dZo~ucdCK^0=u=@7xt6H@(p*{!z z001DHJ^$D^y)*q|y*lkb+O)Y;lGLVUbM4i&69onUK-S35&(}#OouoQ->geN-KbFr| z^E&uIAfVp8d+X?vbXvi*<0JTm8*8`@D9TOfb^-Q!|wQ4bM7#mBRl2h=IXfPj#J&bb@kqR y@5%4qF&9BjPL7T_<`^Az*kOhfhGJWBoBs!RuC5XoQw;?G0000a1X)Vf=lBr!QI_0IE}j=lE?P`_I}^- zoiWa-A5E`@9;{V0t7_JL%{x?HP7(AWe6UcS}FtE2^ zAH;-}UDJ+M0P0Gn1kk6vi1sMj&dg#)8sa7EtJ8s-b=YOOW!2@g8kS|6TGm%3i%rF4 zVPC3M4|V13mF;ayA$zQ`P{9LBZyq2aSfHfdZa}sA%*B^PZ~RPqNNc(E5_s>Xmy9an z8}d)1Pl=xf|K~D<+SF(C=b49>k0#R-+6+rCcHZ`*G1GwB9l@ zB0oLc^qp<>v6u|wib+TqoUFFq-fl&oJ>9J3%4dsE@)Hx>i~Z9YF)=Xw1-$Opj~1#? zMY29+3aD3n_8UmO11nf2{kspy25ZqNKK|(Gc_RYbZ^Y{A=9V{BU~BPj-Mjroo3SsB zMybN>!lcG}3ERfTCh5H+rE0l0oTE&Xq2W0{`aieYx}i*qWipx;s#2obF*b%mr&=l` zBZKIEbr4vjRFGr0(Yd!&5Bv~4z37)Io=T!J#3XfPpIS%AJ~)|YPTeZwVl!7 zv}MD72Y`e5_0fWQlM_t}r*+u&P-3oFD7u}Ci-eREEUjv32pk6G=b;1!N`A^ep8nEA zK~TKADR18HTtib-Z+A?7<2hSJ{eF((T~+p{-`&&5?DOn7oGD0hbvV~otWqN1eszS^L@H019>3_oKvW~SO`{kgU z{*nLy!O@N)seGwXdVG(Fa39%|@KR;FA0CjK#D4`v+pdOP#TQgtUq7}*?0}7lX>e_r zgitN*zmV5)H2K-ZoVl4jNe6$J5y>PG`uE2%G|lutqA!mZ5;`{!0SkEwU#lVC@CsH- z=e{*bgd=rm8z3H-7n~&M(t8SVYzGK`0FzJaiO2`%=H-Ua5-iJki3N}GCD*$%ln8Z8 zBD{fvUVedBo4XP&(*AW9l2%q$jC!(vJ_xojB_yJ`Bq|!(ge79LsGc*98X3mM<`ZL> zc}De>7!ea*xlS8$-YO2eQT=`mafJ56vLpqwYn6; zRrcC!#8d}KXQGRxy3S+9;7Wj#vpOW0?gmi!I7yurHW9l(!SGDX&$*H$C99NxXG8$6L21C!PvGYgo_rL_6IMlW&ss_cYPNg>N@5~(k9r1P7=3G z$oEedUGDTB=Q}AaSJ=$Q@lr>aczI+Wb=)O+?6LeTcGZ5gMi$vz%+lK(tblmCNnYWw zqkYs;24Tg=?69Pf_PooCOd=4`6)aj=A?Y^Hk@00E`vO(I*CF+;@h-(b@AGw<`C5!^ zar1@S%KsEoe}$S8yo0w%Vo*`_?sP?TWaP;Cv6mmGO}a6>_RvsvvPAyCvfiq~;94=9BPa)F@ zrDG{lCcT)i_Qvu-rIYa;I&0iDu&3j(?iVL=8cA0d3PEO9H{5Bestc^I{ zOVx=C2blF5-h@r@-7er${=cCkvhe^|9NRUN%+EF%pGZ) z66Jf4XqdE}x>N@kJz6F3#iK}<=R=X5QPU4+zUhFOciVDoSb!Lq3)@O{;Ej1Ywt6x&5Z>r`R)}*p0Tm_DbsNBoOxM}Cc25gy|eSgy@O*3B~WH8XLmeNq0i{sDJ< z6shsV6uw)~9jY;xE^Sf(Kz+0k9nJgGCNpR!5z7ZB{h`)3SGj)qFh<2C{-bdYIc%Y_ z`C5dcuEgHNx!Ft=+0pqU@y<)q*h9lmR=SRtDThSVaQ171VdC~9tv-&kkkFU$e4;jo;E?w_ zLzPvXEacW1W&9_?B+|HS3#}(9yp-G~@DdDHNgHcy2{C<1ubY5j@2{=kKVI|KqmxUa z-n=2Vu!m{5T8p44;aH+$ZViSxkb&)5EfTFDJK&tX2BO%W+?zcu7!;DCIvTJ%9w-Ng z`$KAbHRbl*>P@D`xc5bbbgB6n;F^2R1&f`OhUW_fK6f2nq$Eq&*l+1B-wv%WKgB3>LZh)sTcG zb3uTI%7)yJ=?(>Lh8{<<1N($r-%WL6M;`K;D#5&U{U=_w>dZFwVPS3(%mgh2h)L3e ze@NIADi7dUw=etm9ZcUGcZ?S8O_X92(zZfU0kLs!FYMptT`j6`VQ0zJswVNDU^rPV zpb~?q-jagUVZMlhz1v!=h1@t^z)sEiDKyC7xmw18-@uzw9E;QP6tsSX050_T>@?r* z;28-!`T*XR3FT794aWkkWM`yLzd6Bd+bD87SF5uT0BZnMVR0;U>xR^Qy6L^{^;rSnkG#*8O2Bb}d$U{vqkDALCErZ1paS#l|+#GVEY zR`ZT%2T8*>d<^h8B$2M=(77*1YQ{3z|I6(9@$vrN{$bF^_~I;+l1~-fWXL7{B4FZB z`SEfbHH%G5@J`pk(Z%2!|~B_K=rEV#-koLJWhESGDdKAXDG$Ix7M2w z_2FA{5?U{IG?HoRAf)D878fT1zU8Vn)oLj>H~bi}V}rI52{lr%SbX6@K_;4*bIJ%? zipTqmUo3|^8+Hu#I_uqZ2orxTntNp`6^m$MCV9ZMygPuoDhg?Uyf_m^y0#$Z;j>af z8}(h%?Ro1>cVgeSz^|F;Q=VSkYG~(|Ud6}dXss&*p_M)>=pSesZ%^h4Cnl<^)m@~M zow=POLgwpq(tI8jsZ~B~?&N20^4EXru4|Y!q_jGqOLKn{ZfZdqH-{Z^Q&Nw{7A1fM zuhPQZURYpPqArWLmYO!QP}1#>1>SiV3nFu-t95OvE3kXCYjtG|Kpj9cCXT*n?0O3na zGa~7a%G!|)^clqg@+%r-JhQlz*Y9?nqG-sRY6?!Z>_m+m;{(p`Jty+N#hUSMeRWOC zL46@2r1I202ubkw#x5|#B-=igU@6@3Fc`FNL=~YpCb}0T4DqD=rt%RDpr3sEBR49^ z_1$|zy%TQumrTYGG0>AoB%1yJ+~)FTMvhH2Q+GKGJZZP|*_awqfay)(=1-+Yc}iUz zg5YT!=k{BzclkO)09pv$IdOl0?Rj&igTcgN;iI^S*Aou%UlA{9j1i#;kk?(K;tX0tA5)qZd0rDV zkb_a1*bE*Lc@2)$d+{1)Sr6c3OTyino)~YUiNX0Z44Fneb$J=y+tsUEF)NQ^Y!Pn} zPnCk4Q~Vl*<#+_rpIkkYzW6zk1|)m%!7)5ot?l;-PRXrO%KLdxc?LD4n>_mpG`oT?NXPy5tRabsGC3ijT-E>w4hm#DUJHC4iml!nYLDriO=&hFzu z7*1@Ld_#IYY8ERC*n- zGq8dkP;p~klcdxY<@qRV_pS9Z11RiQwjwRA0w4*EwN>FP(2%fFk(J`KAyGDy~mm#V2 zfAD6{yK}QRW0ZuQzBCXJT7l2=8@Be-5wWIghTOfi?NJ~(bZmWkf|VLO)CZ_s|_-50${ZWpy0BGG?})ZED_-@lED8p2ufMC*)g+-Er*a`E6F1mwKh7%B(NUI${GsOf#NHtVXMm7H|lIRNTWJxqcR~7qo2GU zaZm$1hx`KPR&6{HEg9)19%e<5WFnaIK^2w{RgGw@zm|QCJC`Tuo4Z#Wis;!?&CAA^ z5+LSXseU|qxKUz|6uQvPhxytfv#gygncb&L)l4HZzP+Wvy$QogQ=$by3=&k zsvx~@YvB`6K>kH}T!yNL=M}WN;8@ZPod8*CO85QpQ@T_7vPl~*s%J;k!~++x+#F__ z5(g~#oqaDpMX-$58|cn`_#~gB{eB*z!UYt@7)4ZhwQl|H(T$K;$FySr9t^$G^d8oV zsU6cN!zyslg|%gw6ZYhpcCvctZPv>c7F`^JZS*Z0O3XXoNmj68$%dPL{B63pAS_~h zduYzWV+Ev7T|iQ~+ng_msP-`-o(EsB%Q<}`+4!{Mxv}w(RA9K&A*I?}-rUf-{b&_? z=Dd8r9fjbS>B@Nw;eR}Y zNW2~%<1K@2kQm90&dHAGNPNq6&2NqeKX$eKbX;zIAS*+&h_nFrD|{N`8@@e+MpyRb zp+K(xbkuR?fhP-CIodQP`xd4ufmEPa;fG(@_oecx2|ih)E3Z|MFdBL*+UyM&M+UKa zBxu6Ta&KvNKj3<{xzglCsSup{*rp=|a%^gJ0RF_)t@C&oEln2UEjqL1qhgwLDox*P zGmN|HVmL|LQgkyAO6((Id3sZrDNhWd;OjWIi%kxp+m$N3=_v)eIUuuTa4{O zFs9z-1wT}6iJr>6|LpFHD7Ik&dvphHS-{j2N<{+}=X!U`D$-T{R@fGX4-XCIQ`Z!b z=3~lfoSd}=%n}dyDN`E^0(PcE+Q-1#i=nf2LF3bt&DTuyvkp>vbJKeNIh?xlxsKDJ zGDR&5!%wM?%2^TBbhL{DzHzDQI1W%ic2k{V#E%0f`!CsZ1e0X1uV&~()rrpG?g7LnuLnP#v1>4+u^;|q^)zC)9 zXWl2XuBeZKR;}rX#z!CMH8H~g?w7vxtBv8qeK`d8*VorTekXgZt2s-h@|=t{=X{lE z1o^TNKDxP7rsz1s-lVj93u$~dq2BbTM~_|y%h&gcPyAghhT5F74JV@mF)V4 zUv;7ewmuRzzRbh2srtltaVrg&Wn{rO!HhcgWZWRPLksyir@klKgRX@IB-tQFh&1TW zZt`y#M=m8-ETZg+X3%wd8Tt$Zr3A~5lPZhYa7WUj3>1fU%t*$Gbaq$#fz7h{!vy{! zpFu1T(giBrUtCsCFHXLoJrw6SA-XvQ{WE_P#^E?Pq#!*>?p*IMttNBvR9DWLbncGM*(sf8lRJ!2J! z(x&TIlRR_w?ye4ew}F&@3?Fi}8L|WKDjsL7wr*l^EGQV4zZJPtz#97G9_cj`c+Y*W z>Q?sQ;b?n={<~tS3Bnyd)*=>fa zkoca)LZvK>=czvTJh5cM-NSNmRu%S>y>DNjo!BfWs{83sDKlYVD=?8{FwjX7qg~Ey z+yTmf|1i4&@zzlm*613&D81EF(Hm74 zJ2@@i&wv&tRVd00ACR`f_KHw|hgbAk?`$s*+hc1YQ8H@h54dbayRB$*T)|zGH1{kq z4d68{iz#x@UEBn(ZT!Kgi45)qTPIoW**o1(0~L$hksrWQkm-oL@D0IR=&CT^psaKWrwc-7e z%&jF+TQ}xUavpQ|ZWuJ>82x6N`#L!ipEOvb-g~zrwTZsWglg<@9Ya}olSCEnRjaRD z;bC7AgfqMtv-m3%Y3@DEI6ON4BrMly_w_<}I`bS5ig>v&$95#v2wL`}HK2LbYw`!5 zCm;!0YqK5LeA?pX_<@n`j>cosN~_~{H}6;f7p0fFf5Godx}abcRTt7zud^rz2G^@J ze39q}*rPIhk+MbfxgsBZTBUG~qUg~WHpBO=_9w5nnxcL0&HDA+4yG4?|3%u*huo|v6suffLsEwm|SRjYBNN$xzGVO6Lp_Xwc?Hm_X5X_?!D=c^L?&S zq+@F=={05V2xxf5wA7wp+g~_{og>@1Vpkz{Zl5@<3X6_6KN^u~H?@Qtr0iPpEA&YR zIVS=|Lure`3HB6qdq07btk0!>a79Z5quX7*Z3IMWb6kX;)0XtMPRl;c;V)}W9pf$y z&(>QH5RIJWTx@vSM(lRaqtKm`H)jLpb}#Q+WR`wQvah1-S}E;K&%u<}2mp+LDPqwb zJ9iim;Hfa|11@)-d2a-c_z)udj+7LQTD2u<7NJz3w1MawI(l`6NMA3cs6Wbv-MqKe z-5rAGcpZ&J+`#?UrttNTmDD!E<^Eqp-i>`-(tIGKC;j9-vpDit+O`=x2{}9C8rlx~ftpS4tt%8k=}%biAD3P@;Q-?6dj@EsR5wYZQ%( zdScAsN^}a})a1>{H??1GbH!rf7^4Ah7<|VkK54?^wnYIeJiVQ@es}Iuz0Z)S!?s4q z-Zx=g9J{}qyfsGI29-v2;tmr2lbBpmve~JGcbd)C;|vm~MK=Z$iZ2Sz3UL1#MJGrB|zX0a?-0a0?D*#~;rjKKwRacLabu~O`nyc6G)&YP@QzUJ4fg{rk7u9%UYbyWA<^I-E z;T>GEKJS{km}7Py1<5u-f=TsW#fyB)|Em^YWQy5)6g$oByO?=&9WKiQOoZ8I6g;pi zf2=)CAMjDy89S0R{?>C_iSLnZMoqE_k}-9;^$fW>5yqJ$Hi|BF})~LJ64KajRX%r;bH0}FE4eUS%2MbpW=^_XdQe)GTsvR;8oz|UtgWxK(}O9u8ZTr8fp4%fUN+UQjg&E8sYzlW;_ zC+Lpk;1ApiKJ0O9C7|nGz(Wcgo1+TkL%CA{B!on91cmay7sDVE4~V+P^hU6O%@g(* zZ9S@@1CHTXxAcZoU`~;6E!~U@-90^6gbm~GjM_x4*^=ik#}K!F5o?T@isK2AYm7}T zGITomK4!k^DT}-!v)ISkbIEqcaurn+tsi9$V4tc@GEBjK-Icr-Pcq-HN&h+%u|ocu ze{y>5bOl#;4v#mLo9u1oJP^ftQTho$Yh7{^uOuy)isO8Y`x;08^kbA6K*e_@UTtDW zH0ed-d-EnWkD%PqPd4+F4}ahc7yT6w{@#-Cm_T-SWAX^I@*P{$$fdB&n9Muf-cf6o z)8~pegw^S?Vo?<=&df{3yw_3o;*6$fV{9{#Z_MVdklT3b!OGy14WendSu5donr-{; z6Vxh5OK!#?3Ujct4V&q1AI}wQJ|QH58ip_^j!*8ea|_;Vbwg%ZY&|D6+R-kmRYJc- z^)V9YeY~ZT(`kq*h?mq~n*b`zQ9kg0k(<=2gN+l<%=c- zq*VSLYP7dR^FB=jR1JUjKNWJ46DlZdBpuh_WJYQSnmHegm4)$UyS?nIpXHH+rQFWH zmM!Q>{t0C~nh+)-ie$}4Ap4u%GdN$jObSRUfl!z~u?dzmzA(fee<{O%L+YVQ&(ORB zi6<(MR9SP>`#&gT{h3D=VhqP%_0Oqjsn5nZZ{)l|;XD|f6@UX&sFl#(#pkOHkPeBz z2(bu~UlK+*OE-{Hn~-q*V2WtUWyPPY`G^d8L-1Psu*t^G!7jif7v&V>Cplh|gu!*= z?|6dR4GSjKQ6|`%?Nw$`xO42!sCUxQW#utpv8=_0O4KG88sN3Heh5OcwY8ltR=|sg zSSJ(L^-Bt;8t=zTNiKGSRSKr!$UZLF`N=W?!e zZslH}&i5lBBWIXBY!maT7G&J`rz=h5YA`hLs0PNWAs{~9aVL}_Pb|)X4QJfI@zhzt zW}+>9Jzbpmc6PGpcWTXz`3JACN?n9RS|(DM89*otrte$8f$;rNy{`KwuLzrs^cn|j z>lA_)mIrTE=t$Q%RC$B=W%#d!hBLTu!L7AA>*Yi*@AjcK-_%@l5lQztNiL}(Da;kH zIx29vYYfu5-sUq3YC0! zM99ZSkR7OpGa{%FN;iP_p0&3H9^hirsd18>G@niTCzt4W7^bvpFN1h18rsBvYR@D% z?MR=|R$huZKR(CuSxB#l{O2p;CT~8X0I>Uj&g%N39Y=}fIVDY$Eez~qrF!Zg)5YTkQ$6-wC zEpChV^XR~3VTS6Fu3E3wreZ^Y+q^L=ZkC%?gvYhIH~BAkPB&n&S1JhgZs?z zi6!yCt+nf(xPEMPrz7kf;B%mU71phj1oyW|T{6KlE@GbwbeNa-kw}?59q<;*PY+ntvmGs2DuZ}8h?l#%nEZGYKg2e=CBV9@d{6rvtd7Vlxh@gs_F;^<1!Ej5gA>eX zd)%p$hp^oRr~cD(7^lLT{`4lD{Nila?Y5ypvy&-3pBp&N=woP12GFNW#Q8}L5f3W} ze~qX!a*yuz!VoI~Da{v@vWBot^yoE%v1ZL1($)7Ov|j!G)?~`iY;`4q1=u~(zeIhq z{pM9pCab;?8-Z5{X(?j2p-)N{=eh*_UH_q>@Q z9v`qwgu!27%|$RKH0Ti%sGI7w>ihu(;@s(IjVKkYp(1q#kxQKKnubq(fzwj>wlny zO)~?I%R)P3s&ZPrC2zxVO)=1dU#e_SZs&+sMI|lV$tTHlGnH8>{GAVNzd2-+QMM!+rR0Aal~p_x$mCixj7}L#A!G z9B;d?c+GZ-_8_5KdjSUt3F|c%#ji=Pd(AoE`DMEnwDE_W|I?oK{n`gR~{R zfLs(K&m7Uqx`5XlG;r#BI;EWHa^-Dv3gEunQtqTI&uHxL!oI&V(SIwdaq)U$T=9WC z6i_Vc$;~3}tbMRJle+pC5LrfnKgvyqDFRC>NRfYc9|9!%X}&brb4KIb%{yZOM?#W$ z+2_H*FCKiS7RXw1bO2><4}zMg?(x`MNvRbBE$ZfI=HVM$c3_eQpu(lz!x!jwY$j_m zMtySoH2rYUFixmIZ5x)kG>h7GLuu-GO?&oP+}G~es98#mx1hk%1HKPsE__!cQKHvkeEBZD`lTD*IdyJ_g2x?$3M zY}(ZO{E+d9j85AQq-;~J{kXZ^a86xAu_Vfn$AH^nZ^JXtd+|k#0fQTPwT*Um&B6dp zKHfI52t+fogXvNliip0QIEpi`2$n3hQ!#tW*X9`R{Mi` zjdvC<2`!R{B@+sW_iLIlEshn1*Na!Gp@rh0fG$a&5HZq#^F_XiMX!qaXAuem&Kn#K z9(rsAbE+IyJNd`c4=@v1F0yAfWs5m=S}F=fPw4hq6anY6OgUwiiyjnCY(u{WEbyi~ z7jH|B4~Ia&36&^u6{}e0M0AHGmSrclrwy%qvlU3jdQBlnlRsOMVU9?3LP(!RFpO!6 zMJBnkXR38cbg#Is*7RNf!vY5&nP5mxsv`h$(#cHWDopCVe~&$14TX#F^cveugITlavn9g!D^wzi3rteR)B;3f+^p} z=pg9gdUJcm_QA8$VO=yL<^$QaWWLbA(M z`}y!9u?7>E`~yrYr83jRh=L0$HDsd&^Gf z=LVO^sQcrL6qs8*s=BQZigq)+Yn)aIL0Rb?1pFPk0}pU=#@iNhPy11l3gkZ>UJN z3ReXvn55!=r6SS~{nBM(A3wq?##snaXG?t$4%0SnL-DEl5!4o?J)&hqnxxY{mQc%S z*1XJlvDST9-iS=X-+v3Gc*C=^Blp}guJc*lL+nR(Eyy1~`nmT12OIn>doCqe+ZrY1bOij5ib)8A< z@O`(1{akC0Ag9ZAU=uYNSoR9KTub}SBo9pLUunn`k9Obpgpmn>EM5r^J)~YMT@l1A zF?ofPrg*@m4YJ@1BW@*-R&#oAD}BTTiTQ4Bb+{lu%Nc2GB#zZGgYqt5^rK9KE zCZYs~Ep&Sn57 zjD9Ak=wX!3pO`~*ZN(oPbWD0rZZ6j@1bWz1;xEgO{e$UiQ?O}Bh5!R^xjl_Q7R}u zZ9t9cZ(5nCR9tMPu9n;ljg@Eo&YN=UEHd|6;&D})*ydU}+(s0Hh^anV%#)_G*0(GT zWRkZ82_O#Pu=mV-kli>~5B1%K$Sl1_(;39G3o7PSuQOxm%uy1g|BG8(4MhIQExK}g z{MXa4RlJX+Th#K<(_o%LZwcD7T16?i@0ldx@C08bhJME0CdntW8ng1(n2#Oyq|~;# zzt-gX*Ue>+tfD(ujA<}!b3~kAW@Jzl+&z3BE#ghgI_6Bdo5|~^nXz{)=9udq52i34 zwIBeMCOD-3Qv-ZhG_{C^9UIJH33te9JSdgnceSKIH#&+byEuv?SY8vsXDeE^Z%R}` z6EZ!y=9kh7KWA*Bq*+XkhtI~YV^%C{KD=K=x_e9Bd~<94q!a%~W%l2x)Sq>&V}b|4 zq`2y91gop7g}N(PtE)w|fTuQfH(p!Ebx5!{wKM7Z8`kU8=hKdmGJDE&pXIbU0rNTa zTN54_+m>BHCa=}!mi}marIuqDT$3OZZ()LqMR)_3SCQMc=IGdAZf-d7Aj(y`O;j(o zBh78to~q$^<-XREQfhUaYvv58Q8&LWKf!LdIeTt=dM)JbFJ+Ex{TB)Ot-~g7-7H1W z@u7Z@UL(3mXt6t3`naYuw>Xwu%<_=W;p)hf$+hoU+XtEYm*eG7@0w*YA@IUlymz_mo;D$g2tGzG_}{bS-h3ysGDe4)9o@B3<^SeE|o2HZ6}; z(O1r)&};(X8-e2Zokwq^@u#z(hU|*rv3t<&#pRZ?8`4D;iQ@}@*W&qe#(?F2gR=i% zTAlGe8R0QKdCREZbirUS{g-0~zjy2ovVfRcVYY-{VmR4fU%>e7P)(W8W6>JRme1kY z&At?$OpW;aoBTcgXDylIBM9DH!~9LPul=|w5_gg)RnKH$*Pe%pvi7kvPJ)V`8go-zZ;;YP_ruCGSK!fc=U8}}F3@B78*fT`osEchGh3hF7|BO< zcpCf%tI@v#c|n$>bsxW)@1R>SJ;0Pw zN!F8o?`A%z)rrY^pWnu^`;akrXgo;&i|iN~{OxsMd@aT&a0zac5)mPjFLh-p!%@#w zx95FF@ovYpuQdd&FM_mvecRU!SBvS;r0tljK^rr%mb5lsxI_c0_SH%;zj%=$ZbVmD zyVDg=x~KJBb!(K+XZX}JV^u2tUfao%rcc5K7^;l0aWDjYc($+r^)?;UTt$pSNAmC1wM@Lr_xL4oxeCoHUYfDtlUW5~-mQWRRUDH=h{Iujf zwvuX!_sfuEeZX(sbqG(**1$y6!XHkQ`UOj{ww(SEdlhr=l1eYk8j>hrDTz7e+ln*^ z396E2W4H;%b(rL!6(_sU>&|gr2MPJ7qhn|(iN8&$A>;(J{KoXxLA4h6icKQDBT?Pj zj~9s8xZEOMEB8lg?NVx#xMdfU_uWXv?#GW_JhOWHXkZwvcM5Z^O@ zbe{UqbI|${X5=NPyn-Fh+Yq|parMl;GPKeakh=D1bFHQjNCpU71DIBR%0@LcWykz= zjJzKm9)COtkT!T&6eZ*7(=`r*B?8erVlSh*Sy}E-Hy;fiUWgL_S;**{DN7Z;^=!ah ziPf(Whx|NR6@^T`xKVLC#F?0NPMXifVqUU0{XSPs*WJ1@C02jWn4?I6voU4ZH18+~ zN>>xaq4FVOXyUp;kHVr0p(U0TUk5yNdx>8^a7hX-Rq$Sx5h+YnbKB^(ge9iz#?9HW zC?Z7zR;si$)a(HSy)Ji%Xd~V|nU0GaM3!5EcKx=$>Cl7H&0*e ziJ=fL*ZlT<2*g=5vGDO8Jk`>)Df}zK*g|exD#*Sw?pYJx^=4Q%6K)+WttwHb#UK(E z%KMmVD(;4tEjg5{G89%Zbm5WoVkmI3#pv(ia+N-V``$sYcm!5bS(!VZ7t~`)u12bf zB=m06Uc~tF)`h>5Nw+r!i$o*rE>Jg;gwHur3U}~AiNp*+B zmOX!@g8>*NJTSCv))(sFSQj>!=*I^yHyTCf$$(|yp?$Y;9hlZpfJ5_1tNZ?7A zr3~)Refzl$$lbR2OEOT{t2<+Xq*h4Q6oy+B7|BV_wGl=8YJc*n-zZW#{%IE#B)_5# zCJ5|MZ*YRubmi&nXr+*_ZVK#^+$F7uAs{5=o46k0cP*9UKY`&b$dRnpv~wLu}ZZ!Uq$LEVI|sWDJk9CZVA&_zaeiG_6?GzzQWo9h20Jyrb5M3LtI5@ zst5bqO3_jDz@^StOsC0pExZ;F$cD~pA`a_vVVD>kxUaoozM6+*@mT!~Rbvge#)CAm zTYwRQGrqXyM2|N`WUa*^rjt4P>c05kF8c7l(T${8#mG<($sZ+mgxabQ#fOK?O^%|j zjoeulwTouF4jhaW;PPo5Eu;u`XLraEXIDXh)?;{U`rdj(N|`{% zW=O*{%_i1=#~bcz;>!z-aHg%n1_r^!)Y=WSJTipPCv2$|Pj&DW#a~9ZC`l`ft+~~x zqb+1%42^{FwBG|59@a?Nm@BeTFwNPqEO%%7?(AjdN3uBumX*y*NKnfgLsG9 zrCg=yla;0aUmU-$+3YLrQ?)x@#yak+H(0B#k+U15v05q<>9dg?_nvh?v~%f{w3OTG z44hJ*sb{rg!X<|e%9`J^ZXhHI+(IB&9}XC+V5QAfN_^iegmxp4)P4hzlLOSh!7;9| z{y8^)$9I9$TU|NeE_$##O zTU%rID>I3Wi%nv?h2aBLqT$%;bVez_A3f3?^5*z+ruEUx*{8NjXAf5qEIA?EVY?({y>0E$TjMAk6&~jz!|Het z-_tr#APdN<78J#n+x*!|cs7qq{cf-OrRQf4!bT}jJ})VZEHg2k-el^#Qf1NcS%dWt zX72|$b9;jrZ89IRtaIAB3VYPDYRZDohWc_`_D9uS&mkDo?l8#t^l6KbcseYErh+~7+b?Kp$Hw-3csZA&hw!O<^%KTI7@NAmmjEjulMV|HxkoP!>2 z9Rk)7{YU%?)gqW=wzO<|R5Lnh{3IwhnjEaXmI5pdufZRr1th6_8fM^g#f_xXr#sbv z^f2>=DJ@3qy_QsCuGb(1<1FL_y?YLi6hE?zrn>b=@T0; zzhOg<(b8fUkvYI8{iWvuR4_%dI)nOJ!KS;t)DW@AJtESOLSA@1fQzsKomQMJAATms z3r@2LNdZ?sn{nboSG}~Us~SCoWl2uqsx_3mGIubBnlnKf?Vm8lP$t&lPZ&d*)q++g z$&a~PZwUA%D1mY&@qvyY&XN_nOAAXlKcj`xCo|~(7q3T*dXqx0?6}Ja%l~V)htuL5 zw$&lDft}&QG-bsv;DQ|Z6r68uv2QDeW9{b$$tRENs}i_lwr`J+SZ?geY`8@b5`7pS zfXEtWu?+vpSvo7bg5}d*5O_CvH^V28T_n{t0Ow{#a|KYwh1<>KM`!%benf?-zJB_D>T<{tVxiwOaNJrO2az% z?a-lHFv7}$F_gF}i(y})n>#wNeaqN1*~`LG6K%e)sbsS3%t(FwC=s)%xh1WN*%SW# zEzO5r@^>-5Qx_7SV?1F^5bapn;RtDEjc;9d-aEm z2n78jguJ?F~Mb)(4zwn|fx}BoS078E;?J ze0&f0&bc|9wl)T4mv+Lz?>ML$#;BpU-mYqw78)qEt7VY~$2wChPTLryf+MiA|rSN{n3^^1ucY>g1M8*pA?r zgh&&~si|>Us1gj66Y~oZ6eQ39QOr}RRMmRhY+~D@svBz=_MiH$( zSA~7WpHi*?!A!&kGr_e}t4ey)M>S9=$~02Szu8{A*ZX-b<0Hv#qTXVJ?Ty6ij{Is(1c1t2!1JKQFh2;AMUkxO_+Q_8~p6K>i#W_{hy_R&m z%3?>!?ODDYd`(b4T;@C<)3YR&JIc7#JJG-yi{?ycI)SHK1w<3$4>}FX0P$F+uCI^h z6tfmOyA|sZJml5*9UB0J;*VIEiFrhG_b*53Zk{+jcYT6u%l{8sUmexfyKPHL3&jf* z_fn*|6_-*dw1q-(C{A#9mjcDLrC4z(?(Qj;Ai*^_q(}+Dg9XUT@0@q48zGUqqUEW4LkcXy=hs_X%f!|`AnF~7B1J(EOJZyPybDXC7> zf$+r4W3Z>18L|)R#Z;l`{^@w?+u7B41(~+qLPj=NZ>qtHl52!3G25Z&q3Pkn&n>E( zE&Sk-U5?GuTf$rOwN>$7Z;uxOSbvm4iISNc9>yt3#7XA;HR6K#MGL?$v8nh3?^1dl zP~8W+HV|>EQj#0#pLQV^H*b|%1J>$S!0$a8J_S{eB=S-$+8udMNDUuY5t=}vUkrLY6Ng`T3I{>Hzuqt@QaK<$LB`l*R$QT-TG0fqROh&Z~2Wa zJ<)^9N~^lfpj-)90wCm~LBoPt3AuYo!;u%5r?F00)aQ!^t$|(wucymI$&`9MsHnSL z0@uxyua=o=Uj=(YC_r)~m|rxY5(&MElgWy)$xJvzHIk7{jZ4ua}3vnJv(X{X74J<)$!bOm5E{}R9l2EiJ#3@B1 zO@Oe!Oek%|t8mKZwn!<#z!(W!wSb_n++bnBHq@7VOHMBc`vthx#GDU;B2TVpg}uCj zpoo!$c%j3Ea2Hbt!mj;~MSqUbOcGJ-;F?tjNOx71;O3m>*$vmaF#F}rH#g+bF7;gA zx=r@%5hXz5F$&BDOR)=22yP9r)TW6v9{>vH%9ggeA+y$L&VuJhsZo9N9ir5~K+6kA zQ6*JF%V#?Cw2|i2Q9Gtq=i(tHCqaDzWLdd_<5KtjFk@%x7+4J|wU!p;U|>`I$~qgm znsE-2PdR%kCMt_mC_3VeBb*;#1@s)!O6*Jr0v0wq?0vTB(isC1PfCyU(P?y*HpbS3 z)c)auA>5TSxy%R9f{V!o`5)YIplw?!2huz>FbGiH@|D?0oIyqPL2|(%#DEk@>2k(Z_6Ez3|kqc50E*r zj8w* zN#X7_!1VwCk0yEuV8FCX+>!9kKp{ncH!CQl<9w%|@I6`>u@iD-Vea4l?m$ zAk_&<3_$I1^2rkGwLM8Z!vZ-IP@EzJ<&MSIE>O$o8LyF`VD-v&;m(&nl?J<_r(bR- zh%ik~Y`%nHNt?=IlrPTBr}yn1@~?;QX_0Z6=t%uZDu;j#*fyRn6~-f7PwM1NxmA5c zhNU?LIIyBV#r$E^TPY3WZt}SMb#y2y z>~9m?_%nXVGCwDDq0g1@bK3*_HKh4;_o6G|1L0Mfkk$MiI}}_^6<>kQD3;u8pesBU zj9`8e_V0K?X&0bYB{SY_`KaXXREGXCORi8%#VB(LJALJfwaaV$<(}*-hSGa)L6dfW zG80JcfJ-onoUq-Gf6D+d8FZZF3P1PYtyHHAWHo0<1RP|!2&a?6|e2{ z=uU3$W?W~si;~w1u$LI*9@=DQMAFVwvkgmA%$T%2XkGVXQMxNuNNVZmFfv^4irOrDx#I8n%?|$Q6 zc+V)YStj=Jk`RLaIH-d|q`c*q)v(>B>!ho`FG)nUl-}XjLMnQ$RN0Z7{8G(|7ie+ZoXnA%uwMI-|ncag49`&fH$^L*{#4lK?l; zSbSI;qRF`p;Ywk!D;L#_zIwUD34e$819gl0Bx0pL%G8}At&UU87q1ldHLoQAy5KUz zFz3JW+u@(|H4P@{U&P=4OeA!kI7c?jNvb%MldnKn?_VShO!1aU{?GU{#PH8YWl!3R z;y5om%@qwpgqjut?~(<#R^({u5L>u@Uv5@^T2r|zD{HRg!_{>SZogL=Ch51}R{~n@ zAj5HVw~vDuR}bmV>u+a|v~xx5-dKX=3~{JuuLw2e)b($)T6hv^fZJhz0sG_+8|Uye z=!NCe{rd8icQf8wXMzY5Xj-jkg+;7a((E9U8E%Fpf(ihT)4#vi=1j^ggYV+)>!J8CqDR1#7rAP8lF=5V1iCqXt zWR8A4<#bfBDoe6pbpEJ^v_GYo?mB$(@5E-VC zK={k~#<=983DGZ;i@4Ja7R1gYQU&zJ;;#&S&p(Ibn5l8vVAV@I0@g}~XlEdHu`yM# zG0Fc98NXuB%rDSUJ+r}BiZ)ncXT8N+W52;uzx#x1tmJtTu?h6eyKZF2=yA3MAUHW_ z-5sKJ)u2JAy8(}|kH6NS6O%5MX-|#{Chr}IGb~N-q1FVu6dKMGujMl-W~I#8G?*O9 z!_C*OAJ2d>&A!xnU&<6yF-9!|=F%^uXSt&z@PgyX|9$>gLZ#2~3K<)GNEK%yFfSi^ zDSZ-#$!?PDk46e8^cd9O(m-^7)kzK~=NSzptN(M#{~d~2EVDR44Da2FjK(MOY;HOo zpBv=h$y|vJ&G*wGby_rZJsJ`ze&im`P|gSN;RaPPkEj8Z-a`3Ae&}1{1g<5^h1|B> zNS>bU&V`7WqZsKsMMUmi8n*nj=`*2R&No!|;8OO2yl}`Z5K5ron#q`|E|9=1w@=W2 z)>-N*=4JBzj&6xyZ3z!S#ERX+#R%uA%r0%6A+k)-GF4I9?PMwE8+nnPQT73fq`BGd zv1(9#%5D#|Z5QRZ^Jft0b{-xLRTuf%clhrE`bvo3uJDvdz{8U5Nugc-QZB<-Rs4f| zp|yYvvq%Nw7nMwd-b!p3Eb>Kq=U#u6(8URCE%3WK6X)P(g#Ky!@AL9iaws&F`H8_B z26tr&o)-ithgj9jS4%Tw3Hh#cJ}d778WPT&LGLqejB(bqu6ujfI5T8%v{V|57m85f zF|omyLSn}!$JZpfy1=Y&d2+S#XupJ++VHXjpGdBWK+1}dmzJsag-b_Rb_B^AFN|FpE?|@W28iwY&4@j z_GCF0t{iEwkKCy(Az%Oh;;9wlbrTYUMT#0ygZ{7ksi7Kz6>mc=qj;wgf{c{jXFwp^>^|PFrt)T;SY@$e@8g0QMV6Yj~_E=E@vSrmecR(gm)^3-i+^C zG7*IhZ83OKy3fmP#YQrZ7x`BI+}vJz?+u;Em@=?tY8v#+)X6IK=rEWpaYuqqmQ5wcn|&e76P-G!D}a*SVGONBSAd)#vQynK8iUdF zdfor`o)jIh_);bDFNP8AUo3OZEgSMkZ|z#*My};iR%>7a6n3#y&h64q*U9VryPk5- zf8VO@ENNonCbYcboNI8zm+}?hCtZ>2j4Pmuq-l=yb3yoAomikQr zy=qbfM=X)oPaf9iDIS>%7xkoD$=sf3=g^s?RLQRkRiW>o;wR&500kK56ko;cZ1zXl`i11 ziOT3F6D|@Kzo0kUM$$rmqr}Vg^gIujaBWom$yB_vKD*IsbfOfby`cj13v47D@oo4M zd{SQ|)5mFf&@<`+H^nAVX#Rr z?4Il$q-Y>#x1jK>d6edy+_2u-iN>Fp_DkA9>v<3L3V)#z z-Hv)SnuR_zloWF z`o+Bbcna!V56O{9UJPVO3re zoF#T?oA3t2@+0j5ug7P1sp3K_HFo0EG_begX8BpFPx?6Uoe zNzo#Oxuvur5UQ?el<($l2lUd+9MLWjN-bBl;?k11-sU|*(^6%7lJR9;^LqFA^F|WW zewFWc2CdIiK6qy~qart${~&0xQN?AYp{zr;z`d=4V1$p{tGqnKw}cxmp4Xz^>aSR@fZ-no|}9^|{a z@PSP30NE1x!kTT(I1v$V-_Zq9Fn0OzB#x`*Yh8Y83!Z+beRrhwY=B{Z<(U5#-tSEv z0uwJjl={+>!VU`?iMRp>JjT-e<};ls&PBI3*}@>X?ImyhfmD=A`yp2B1^q({yCDc< zAXg^fTV`hHtp3@DSQX4sXO5VROj8RDEYO8euMS>q&aBg%+%SzMwAM(1_JZIRMI+AZ z1D7DkStoU=x~bFbI|j&4Z^V+{(h(F+MKfUn96Ck&Sx@9HZ=gwx+6HC>bzC?4*of{G z2fU+~a$58f@_K}37@JI_R_K?@*E?6w67BA+mrp{h{RcwGy_V+8OXPK!P}Ry^vR1D9 zKAC_e29@nAj}G1I5c1l9O1LRiFv^&t(PkpGL-e3-X~CsiO|g5u2>(BGpaLu6`%bi3 z3>`d|-ifdc#_G|jbSnk>>v2Q9&~+MgrykQsl~6AeVt)&`^afn8`GF=;vSJ_71h?9v`hlB;jpcVbPYbn6a zwQ+)52-JKQ@!8=Z8|49beZ;7=OWdxMZr)0Fgs4HKSCF^}-_S3EsogD10l&-Tglf<; zV9?>$)hURbCQRmyqQO7J|KG?_Dv@>jpqMf4KFCABW4o0T?1q`#apI-l-a;8vgCJ`E z(AV2ruOdilmyu$_$T{SgIf!|yKo=HuY3u#@`9Fo~Z;Nmg5fRzoHZP$Rq5|L`6>)h? zdk?_yq@MmmUj{>yOD#d`gC+VuNQ;u39PGySND?5c6jjWUP6S!(O|v9k??4xShAjJ} z{*A`bW!anmq!1YLz$@ixcZ`0C=qNH=z9^F};Z2n2!FBIoj4S#ukI~8`M0-w&8-g!r zYZ#`9?Xc8<7aV*3y}%QlG3xA`&A_VJT(Qk?W3iVrYt0TOLG8C$rLLEw3~sx(^+R6o zylj7@7fG`b7*KGZfU@-_Pi9Z{@`!$CNLY|3F(cg2m{m`B|)Ndh7h; zcj7#O(yI*IK3OUe9ZSNC;djX@|4#9?>}(X}Sei4_$!Td}`X6XD$=zPqlUQ6HDsX1| z@T$>?681+D^^@?0JXkN)hJ8u^REKJw-C;D$j>puu=W$n7wVq%EfcJC$TPHTIW#h!# zW>eU3qvj`#2Tit94-X7qf6z7bJXj$wjR(^7FRVu{o34d^#wrIV{$3QuggUXzzOgU6o#!dk7Z5K$_d30Ie~@8 z*BgoMe76Ub$M)1uGqMAkDb(&5wWlEhG~JxmKl1~K6~WPjQEduQhlLMC~&|#7IopAURC)@(i_sdvAo{5YZ@HG54qkp({o@F{VW4PiHcs&Q1xr z;O(CWd115qkLRnQ@rp$u*wez(W-rKU&iEs}A@4AZn$+qJQw3_w9$GYOQTm%+JX*WA zCy#A$>HRs#Z$474%zpZ#3x0f&_$tHgX7iQh-_ng{DgBTraELx6X zijx$5W}7QwuoGrzhM=*Y#n)?C>m1#YFE;D4^>i^_BJxqH=d4SPqhH*J*6pfw@A0U}L4 z-vAZrVBYCqCi`z2g)gmKTf9)jBuKN_k{Z3O*VT7c02mK=A22eSPy68~oerhZIsh zz3b?E*$X;$WET5iPIz9n^fRBX-RCcz&CQL!e%+_lrcRA2VjHL*68sqPU%dd$bx-^Z z=-ki~!Qo?6Xkv8}-)CexI*VO?1orLzAE;JhH%spyP6Rh2-sPZ@`rq16z>o$L0A@6Jzn`js?ShW!d2unrg#m-EJ|(vFPcNm+)cLxouuZ{y+ zBRM&qYXuxe+84Jlfym-CPs~SlDZsJD*ZiNEwfvF+-^Wa?SJ&9%k>86`j^en z^@!uL$bCsbTI>(d_qyxyc*a9-ql7gLetRda0Yd<+DNpW8sWU@p z3t7!c%-FC+96(Fq*QOC3YD<`z3@AKEdX%+GazgRs`Tm?BNs)z05hw>yu~x?gShe;IBzAbDt< zBy|~FKaCH+-#vXqYO(T%HAXtH4WGNJC-y6wY*!9(Cch+Ph{K;Q;H^#@iAKO;-|(XO z+>tzZTGu=uc}g)!%+K_)tMGHcr;O$))y}M*l*~~}jD*j1=d2{uT-kG<@+)VRZsk@& z9-#EU#2lG=Vw=tT$LRh@9JIt|P_8P;vW(PkG; z?x4UgY=f(OE)d)==cE}u4d!3JcCXL>g^HbPIJ!KQD4<5+X9zN3S=gc))9V4dokZ~% z5oy{^Y6;sONwEkiJ!mx8Bi9y~@uRyR&5T;8<@UfUo=kCyQ)}}*e-vxiczM*RuQ@EBv z>eip#$i)6HZBx-8V4=pZgUy$HWT{Bn`hWbpT`&2cewQW_0j|GzoQNk}vk3?F2+uNs zJ<*7#EV_{jKqm+Mp#I6JG)tx#mnYA4KJ76aJ?h?4x@fcZh>flLWR29HV{=x9#s0Sh z&-`6E<#N)ekMDie6JZM`Ori9&zb9S%u8TO6?Ri(L+fy9s+JeBojxILG%@^8H&+*@M z#=5a-DK~)QN8p1WIu`ao*VDCFlkKD=4}|kl>R+@}L8z(G z#&&LE`oGiB2Kl5?0;faLKkDI4bVKlTO%$g+Nwd71m{@CXUbLgPnYF8Hmb`eCLFu5t zn}Y~WD9tZFUxi?d2!f2v&EAwM-Y3*jvTNO4a-^H8)SbI}kPU9ka{mOt5f@SmmsBZbB*X4 z=XK1@!vyy5DDdRqibS`zrT%(#660OXL z6}&h`rDtHmG2tmrWdk{N>hsAA^;TT9=U)mQe--RX-clS|koZsMNEjFWed)ea$WAzUYj3;yEC z^PfZh>u`LA_fHkyMGt=2%V7QC<_fo7IRmi=YCCT1F|Hm@T6MembH~KD$GCTOx;|z^ zRXjoo8^UfqaJHrjs*^DT@K7ha3-d5!7@4E=EY9WXHMUX8=)S7iYQw8GmlL%>L!2g= z8_pGx8o8Pwm2k^k6O8)u-16&^f}Fu|ByMNz^M4sYGeotSgBO>lZ#kaGINvAqI#3a5 z@YENNJWAoJ-@mkETRT^n1b|$k^O^g6uLMPI?w*d^Rz8+t^f5CpCLy?}~yj zup^vV5dP5(-d5%g_7|HZ=#{UrS|MMyFOvqGcw=2rVL6=Mw>9SZwotBHdo2fP{{_FR zKO>1(_p500dG8hg*J+{@<)yJVy_%X++wS}v_eter)RfN(jXrYHwrg_tX$i20#=&7u zBJUaXN}Tt=4Mu3qFE zzWl%sMPlyoi10?^Kk5U!j>li|#0oew^t#er#pE~MCM`_T;ez=F6^q|T2%mn?B3js( z6PAp<6SSJQ-F_ce~#bE7+2oIdZ|=n{qDHFtX31yV5MVuVdkMXyBZ zc7A|`m}n~X?TvL1e<*q>&6`k;0g%L?Ag)hG&K z0)Dg)D18z2``Z9Op56Yb>2!7r6_F(70a$eP{$`5mDaoR_>bt)4w=BbW>zDEjD(vS< zPXX*@4O#7dYCxS#WV)lK7Dv~4wXp=vKOaLgzGbTWelMpHw|HH*Y^}5$t7J|Fx&OXO zDQi%(d_terP~%rpp6>UvUm75$*JvYJYO}R}ML|8w{U%W&P6v`jKp*ukZQeVKX9aZH`Zd0Z$h@>Ci?! zba^h^^42_|r?jO(L;mqX5~sV%%g2N@7MSLQ68v6S89dKl*!s^}7Mw;tr?Qwx)} z|K)xeHxw_~iahiTY^Mg$Q1s^0*fc(BAvSROhihV#u3Ql|2jXqJao8BY#^r(NSzqF3 zx?8jD2tIOe_78UhOM-PF<+B%#jG7d|)7-3O!Jx8q5M^_l8ZZb)Aw^tzRn zT)xWIcK^;nMOZbq^Kz8m4W!3#vi65jTofn2;mLwb3k|k2eT*SO`kZ{wckj{^HrY1i z+vS6gh0VQY8jCmBU4I)pjx_gAOV1w4oyhgznE1KHWwwNtLd-LD6C(W~59BaPK_ z-IE7F{dQ8VOkq`tW9T*Qo6NcrrzlF>Mj)Xf+3$M0*MX)q_?m`WTP>oXK&*Fmp}FmN zUEQVl&E1XP!o=|}vu5O0Ortw+75uVYv+0?D&0|)14jE4 zt891s%H>~z=0Xnx4CY~v8)eUzNt~PD0!GUWGisd~10uF77atoys!#W34+o|4z#mXQ z42t0WtjELd)go>0%PPY#W#B^8TFi5iwL8GJk=btMzfGVsr%S+B3Wd{05wXEOGiq*p zr!&gIP0KU}Id2}f%S1xybMoXSJe^x4j{-B;E9EL-hMOXwD%mf}h|kTReuS^fo0Tk#SAkvyTwO+>uIS4(k7voa?r%PZb?`ZgmroLa6OVP1o-GO zC`IHve$t+-STp|Wp8x~DRBsAU)XCfh<%EquF%q& z^au0tEYc`ffBQW@Cw21i1Hrj1c`zXO2bj=qLHWnOeX4*Ig7$u(booVoGXcYfb$MN$ z)vn2sgY7ETS3>#M;~^Crd48Tz9N*q5*=R3q;TY5g zu6k8`l}mEor3^+{CgK{@+P18YysCDDH%=dv$XUv+EJo11S|0yUZ!ObD1N!*-I-1(hJ<8yEw;F13ZgN-W(zVp zS9Mr=p`yh_&B}Xi^#$mUOu${Pa&1g4V&Bs~j_EG=BK2dKzds zWWd}^(9#<{RP6gZ?J=|lk74zSRuIq0{b;Vo?aE9zUmWOlC8B7O5-Nnw2Irn=&rRgg z4Z`*uYoYCw31H{lLdyhPL7J-73yk|cOLvBQ!S8eq78my}w|e8=Y4cgwT{lEPI!FN67yaId0 zfRn%ByMVDER=0rka4!sKL`ZR+{BB|@z>x9V^^f5i0zrhLXnU;0RgFgjLIRGnPo>dk z53Vi>&W`68`UUF8?)?EhTAh@&%c~nn-?uO}#iPQVyCsmT=2RfwI1$&Z*FCqlLOIT|IFq0KMG@7Y8GdVCL?i+PxYur@>kR?{) z2=K(w>n7c=;t7|`eKDElULTib4EMTpyQR;LQHplCf~dvsga~=x6aT+HCq^hg_A^*H zf90xEmAmkfS7o~MTDYkyK2M~!VE=IcdKDixM3+K80_NEn2KxAZ$KIGx!6U0qo zROO=eOq=_%>Byc#6~n;?ivjx_1l$O<=t^SW?{hVE#+A;|g%>4TY>Xv6=?JaPfQ)#j z5%uWTI=d38cZX@10?siawH__A;;~({DCEYM)*VE)l_!^&r`|yZ{M+y>M0_-OxPopV z-3Z7p;;fc$`$1x-eet*TkhsfwaGKAnHToV1fm7e>I#O9{T4K6z8c4Rcq|)dBvQKjz=KdOg%fS{c*ypfSssEWiG{=W^G~eE(NQz_P0+Z1VF7 z>0s2XB~5RYH1azAKtO$?p-c^AJ@0am-JZi~6|WIY{--Ma%@n?8r^$+gCWo zqtTkx&cTCtCn|(#r-r8GE%Wko?GYxvCM4kKU=d_3V z?BvwtZDT>jwF)x(U@(8z(yX~MJa5MD$oKyCDyU>fL2aaG03}hg9F&ub%;w(uO9TEyAD1|GE5Du@zU3r-MxQI!$WB~g1yD*4Zcys!ZKbyB&S-NN3 zhCP2g!^wJJH-?`Z#97SZWb158h_cqFIkxg_2wH98?Wv;PCaJDLhm_8#Tcb;6zEpis zX;^*%|Ma3rWd($YdR<$#Ck({#<_EiZ}wPO_v8~#p?zjVA{93c zg6O`aW$J@CvrUr>qC8&6BhV^az;*Z1Zt13lxi_b4d;^v>0PdyDPemN*AHS~^`a8*>{Lw zQOAKdM1Kq~c=W(L4`@@58(1pH>cM|(h?6MId3shn)1wwCEmtq|SA}Z*fd}Vthc53B(9u3m!Y! zU2Wx?ftY(`h^D8g$HgP^sBRUc*6M4N_H5~3LM^2X%;&T|P}p=MCzXRqpMrFTT~n2) zrpTD*R%ET9bP86?U8#IDR3rAGlxS>le4GLa3TzC5iUu;o4PV~pu4j06h|?HQ zG{;0DRr4ey0qbIT#=x+8U$9Yc@h>i97r#<8+P7OQMsh6pGAw=-MA*}PaKn$P61G+| zS;=Rr+84`O=Abl4GU$}h5@|8qUMAb^z;rN)W)N^t{+e5Fg*fVxT=3et$~8~3?l*UY z)B|daW-7iBLmj?0kNpiU#)ksx&whijS)+FaOYd71cG}fmZfdWozX9ly!X zkAlx)3Ds0abod#z6Q12-|Fqo`W8L#8_J3Iky_ej5(>N(&BJG)J z(b(SZ(?x8m`GY#9PG@k=^0hjsXcf^|V#x1T8f2LS*DhV%mk=&WOA+fyEz#$h-xI^e zBJ4lEjRtSR&;4Ceje~~h*56i1pCUHkhChR_I(HlukjaNbbje{2=-?#dW@W%MqC0u6 zEl!;92cJQxUV77SiB^Urq-ju`lM935_!Vrj06+*@TjlhvCX|466ez&)5BxpoDsUO2 z0Jv6I%{q&hOV+a&k`IdbZIiMU*)Gy;3eW0k>ST(OyibpVT6|ZXjf4XX?$D#s=+B#M z((wyUkUD>*`ihBB;e;9c$5MTaKi_Q&|G=NHkz$pdTwL4xdeGf>c)hysH-5-48pmGR z5(oAP-#eLD#>#2gT>iU|I{=t7nY%E|WnK%y#&1uFgyEjcFZHEfwcOyx4?X(A71-&H zErc?P$bCSsqXRxOwO;vcau6Q)z?Bxuq#1ksq(!HdJKmfM(i0d<9u1Xnoxya6rQOg7 zci^RXw<_uKFNG6#vIb-eAUh4aY)M8k*8O`qe-D12)zHK0Ls)4r4?8RY-=jO_xu=AyL1r^co4>^3SaUNhfYy3AU^3XptHmNe`uIf{n%sx_i7dsj&;!SoN3$yymkv z)PvOm`9UadpCYdkuc53#hgJX@oyz=64>zzih+k8xRk^bURd>|M)pV2*(Th8B612`p z?X#mX6i>s+`?7as;)8~8oy@d%`o?QNy6h0>)LsTL*58^iy~Uu7WIM5mJ=q*pxi^M1 zuMj)$G6Oz+nm8pCn_x4^wd=x+sKPhj!Ks}v9u^lfk@J8bq->tnF#?W z5*bc56w|}_jj;KN+B)Y(D7BbWPbPpM;HZ(#g*+~MSP(m$=2n#El(4mreV_?GuP# zJ)vHF?>d`l!8r*wPcR3^e+<1_8Q@8kVP}Pcg6hYtnb6^%q5TU-CC-_$DKWL&^Zi{- zp1$aqg^C=O{saHyle)NR=`0@Yi&S5eDwC>kaT47~%=`imAVT{Z^6cE6yT0aiUO7PU zcOO0JK=wqd)j#SePLTBgZdi;9lc{ceEHdl(6g1!Fsf{D*q?#WfX9jf$m^62E$zG|c z2L^VREGaCe0*RE>Zy($s)+2vW7}(ZVV;PdrN36-&M=<8qfOp%&-89z8s@9-5;Y%*y zQS`e(Kaxu&6u++7cte_ayOp4BRn4QN*8coFWbb=$sS13@ZG>*4DTkutboc7|UCC)j z9G3~|b!vENypKeZ_`1~Fs*U=F1i`S8U(bb^ZVd1?C^JtSkSwcqY+*VwCQZHu5v31X z0n=~^ydedq=xviP;N64YO#wBa_re#?=j{ae{B4ODFKi(kVPL*zq0tq%?U)L$Bu1=H z>6wUFLgx8@^#YJ7=O=O8A1{TN8+wt84n%Rvo>bX>Y3L|d4l-)={+vJo{dH{O>i@|? ziJ=q`M!jqCra7i8pnjuUv^zHd>fL#rzj^+K87_#pEXqtF{Xk(2t`}N4TWGe|4zv`J zn$R8H$dOgs`#i#LQt9kj2an~5uT<*CS(n>VslZoQR3yL-c{<^-b!Ed{NbPLeSN&vK zzz*5NE|pYy&z#Joeg5)DN2>V+U4#KnhpwndVO->Gm<~#sp%N8?_!yD|b_kuNcHLl} zrzkF5-Oj=Evzxr|-+o@LT=h+(OV$~kEP6G$7}|7BdtlUp-Q2A?eBr4LViYye^$ml-Q@0NzU4eA(h8aLp$puL18WnCX8 z4%az{8%_lBZ$|reNvB-(jy6Aitk4zTtNp7WC9gl_njYcRlZG4;QwYQ%%}KG;ySmPq zfLx@zjc9opw+qe(NU)m%^OA5I%3O7K-0;=^csEB-gwmXcQhz48erz3lOaLJ~WF9%` zI7sa#e6*d(9iGS5=`A*q?@}U^3G5G3J!s`5O|@FH=3n+M5b&gyfx20N8rCOGti_uR zE_xShh!VOMUUVb-+=Dv*URoM0+zMtCjB{yg8h_6o4|VuJ>6i^2E3c5wS(RNpS%{s> z(2xLUB)kfi;O`6$%U*`$KFHnz{-ja5PN#+bnzvT6hdRtT`qk}kS9v2do9p>v{yf^| z4(yt@vA$~TU^>1Vk0KR2 z(PdX`Bt$v&Xp1}G)Vhn2h$CVca z0`MXH(A-z$xkOjb17#p>d7>gznL3%ja~+FKr|IO-f?r~D7Hx}}SNrO6MMYZq$`AFT zlI;gH?wr_gRt3qz&CD(ho1?9YpHm1HTMay|6`hnl@>M-}I9szCr)ZBqja6Jy!ko5> zb0<{sEi)|~@-64vrP_m*BOzCa;Eu+*AE3unp_}f?hU{KU=jzo^=hT)@7xsO37EQyE zn~CkGR>f{ezH>T9KVjvuqjbg1DDgebz~~v~32|#t=dSUnVH4yQGE-^i`t>##8(7fv zcBMwr)@3<w6gf<_QAaoJiNa6!id%te|9EZx&@F10axO<1# z34(0mB^ven{#Qw^pmVK3C6#Qa+Ys`>2Kok1LibB(H9vfp=Ho+ZLsAWWnC61cC6B$Ts5d{^u@lHjcfUAO%lQ1}x% z(=FjtTm5g{M`iTF){!Kc@aLHewd=5kp6%rqXMv+GHm_tuCHn&|$(LEHjje(Vth1WD zQ%jcX*9mkHmFQ)iw6La}L49E1_y*7k$w&XrDb%}N@EIi~Ml|4?j@+@Z*^TvAxWQB- z@95_7+Wl~d>C5ED8Y~9V5pPeHxcnzz0+?>N9?4 zU7B5;znJpSJX}E3oP=%jaz&GxIz$|qcX+=obDol^(m&Sbc^0vDs83j#ap#T1McD0f zM9NN1a;Kt0fEmbctreSK!&R6Rr{&T%hhNPC+p_LLZ0v~xrS6c5kt$FUva#%x3JbmK zw3i8%SsIfS(C5W$ruxC9B`2$0eo&fBd&@w~q)QjZ!gIXPJ|ajPd5Omz7C8P6*UJkv$A1(vD+G{QfY*h+&Ply%j;Py9gajpkb%IU|4aF;K98s z`TPq>z^tEBZ}xe@v_)W}8Oe0iW#3|)WP_3WXYgXNM5+>QE2Pbj3n^oqSoS7&h%BrE? zdn%oU%g3yVDIHy>Z>w_Sw7+)Zje2ePJZ@Z<5ZJqxfn1WO4s|&UMM`NFu+e~7`V_vf z_!Q!ytw1D_CJ%2hk0iYBG6%knXk-7P!%3DIOrkPGN~!~sF^FcoQVr0L&l!G_v|U=g zMW$Pt)dj70k315X8xQ!fB(wO4G&lazq@}-ReQe7F*A9|iZc0c+n&x&$SsA>mFpSkp zQ`&7t6**q5Calm{QE#>2W3rQp2m( z8Wsf#y$Q}ta4V64jyCH2&ikjHADxtRej=33t{!~fg;QAv5sCKA6btvIoV%v~TOw1D zK3^%q=idvzWyA@i6*lR&Zxh_WJQ-Brupqrll=E&>{)oxDZ-fNcA0qeo^TmFwNA2HG z!18QF&rAJglCqEaTdyhX9ljdPCh*Y^>99+qjSDd)knk^w<7iBf_66xPB;=AdUv2hxdUyyA%B{ zQq~_N5tFh6@wfh*sNRumOtuw5v&XGF=v+#v2py?c96i=(oH|av`11xQD6}l+HKSZT zy83DNvUWFNUHV)}a&%RDLT24lQ9ut}*G1BupHF$66pyrZ7^szZK@e=bs8Ov$PB zy~cyHV{$dvTcwo6BYE~=WSs46tME?LFzY(8cTUBvS=CMOTw4z-C{TFSTZxgQzsK-M zwbg0P&op()MU1%cRu$8|5t#q!|1kF!Kyh_l*B}IfySoM_xVw`C3&A15EkKaq*0@`6 z_u%dj+}+(>f@`A<(wuR>Z|3qaq{ad1c@Ze<2e}7RPaHFNX5(VxxS^jG!j-O zlF*Cm_s8Ic_SWui+vGe^PdH^?i!6-d`1}-$YXQn+L*PO$9Y3leNlS#r3(CYFkS3iis~0BQHF$BX zkWSo;7Yrmxh?OLH4l5&91{No`^!~$bUUF z`!1n|DkLB16Zat_0*6Hn{1FJgzQJS;f}NxNI zn<~r95HZC$D<~yOgzLT53d3iuz!qL9jv}q>+64Qn)y*&}d%Np8c&Whc=-%M|=@N`Q zs2$XG%VW8R!Q=!HrCbv2Dh=Vl9=9TwChF3y`+acS&}&sevTI9OKZ|~Tb77d>cr&hj zlpma~oPRG<8NRK&(_22NGj=zOM6JDFF>zpL71e+moX{MRFkA-+C+w+A=F(hF&Uz2z zH_mtaen=hkyf%>q>49RLhidhLoHbtPB)W7Nwi-*hRvETxUoHyDI3+#}rzPI|0iW&9O{)vF zmK3hudC>yofD^EK_|b|1R|a_Z?1=`6C$QMPU*ACtoVpM-mg4|Ma^_nA`$|Wk1Mb5? zFcX)xg0^JdS*x!LWOz+YgG$?aEtkP`xs=l6q->;DPOHh7n_4^C|QI!+Q3-?Ry-W8s`jI$ zz|FEh9Q$Ixj*vH55~dv2mONU$duEjufJrMpIQavfL0u(qLN5MWH@Y3aaEm`whHwFea{Pas4x-5dO~=Vb zgacwTJ=TY?b6XqX(R-}G+~RQ}a-S9vK#Q}nfv}WKBCN-m-$F>mh-{<9k{h@7ov7~g ziJsp{S^no;@}qt03z32kjfJop^M(!D)fe^}(@w3y$zq`v?Be)~kuDBa$nsTImBtlu&; zO*Nn3#B!vS9;&h!$g;!vu1A3Kz^lv!pys!H1LRxf=)Dz00_U!R^HufqBBQ$MA#{rw zB(|#-(N^`y9Q1JwmludXAH8x2Rm<8bJ5a32$C7f8`Tl8~aDKN|;31+0yd|%c^3Y<4 zge2dG(POVeb3O{HuvyCtV5$nw<%gFOq$K{uUaV9{6=KxJttxXY{_!kWdgKF}f&&X) zrUx|ObiOPgwaM7^{kf$P+I6s&&kOz)Wy3~5Vg-R4KpRIAm915M8aoG3S|Cqxf(gvW zSyOZU2Jhr-1)@U?$BRj9A1`y5H*C_bI7p@q!(T~2g@|tgAfdF7$SJr_gGOAp9Mfyj zUZO0zvNArG!2D!IaE*ELS=rBjAG0jKyUE^I;r~1Vts8Y~t2oAR{V<{^`l)E+9cqyW zrp;s=?J#>N<k_UlN&1Bvg)3;yS@v)TJM7VU zEi_&l?3zBek`Wz$?(f)Yuz2W5QgsBPHUuV1OexGW-O{c-rgd!QeNqhs?Qo1jyO$J{ z3TwbyM62wq_hKwc$=(se3_r6H3FB*CRV|m}#$wO+@zhc2Cu+>uYjWwY9*QFH!6 zoGGAE0L=I%7IMfO#7G9h8Kj3z0wD0_9#2y91uGEQ7HvjvKEv= zc4(=8i8qT~fG;vng8W7Llh`MhyzE~D$b(8oIVQT&Szi_76*Kv?Bg;4$_D}2!s&4{X zD=sqFiztPk`Y_O$7gFN3s!)*unDTs|BVJgF9sBZ%>Q3FI=JA>&v5KuB8^*UEsU}M^%pvi$Fp0_w`#hpxtU?GgzXg_i zcNaeuJSaIPNHV|I7m6L@J!$(@N;a4}yW*HV5=!5xXPp0__&$Q?J#@^)baw`opVEZW zgG@tdpg@ix?I^k*tU|jwPh4``FZs|vsyKfpQH}Q%g43@ga{M#RK$?swFr?RDcZ6aq zRype-45zP!n{axz4Av4=Xe%5cY04=AO>qY0Pg0)rLWUL2;_~74_~69Xd0bO&)_q7` zaqPtrMw?Pu3L$1Gh(x?bQG&~C|HX@bxNODrKoUOWJJG3=nSAEtZ(~+jpQ=EqwPyyW zvEwO+UEOTA5Z*Hs>?o;Uo9kIm7rqo#J{j$QNbEFz)-r%`FXB@n?67wmliy+W;fsrJ z=(E&nbWhy}E^xU#lEaAw!{J}5DBhQ0^HeusYHEM&zoNfadpk z1So&3La%7NqukzB$;Tf<)hJlabQ34}dVJz}Lz$j^cO%+Ys1b2)pE`bi{xwE8QbhF; z{tf%Ud;1f|wlJS>&WDi7+PK6%Lg3UkJ^3wzy%3n=f<6b1wdCeLmoS>a&_j9VWpE#w z3a}}6DL~gj8s5kBF!8t~lp7ceTbS|LrzT6^9l?LkdfrrY?mv|&M%d`Tjky~fw5oUUf ztsms`q-Zz5v)0>ob3()FzI_gvH%CBm$Y1xz$nY}1@TL5*U&=fL%8^u9q<4&Lo}d!i zV7{N?Vc;~uWDG-5S5Wf&$a3cDKixq=|=T?2m8iErFqr|JZB>$<0gkkw|ow!y=}&0WZLkHZ65lOK;$^KZV8>#HG)&J+|} zHO{m&A_T0MdmT!E^ z&72;b;Qf}sf(WKBo|yo@h#hbjxh82>NS_h|6aB$lj2YJ+Y+2GtUBV*ShF}vbFRT?qRW?S&$-yIF`b~;YEHeV1d4XGiu zj(W*o6%_~6aKHJrBoz?ZC0_qf(B!Rp4g55ZpkDvNNEn0=;9x{~|AP;l{l*obv0zBXEqB6O|zG}?Wk5Z)QJtdq10Jxt1*wn8$;CCHPYCp zTg=Wp65~ZO@chNd?^KQJ_6q=DbF~13kCPtx;;_5NTUKxDZSL%3NfuCYSM5>V{Y@<0 zUtF|m_|<5=8#mwAXKcx9Ez1C91+)Yroa8>Zc_fAzHEl_z7B*Ern5xAFP9P;3)`RKf zxZn(GDKNDrcOiQ%m2?^a`=*h}d%|+NVn|0?yXm<5l&-LB8XV!)2gkp!9*tK@<;fk3 z@0N=kn@#)F{PvoU9foes0FJh(#;0%hx{p%tmP6$0icpuRW3CrqMK^c&qKVn{nnu}< zEXBrrbBG;4B*0g7b~@8w;TG}e2@-Nt5I7y(?kFiw%bzBzxcP0^H5~fiS}Tp!qOBVj zt6+{BWA{Asa3{#b*kBm3wF`T6XKg&f#K4UPGa7JggHKc4SqTg9>fQy>V8FPy z_W3ujBg^r1LZ7*Kt|8sYyI&Z=AHxZ&S+$p84_5t%;SSSp~ zo~1wnS;+Cf=3$VIx?{U~IKk$oE@EroAK9F5-CIj8N+w(Y9j20wCiKym8jcY{@#k?< z+32{E@%1q(SUTF>UQ-Co%GHT`ed|`dnUWPxC*AXZs)Oh!Rck*!Q`pw@JtZiqrQ}W(uh`SLs#NXQ3 za67C-_1c_!!N~ePQXGff0FbbYPZI#6-Dui{%5My^jPvCU?Rj8{z^D0#8sM{3WmYk9 zVC`=zSUme4VZeJ$nChX={YT$|<9HK!lr>>gLbkfViA`^9eB_0`4N1V#@27y%b=F*# z%;J{Qy1~Jy7YN)&RT3UhAGu3k&T?%602 zqq?=5Omn`?Sud!HW+0^^XgL5j|3klYXagJ5yE;^jgfyBpDnE|Toj9b~6ycx79nOxZ zj}l%OjdG@UsYriNg0U*zeHsutSZWI#J*YNU!y8aFkh+{fHPGtFrLnlqHH=84jrlJm z;Y?P{u&*&!zi7m_Tk%GpiNu9l5L)>+Er!$yVZQ}89qeo#^zyCG+m3cL;xc#N*AWFM zLx{Y5w7-I{Z~; zqYMQxA^uzH0z8TQmF;eT>W)Y+bk8~RFrUX`1r$C#n5?Qe&e7R87dBpB&#AHjD>mW5 zwzRFLX$Q+=p0xQ1et^UaR8ymjob$%*NexmPRS!fxJ`9+evNOzmyR(69`i|sIPohVh z)S8Q;{%pev;S`3Szy~_hpRDPU28a0eL4c-=={{uDu->89U@S#9T>Lj+%Amn;e#%j_7sy`S(->aYuuXP{k9`^7c+KdQ> zgb4jD6u`4ytaX5N$EmZvj*h#QC>QhtAuctnR3UdQzi72Bcr{&*IIEXZ@gfw3p%7_e zxPPn->6QZqKFc|yv$2V80_$$P6nSWFln|uiyJXY&BK$ATr>SPWb?m6v$zWRBqRtnw zao}t9sv9asu+X$lGfVN2Q2-El1M3*SkoonV-bjdP7IPD&ey$GSJu#fuRTGw}M0L=?c0C zQ|_UN`f1f-*A0^@D4PPEm{S6qSekti#==(;nM6ITlv+S`<9t~IY9yB=nLqW-eoLMG zw6ZiJxG)>2d=sz)59L7am}EO4s-k|CIe%h22ujwF-qS2q3Pwj>kJd=sQ zqFs;!_M)%QRY*Pe9^d^|odCZ>l!_g5pf)ku!Xfh2+=u-n+y+FjDIPn58Ha{u*XD5B zg8SXmAKCh4ea5!13E2OoyYLSghQA1}Rv*Y6`!*+pjX|bBLQ?I#2LA$6RBg{ zfy$4_Jjns$UB4&)=l4|Kg^cv%gnh1pK-qih?3kvi$Vt_TXP%hxpdw8f%iwjvJCijTVkwOUw@SZB6GDMo=3)9 zJJKcF*=0#B>-`!7p;SP}(O*>$W(wgvGlhc41kRhE8$i@lK{fovA5u<0U2C?R0F6e> z-xmFUd;d$zBod_oDj^_{yonM>bHyx*_M_tb8!qxS8_9!qZJzb7Di%e96d`wfuCxwJ zu;8uZJ22d7_)@N92OdeN9$Ts(rS%9+_f6-jQOxNE(0n|ByVmpD<(L| z`qcj^au`GA)8d&|FG>E(U3R$!lJkEA$I4$FsTV$rYGj)ay=nw^ww}<% z%H;&Te*5lKEoMAygx{hQzXdnIYw07~FTypvMkuZ4Act{>&JMf}3BkW9 z**LhYmqq1gSNArvm$MbcwBbO|NN?C=p27K;Lm=nEOq-XHN4rm}2RN=9@q_@uI2F4nO2-4exJ)Ei1 z9&)8J-L9N&=`nErvW=2LfGmECkVy)y0my$g_+KsmyYQ!H>F^d6^v=zCl5FYy8Fb6- zV7DnU1gFksdnE4q!9h#ggZV{DE7FvkzYcOUmbn!O#!A~gCP=N7Ju5&6ov0~Z$axPF zdVER`#%(8(`BC_}PoP0(;+_98Z{ZaBocCyI^@kVOE{QlGUe88fZ=adBwbW#+5d!Cne5b!VH|DJ;22*1L(Z=$^$^o-+u-9Y?doQ(!E;N9Tb zrQGsd9W?6WIev_S3r1aPie5u%0`x2$oh4orwr@d7x-fHP5YG+QtBd;K=Hjpa>=YI3 zD*=)o%7b$DL+=xNLN)$ZSytYCgMVlkZhqrGQ@L5jH!ez^ctI)Wj5xVt z6f9zc`13r+f!kGoyOsHS?4XnVHNDN;#ADi=&@|du`H(VyZ}jd_UR~YtTsc($i)Q@!={H-)Z+A8Y07NQ{drzqd?uY9WlZ6 z1a+)17ePfuC12k69C929&|B%QUBS8x|8@ELd+j3n+8g!G!s!UG z#0f%ntNCrigtfX7ai=AP;CU`&#j_m8$+DdA_gbE5~uft)`XVCsex}KUOxDfXLk{C&xRA&Exa9MM z%&#ne%U=FN0rR=|y|n=>@K8iIDE8c*f2}^RaQ_?xU?}64LHzf+3ikZ?D7OD-^k0`q zV0wZ@WPhz5e|Co7pMNDc_-z4tKR?W0-~OwB4*BP!{o?>SnOq%&Fj!P)KThQNtf$cx z_W(&72So^B8Fbgf;E9|fTKYNH69V&B=yHctNq92F<9ITcRozjh7%$ri49d_OD{v2A z@~d`9MShxVUM0mshlFgm>AMv~Rj|}`*cm#l>@#W*|Fw6PghULvLb{OLEU<~rk_`cy zKIRzlwnEpzh^3J&;S>H)DUz`oOcjIAd~EySz`s8ZPr6`lWSfdhrF4AWz4MQkvL~|p z^WK$zys&k})Bija82IMp+?axYk}`nxKbD2D2>d3T}2u)cB2{{CjUqD!DahnNSxo{1mf}NS$=w zRLaS+I6Ta~oK9iXwOkL?)RFBx4sem&z-T4~t89P-o08O|@r(3nEmoiiS8vvpLqZs& z+ZzjDiDa;)Z4hac&4phKGE0cW1k1+gooJo}eYUZb5|5$(_(E=HRbs*lO2Q1y7C;AM zXMv=U_kmWk8p)q{thrfH8I4Q!hRA+EvvX+)VMJwNZMXCAgE1G^rHUMygD}=h0_1Kh zt?{t}(7^7E*WVxZd-ci_y;@Nh1S&W!rMXl~$Kqafp9^Y1* z!wzR6ZDB+m6{aDpl^Br3gAb{TY!7zC&pF3UASZ07zGn zUPduFjc=?|A{SmJhg}7XZf@v#Trv=OW`63?weqF#3R>yppK+yFux-_yTXlZlpY#+( zb2X8GEq*%##R|IC%m17-1mo|jzMO~bPg>Pm2MDl!?69!_*|V6%ul*RcpneCNajgd( z!bQo#H12A4MI2h|QQaHFu0Vd=J%9N9P`bm~dcc&(oDYgJ-Tmc>ZVnW>QDi(ntL==@ zRI&}$DhCtVy_W*>ASRf6FkGk!))lw@jDb_eS4N_n5!i3Q(B2}6BL z`W&3GZ=#b)uWx;q56@8-#+*FORqz;nicu#S(`^G1i%0>7@{p75A z_jJ(lK+$2t4hvKP<>1j5D3RDVm&xnG58>265CUdK?T0h9O}UTYU7he$2i?QEt&4T* zUF#V<(wz2YTTtKau%ge8G`LP;6s0W<`yP$RNaQkFNgX(=q0VI$T-o1z7eGrG zi5qXd4uFrbWk@>hOjIoRYR%w;xy#)8frC(ShJ9^3$e{k}EpNTX^S_S7*#+F9n12Ga z?eV3TD~Qi0kZ_}bLIP^zoE}A7THtosNzZ%-cV|iuDma9E^3Ka(>oK&0euYgaJVh0m8Bp62m3%s zlQZ>(cH}Ec-Yd(?e6P}9I&$I{MnOZ%xiA8G!ELEVPbTy<2q@m zR#v15z}3*fYq8VQ9&%a7l@}-B>^5oI=h8tz9(tC9wp=u{_v2}uO_@dST@HCT=!Q&e2aY-VQn^t>zjC*EW?sFg z&tv_%$kBVcqJmy&OE_{W`8hFomA%SqkN<%6`!EDi$ra&a+5$AyO?+?+araV}mpiw0 z=PDug;gO!ziT9{GDTUd!wX)q$FO^I;5P=bMuDqpnKV;K*e^3!8!J~-Cyv$`Rd%dA1 ztd3ooZ`N>C?T7VKV3J_TCXy(NmpJi?Q4ywLd ztB){UiOb+cV`XVyk!V!99;c1fyX}FrxiK}~BTkP?OLnCABoIvNNfCukHI8Np4xeCh za?Ef7kHOlV63^KQ;Bd8-^!^%FSN=YWrAP=t3(7cy^NG=~5?}5NXK!W5Q?B(Pd{V(c zH?Th3zUslIy9J+M@q)W9ra2+*%2VqSlJOd`Ytpn0%?4^Q-m)W1tdv&C`{^Uq6?@kc zp`a9*Kc1<*rl~z^1+v>D!p+d&%RC(Uo?NZ6jEJW2R%+&+oM7#}wGP6KCJ@E>y`yZAe;fgO|CSbTG}Th$X54c#m*0W-$XU+-%n!QA#v6 zP9966<*soXGOp|~#N{s_Ls~pJpWZ5%QQrA-TB3=NmiVX^N!l$PSe?(D_=k4`4b~5# zoW5h4`aHD{bxXf*`fOW&(W0LCj*{Y`wm_4WN3en~X$Ykwxf54b5pW4OB-n=rcw`(h z5Wq?+OYAmg+t@hcx@FlBWigU5D;V_eDJC>-Gm=Q}`h5v2#pAqktp;n%&CxcFuLEbm zJCE(g@>p|XX>Pie+gXLTU{YrU@LQ2do8@(nc$MB*+*Wb#tS8qaiMO?!D2_mj41Kal zejuj4A?`R*bJkVMg9W4rAzcmMmN|bQY`?(%w9cjrTOG8TnoXUX`Y}R#$FV#^QYDl( z$q?vWL3L-r<3%?;e@4#f-0Q*|yCn&K7jn}8poF&L3;Y6Qaf_h!ffy9#Y^wT&NWO^` zV-l(4u^uwrp~6E2&)yyxfOp0|L(&?c*6^-9d-=WWVzC`|iV1NBTFx~!t ze(3}`EiD|SRH%rZon7#vufMx|e9+yN2 zyWe4HgEyAGxaiE4OJ+N&r%tT>hf$mLHnou?)C?yPq@(Nl7mtw40o~ zNCaKhZq7FG*bL!*I2w8(I1w+~mD9hvr_p;;Q`#SPKfRUmprM|Bc4bAFJv+Wo0!{?;nPSn+p0M@3y}%$$nvGH6Cka)gUe^9g zL5zQVpRG$X2_}tvR}_`ZSh=1!qjnQsW@hHzTm@xMD85e$uWiTRAcImwzuGVVLJ_F% z6u5jrqu-t;&GPE{X>9W@H=Wg{pVjxw^20B8BSusySGK*w4^gqoSdLM%8t(Rd+b1jx z`2hq{Y;v+e0?QYh&z25P8T`?@^C9HW((%k)0|p8k1b1&ANnM~%K6(2Qj*zGP;a?4S zg10Tyn<>`F|JcA5$Ee}`;w8c>x1sTI^uc&$>2~jztfpgRhYK|fli@{?#duqP`g`Ep ziIF>6YQO~Vb?BX*PKp5Dt@V&=cQjr4=@E3+OX|_q-cGI*KKQT7b6vL97$hfyRIJs_P`qD=-i8#l=I&gTD_%eX-iZwxq7Us1OkB{ z1jMDxt*n^4*$u1Z4-NV*bOuH_M>(TcG>6Tlj&2)v8jL5jY=>Dqq|CtLnTeM(X4>p# zqyIbw^B(Wqdf4N^UY}H)gcE$qMBp2Q>mS&^Ovi&3jPBmDo`(?!x~7E{&wD_6X3x!= zOOP!&%rslT(sBrX^S!Q2j&Oy^*DqWBBIRO!2&%%;0bSyk ztGnFf?+hG_@_G3)j(=D2Z}j88SO4F~hSP=^E)A@$E?DdczG9J7#Tk4xuv(S;I(e zonimESkEKrJg);!kaWwWT$HE%D~`sjzCW9sa3u@JaF@YQeD;UzpVXixx>IJp3VuLB*C-G zaMFJiMvD0!{r3BtyRVxutm14etu|W6qZued#<6zz(2Ydui5V&_#dA= zNdY73kRyvNY?oD}hUX=xQqzBdOMStIpMQRCwOZwmP2Qjn`3qF4#DBI4vMd;13m#n` zx#n3bef)bUQrsobu8b-0@u#z2PO9GD+%Tk(XWMVs-r${=t4a@Zj`B6vB+Z5{T-XlV z4u7xPNzzM=OfpZicQNNI!>`%hP1;R*YgGc|%mzM~l{D;VB2M*A{U5GJS*6G3HXpVBozY>_1Byj1z<@IcEiCW&d3nwVcrj1mOB&(6JphEaPN1pJAq3;pS>d zOrPMC4XHEP1MBgn@gv87Ny;v5qzpElZXWEb!&!h3}uZ3MAX808QE(W=v zAppB&$2R8EBod99bEfqKPTD#SPPK*ih0mzIC}vfRV^*{0>b;v^`n8a6?lFhO=Tlq) z3-gGo!N#@dI_ zb0j_Z0xS0uI>}+wU##>lf6nK}Q${;7F}S1`C~!nQW+Vr124it(fgVc|wk+3yNPhw4NzET9vOqy#6?U3zZTc<~chj2q&XA zN;iyt_l^DXzfA*xbiRt4>&4KesQpF$>!)1>Je_V#gK$Zc&w#4n6;rbdw6n5acLTyz z%eh-1?a`y^kf8$rRoF7vKi*URYsEt@~ureA$o6y|N9 z>+BsUzI$ume!EufKR{+jW=%tr&ul~aa;~6+l#Lqx2KC5E4LR5^=BO_mL@_1eFs-g z=z}-&F19YKXq_Eg(%kmd75$Hp6|V3!#y92HvF~7f5Ag$lI>mlhQ}*g}^C)yrIsWj6 z13!8mshQ8x4NN&~tni`4*k@t_JHFFq$xxTJn9^xZ=v`kNjbv)HdUU9Jb^UdjWH$?(X42RWz?$!#`)X zauFhba@8B@Sjpeie<_pq1F!mykAx(}t8|)3@AFUZo>i+(aq&av)kOiABlB3F=Gd3T zpAItampb9od*|Gp4F*EX#+ocuoGx|J4ZYuDl`T`(EX3vUYHw8&alF3j z3fAt_&Nns(d0^@u;UYpv{E*J9qNGfa06EKIt2nfX$@aj*K1j@ zspcV{5OFC0N*t&PIxZp|dSR;z96yeigT=O7-ODQjkG$l{f7hZaZz3G0{* z4(eW30M^tk0FS_C#!EGTWNV~X{^Nno$3`sAASy=#IbE|>CKhj_I;uIg38>qoN7UXI zQ0RD0Fs?nbPJ)Cwu1HF*a^i39Rd`%ML|n+hJv+#CdT$1)f`tO+m+uVnw%=GZ*umB@ zANMp_8l3`<_$C421ul=Mwf;_e_G`!~n(y(YTTeVkA2~Y5UgO$;R^iL%IAB_dLYhgU zMu|ZMO|lQH|HmU>8c&X9524k3vyK?z4gR1$|r%*IDSuUNqnJ!q)o!}*Xt zP2@FA0NkVYJghvtf5}SuBjiv%thz`VjzQSPnfxUu7^t27HtNNeZ zB(0gu4j+H`C5w8^2^Fyu*(PO*vY9W#^^}{k!XGHWtjmuH$vOyz>UBP#S@cDA01Ljo zFHV2J^j<7(pHJqt+3e6}-2WNwW>u1n2mR?sP*!OvE!H)w964?bodZ<7w|+*e<4ZM4 z;`cLjk47iFYaeGIBh{ETwOs(NG4LxwI^rx`LpokE3e26ejTDSS!+MsMD7J{Gp@Kwp zrk$huppKk5T%vd`h1U;j!r0jIZXrnyIq!e0n0_o|BOaugk*qYhj&8@l`&s1f_JBS5 zZJh6n*A2;8y(oJp$t3kZoU`(gH~+(0R$WYb%lOk?AuLi-CIMF{@QPoY4C3*|hM<<9 zPJ|zo{f2Qda!Va%X=N({N|M3Af`NaFi>-UcyqhHhh;0Gy6qrM|eYp%X%2o2d#fjW|gdoofV=y81DsCSQMK*(+u{ehk=#uhGf6 zmR=Pkx?g1{tf22g*SThjc#xu=!!Qg7TzwUV($zqSXwE|ncehw0cmQ-lu10)@N&ZN1 zQ@R9+JIY3@4}DWAcss+JHvi}tyqge*f2Y7vyC?V^C3u&meP+@5J%2n3_K&NcTe+fd zot0FYYJgx*VO()t=n%dmo0C0<1bqB#Pc76KCJ+Wq_=-1)=gA$rr^Xk%rvYRSsud4I zvd7c~e8HJm(W;SSQ|$@pF_MlhBjz>D76^ghgpQLk1JkEZYFKwBnAA`B_v%X5;I^-R zT^m#c=@!S-wXz(cSS8BKs8IbxJg7a(oTl@}&Yi2J6ok??b@S3Py*Y5c^|jAuuL)~M zrn?>xlIksEXIROBP0oUd`tl+ad$xe}KHm$=+{JQB4~s#-HL_p|zgy4`$*}d!3+{oL z6912COdIi3bS2T)EUc`4$LrWbsSRj~NgrtyN043Bnpbu9qJ8fM?C-sYqjNp^|KBo(7Mn{N>JXlpkRh;N-|?f>&rt$x2(5!S7vQ9 zA?tmy+z#${H#bm8OMS^QAt8%#;uM|eK}$RpOn_yx^5ZT{GBzUgDBx~@L4 zXtzN8Kb_c1NcSc%)dfkWG$6JX{|?4^ZBqMC_!B+qWtrjix33@UJLrON-Wto-%cDdT zl2KU<1_cC2cW8C9F-=&^bjR#=5_W7IR_aY;%1hE|<)+j(Gz6D4__#GQI3&2vnK4%! z@6jkA@$m{2W+@Z6-&|STCy*sB&aD%(UtWE+vN5l?r3d)8h>FG8qZN&+_SvEbEiB0# z5)8!@!9&`Abt{%$LIUA6a5ZMuyAgl0K9TQK^7v`EtfJbC7PK&-b-4e)h#Sqz3o3az zv6NY65#ln-oBPH8QH%Z9UfR%Zd;fg%=U%;|ME{Hsa6*6m%Xo-r8j&^`l-BGw1fzjB zyxiP2wQRVf^`oD@UYr}0jzq!Wplp~PPzcTlp}9ZY`ro{Bz4)-9+)p{aThqkTi1KZ? zOusDWYS;YL;ZYkw@HCIJdwxK5DH-*fpR{;4+1pv~#u!on%eXsA+Tg$_W6o^{f0oCl=6CC% zt)?IJ2hY>8=%&=aVz%S{tqRxVwGSf2~-V-P){7i7a8;>95UfF{`dGv9{_`@=f`y=BEg;Ft6 zSIQ>A&>lFy5FClQ=)5-xzLrk@-|{{aghx|kQ*^&Sb*9xmk%|}_!?o$1ZQ}@_yJQ`Q zcYgIi)v;O2Nw50Ck91kIoav`FyGwZDt2-9sOC8@mW;dJDL+2D^f$&wnX2IH>*SE=f zNmh;mM2jyC90I`RRCFC)@NQLad`kePP+o6%YI_di#TdozK>+oN<4tR$^++>$;kNuE z3xN`QLYIX2(_Iz?qrjs_==*9-;UR5Ti1<>H_A+E|*3D!;p8K8~S4u160lOlIvcb|n``f0f$qskSxexD!!7HH$PDh84iW7;+6w(Z=MHHc`D7>l)cja2st1N3 z|BKHpK0FU;ziaZGS@d-(c(ixsrGCni?>KN+fd)g=4rG^W( zQmfBMi!-0rfhS0^bJoauE^Qg^{>jp{>!-^x$;TM@;ekt3>$)I#S>3itae%rbXM@*j zPr3QRiv~yeZk@VpNIbOj(GM0)AON!aB*N?QDJKRu#~!Zo?2}@@6XDU#k$yO;kDqiM z&LQL_A-=JsoPSESHc*;8KN@d$)WXOArPR_A+n0je2vo>vS--1b z!A4q4^o~3N9nIDQ@u5~&zSA9&ONqy-ZilJWy+s?Yt4^byxu#g#+p>lnUXePk`pzznG z^!U6H1Ve0+Av-<=kv35<6|9FzHU6Egh%5#tlzXo*W>p_UjZpWqzZ}&C6y<$sKCszc zqdr7+K}p4X8bzc7eXovyX7hfp-y(g1w-e2K zQ_EppED#4qP9BR^6|X@qRL=tXhA}bdYBE>P{TqoVtA&=m?|q_V0{$r)-?BLL&_`eP z?^PGVTS%bd6%W;!l@;w^ zlRi^o57?g(R0=NpT|!_QNX{Q{)O3^aR9d=unmKhd=Pc5N$@iV#*xWx5tLa)}jF3?e zb2CI)Yv*t+C9PLlG!`d~#9@omZNu)pk%JR>;WlNLS7-d84xnU8CpV)Q`p$klgv}hJ8M#Z^lgng z{p3L%3o?J7aYtJXs%CjST74Of^4Vtin0@H;CBo{oy>~+cGJOq6ICgx;N!uXl3dgwC;gV?sH`Ng&VOaH9DH!0u+a8}ZMn zFJ^Aw^6Q#@gwn>5It9`P=l9d2f!)Y6U<&)Y?HM zLp6)IhvF39&2A2%`p940HK|F=+TxIAIKu6|Dm@`XNudG6r9H`hpDE^acUdsO`bX{` zZIvlUTkpI-*#HZ$d`~=x7eu)qJ`|9n70~tw72%v2+8?|N+pUvX_Wk-+E^y+%2L=8c zBK#{}6IyK?;Y}$-x`0wks>uG-YP~GX<>vQi6y6;VTs9JacU_Kj4LUPANVnnR>xY#c z)IUu!x|sk9>WmWFqPN;T5Vfwp;foi7HG3$>yja9`yGGU%eu1v#pRtlJ_=b153&jXZtoV%Nfo0GcejZzxE(oqnwJ}j}v2y9OsdOlBlB;x3neEAh! zCn9`;;JckNVOm^E;W!${@DPQvcOSA2(dLOCXJ)K~F1G==l~x6w zVLG=6>Ac~I9DoKOw7BDN;JvK_`hPAz|NiVL?6AL@T*!ES=SNZKLM6?SUcqY*{a^94 zo`AkIY{6rWu%&UG#2~3Ft_+PfOC;O3dT*kA*W31R624i%ND18|thE15Jc(-8;h+WW zzWa?3OT_f^d=0212bKrYQXwp3&3a1Hgs;!gY_Az7P7vdQvqbZBry`{i_`bjRTBv7@ z^LKbKGPo%_lNnA}5Z0YqTXM4?dz{t^LCcT0E9L|>>oF!XKZW7T^22xb3tn+y_nL@^ z)?bLfP(TDZs=58t$BW`gts>{)d_m#gFn=lj41U3{D2M9*McG>b#kH(mpt!rc2X}Xu zK+xcB!QI`0dkF5q-GaNjySuwP18>f~=bUS=Uj45M3Ye*yJ-es7`FgGOt#zBGh_{Uc%z%`p;+HQLHFy>a63jN}|?K|BHVciaT@N=H@Pim9+F7c*wRSVaj!|7ngAE z7>(om>sDc;E)+TYh_Fx#DCn|?Wq?~3-? zD6Xcx&_!iJ`P8d4Z30b6{Dz(h?*xVXuMwDj{cO4?k8oi_6w%NQrf53=Cu{W;!LtG= zlR{!~=oC-JmbyOdJ6`fuM*jcQOSyE%Hl}|3|0QQ={GQS#4QGdma~uRZxqjo@8j3hk z-EHQ``B1IEKec+S3|E{ z^I?5ALRVy0i98;Wsm{UcjpX+gYj%1z2ruVhzqj^T#PzxG3XXFi5VB)Na?kuoo`M@P>u{O`1{T z5;Th~D>@34Cs#Zay`;RQTNZW99--st*9zTr67*0g%sxh^+!$7V1n!G09L@Bhno0|q zHw8m7q;I`#)oM)bRm4)d*H;kJjyd-gR%~`nV}!M|L5|w-c9m(ezKSErE0hNdvN$=I z=R&i3nxgp&tz#xr+g2OQQSW`B&w*6RjbcW8G8DmwME|EgPYoQwLveN95|_4MgJ?7YH?6tX*>vCzV3=8c(t zDwXIhJ#C4yj(dYJON?6_+B0R2dv9PQ{};V!3dlLx+VUzFvInquZ`9_>(-%AzQS<|t zR^tj%cdce;qWwb$(eaw>tan>U5nr!+BcYLh)&3p~*sr;qJYEAEh*e%Hn*5X2(8Ui^ z%O2#so&61nk56ayE`O}Je_858bVtLz%X-B)x<}I<%#iBp&K-KB2XTJ`A@w*%sdJHl zdU$T(WLSsUkRz!1np2e*c|4ZAaX$N%DU$~T9Qq>YJjf@7`x+Q=)=mfx#n?So@D9R0 zq&fp$z`tVj_4Ow+*w!P_B=WIOrF)=vJ{%T(%Ko56%N*0+S^>t~|0S^h{jttCz^;v0 z8x7^>19rzGCiM*!Ug?nacKmYZAOz)APlc6Ut(G|jy}GsJlk_mX%1J9)B>nOvMX@(> z7f0u)(1Z_0;RZxE>{FxuzL8_DKrUBQ!snyLW{>uZZ6A8zY&%+XhP zGk03AB9}x@OoG0Vp05ODu0O;1F2BgGh4!j>g}X=zc^ILfhW|X)Z~RGVV$(NJ^Sh3y zURaXLHNkf^@9R>t-o=x1JY2zefjtehgOd|F7Z(?el^x?jcEyiF2kl_!chdG#?(q8P zT9tEti349<3H|{h^vu4Y`enra{Zo)>%D($#`32w!HnNG%(JfT=y{(~1OFOJUm#0L? zAaN}Ub$U~aWSsD2q@j56@W|9Ib&SXI)0P#s1^25~4-Xa9!3n*^){L?#)6u8;OoslR znivEfObTQq+2qMm-mu`{T6Vlk^XEEKO&S|bnQ|S=$j1ynbivq~*AvS4 zB0rk(6BX3Q4Zq>qvfBKBQ-kFSOjM6g$v*A1N|l zQ;&tO4NbFYkZ|UW^{Mrz_Nh|QH^WECufx+?^z<@c3e~C-AiX%8ST9=Mfd$)NAtjWY-Z=zp*^R^A71;_S0+UjD%BjR zoa>UFR(|B*SGOrGB>s1giQuo;!W?4qWV5;C--!^ptp-4%Baf9F9 zlPmH=zR=KoZA+zZy63HWpHO?Q(FS*DWcu_;hDZ9`cGl!FuP!t8ecJZ9BrtR-H5p^@ zWaDPE=FlOUKa(JPR{ErQHPWL7%}BW;9O3OYsx8XO*WwWYwWtTOz@WRS(a7c7OaI(T z@v<0j_jTjClela2OH6vm9=;iLz-B)A;jLej>+MG^Bkra%;NdxRlvlNS|H9WXGhC8} zuxzhOcE{`CZC=XmX7Q<0PhlSqUv&TICED@8Fu(7JoWk6Nxa8<5vD^>KYphRhEoHQ} zKS<_zAvhG-+uF>x2$l1kzQIax=D$1)%_mb2* z%KNmpC2nD@D@t2XkWr1q+*E5BlY%OZ8a{T>R`UUzk^goylmsIcj)x%rNonbh7$&siE$sg4{0^&4l%0 zP~7wJ;e*+cdg9KL-}mMU26Gi!uqxlk&ZSj4L(c zV=;sj8!WTrCN0&!id~$W9Lyhe z%<7@{PSwldVMKyJV+}9X?;`k^N^f&xF8}TG8N9DQG&0dvcV_0(fM!X_KCuvaWRkh| z1NXuuLIB7Vk#1WL(9;;-&C=DV z_4%=*q8;;`Ti?y~&)8#hqNIQ45OFowh$=?=;^^eT$VT1dc~6R%>)ru6pmHaz`xe5m zo?6^I_PAI@;_w2etMnMnXKt3dI5cj5(R2{cB5*ddPo-c6M4I7ZNaN9rA3hT=+(%A&!`A5kc@6SiXTZPU`h#CbKXzDB@jANW_nQ zTihL3xNrJuLlVM85Bn!HzwrqS2+g~%aZ=h}Tzxvh;(+=AZ*r<8R!N8Lz}Nq!G9Wyh z#u>S4OJ~Yh+`=(OoQF%}P}b0ijjQf#3pTQiaw;WJ^iMcGV|XevA=<#wQuyfJsmW0Y z%t#Gl;^N_HuR_9HSX>;#abK=ZkfS+{D;aolpz-~6j6(UB79f~L^!id(+U(FN#COG# znAqU8CCv~MeQ z@Q<|kg-0`i2*>&rHA)oRm>8(fpz2q&Bwj7?QJMaVw$iP$+=6S3$Tsc?OR}$b5Q(&S zMF9sv3-E7lpKAL~NKa3w)V$735O$hXWYY1LX?%O78m)!XAi#QFd+d}XRz{TF(_t^a zH`CTU-b)reRi-PU!l(<@Z*7@tGAc8bDHN&Aa=B#ICt|&%j1mnbFL>4Un%o~H&cmXY z>~)~KaK4U#CKAZxd=B^?#yJxHz3|atS8eVTU@m)gHjJKb7>}S_YE`~uV`-Ml`wdR4tf(jZ|gbt))lfT0n=K%Al#rG{SD-x6- zBF(Tu)sdcdYt5#_NB_r>L73REAP^v61U00L6YNB}{81}#b>9s8=lkL-HzX5osH6!t`SW`e(#nHTQR8r+ySY<*U$?M~;H*{%j)5lNj1P zWCmICA;){ZISi(J$4g7=QYq?hG5Ld}sy-1!7g}tJt~sae8E(dEd9Q~3c-_6{v>WUD zFy`cZyMn~?1d2K)h%UwpcU8VoxYEn{zM5z=QF*OdwW@)oeK)_I71hYhj_J79*;3h8 zt|Pi)Bl~f8Iu9d7WPU~ahDqTobOX0tHFkA1biy_9iOB4Ts{8Ll>++b?Y>4~dP$tD~ zvV{0ucVvE|F1F_TQwP0`x(vT0aoi!5?+-jg)1iHwxMWbV{O?v~n(ikh;-^HT8`CcN zI-BD+XB9O_G!!lGk?gdljCy6tL|SoZy~g?$cGm~M)+USnyL`MIVD!dx+XIH9P8R7s zealGcVDh(dh1qYj(IlyxbD}Hn*Ce)QF+l4Km-yc?4MuwTKN9ZVBpdppqoyx#$tKh$ zcJwABM${}AeGZ6z3=%)j<&OQBj^iUE3mNpCS?;KK^EF9FpjB3;%#KdSMe`9I@KQ^f zmf8vR>-#*lCb@I959N^>W6hFm`q`&w;%4>v5RHKh%}2g)!BIwIwQ8`uZ)jcc87N^HhkuWSw)9wc*pkjX%!O{2&0C z!82>Du6r>TPu$n`MAUrb@jRBfaeO7&#=Mdj6k|=;sOzY>y3H+b?!3MsUlOd(jhPs* zHn7?+endG}k@zg=06TZX!qgso)a6TMxj#)0pVMvo=#RF5&*rCE5k3o&xQ<1)tuO)z zPlxK@hYKRxlNPe8q;b~C$!;8t6&z0A-FgJze#WeY3vwuxdPF7eUN7>$M9G#O+zs4n zp3w;W%=@q+FDO&^$u@0Q1(`mn-s$@u(M&OWx)S!dl5D3J`81m7yeC&`v}ZEK`@GUC z*;3&_8Pd4WqDMpzP&rGNk2fZ*Nxgr>`eIeqq$F!+lO5y4DL%5kZd{P13a{zTcO0*L zwwPk#MeKngB=!*(Ti5vVWO_vR4)=F2GzT-SIru49u%U$}NYX>Ykda%YSOn}FNi@iITp0UEct+KP(d_TUB`>i+oo4@`p(S-x`UGZ5#c8KECT9!pAf94jpY?FqWdAi+06gPD9x zyOpg#=-(}PwUdq6u$Lp~7&Pz!*Oq8Gq}NTkqvwAa7}e~tq<=6lYS4hI#dC8IsGzr6 z41BxJO|!{5(J$;A8*rPMq|6{;9ko~;AN;X=ROAWvE&>Bn&$*XrHg zgiNVD91hkGN8T9D5)}<{RAmULv(O;U zhc-Z1RU_Q?HAOXr;t!I4L;+>P-j4F3s{0*HNJz=TYhJH)WCUU4uIp$1aUAmQ1+WP0 z`M;pgooTgF{LLQ+d{I$`2wh8k5R{aXQ#h$z8pPo3+n3J_J#Z~vGejxX#rRE_-~CIt{1Tb_dQ#iC7gH- z=7H~g^om6~H>-uInwU{<6~xYL+PSXrN#;T~{28YjRO}SvmcD`6CmDUeR_dp!o4LGi zRm2LOOe{}A?2;xV*74D&mX_fbOim2_FCl}dc*Ng$9?CQ>G7nQ|#w>SFiD?boCbfz; z+ZcGGc@gO*zkXg_Cu65p^ubVj*Mk3excn|1T30M+3yFuTw%ghwUtQ-YUa-(xvorIt z+^J*(K)AM3{`}-vqD5h9qE^hDiVE}WNTO+B zlN0h9xI_p#M4ZRr?JM{c-R<|TW@y37#nX-#SDwd=Ngn>k5x|C1cD%o}Us9;bN53;S0z1jux^27(L7TD=>fb z*gn-WYG6d7!okJSYR>gWJT?)mcfmK(jn-_vG-p!X4G~%sE}rm=1OC$7S_ zTO?*cqKWT|*>({>d@jmX5Q#I%l+ch0qW2Ztk9h}dn=OXNYH^~I`yykzA?lj-xU$Su z6g*kmxvylFbQ=YQhCc26Vol!{>#vNf7w;XGlF&$UvFxjmAPnwJj}(82;+MSgVoKBM z3^f7jy^`0od~6%8ZmzK#*$3i6UAEf<_mV|nu5X|PcW}S^WyGFV+U>XyyQwG#8852m zu{^uuTl3eToZGPZQT!5{dw|qHp9Qh2dyuS5;3RkbhU zVBV%2K!G^N;WO7gvM%{F6AL-l4!?pPzvd{F{0c|v@yAM^7IdeRlApKaQZhHP`}w*$_e{VZu~MP#HdKDsf9Y2sHLCIHvwE6&!#~rRgQN)% zyIw$}D(7tgv0P^-x{hM3MD@7%p5p}45U?NYOW<+=`Qh6@s%`-7`k*1T zujHYpUh$$kLPI~iun$2k-&0qs12TOJMxc-sM@XX^8^Y!tckFuz*gl_Mw13Tk2G=iG zOWx-0)>pG7N4igg7A&mjC+=&V_%Vaw&ndM!0OCR}mmsmgk8Oh)nlWoVa1L+5K_yIk zuT{tLcAOZ1@=Evo1`)75%>L>L#w&5M5yoc6cn#6d-|Xd9g8J<0Va?=-PypJ-YC+_2 zJ_)DMh<9ZPL@`Co<5XStVjb?@(ko~81F6?=&C+|Z6%GUCb6W$hvS(vZvNj<*F$T!} zYo|ef*c;bvw9^<)Wz+5H1+<~PvYoq^SqsN~Z(8-+ctEy|>$vLMT&=^xy%$$+N`-^u z?Ca=h6V-Vd%qIQoR`kGnr}QC%Fz?R_o&Ez3lVj=t6Jteos%q{l$0 zU-ua!8or*eEqM0l;P>PGM;oLl42^`n<%L*~a03cle;UNd;N686%_hpeB?+9nyloc}rPkY`OCLP0jM*j)u?CqoE;krFPJ9BI|Df|eB{qNl+?Y?Xd z7dzTS*SntOZ6h*w!3?;LYfWwV>jlM6|Ra}bOpVog?>bo zoC}DjOMCT!%LN?XV~d8-WA`(_RXJXRmaw$4?`7!1cmM@B7R;^Adq4qBLHF6r4<}dB zJzxXYAHT;ry(j-ZTnJ$neZlrm#OEb>;0+i>+_EZCh72vDT2riN%`Uk#m9j1 zC3*uISWDMbhoZCU6H~Ie^l^IMynoXqfI8`y!Vb_(4K*>p<9>UQUh9;QYQjMS69QlKOafnK|n^qicZ&+9Ltp=1&(OrL%H= z)xQhk00EMlVx9xd!^WiBlsGTn7>}6Lw*>;Wa`>-KW3>}@42LY_k8cCK2a!$}PeXKE z_D21<)=!(H^u&HRofS=y#b!O#_u^~)=bICTfWANtmSdqap){EBTNCFn0arwkc%+@f z@DIaNyI2SEosCOt_7BOh8=4B@H&U9xa*D!iv|>5ZoNhVd++iR8|&?ny5wJD$5$zWJ02| ziQE%^CTKRh-v66Rfcb#f?lOg9=96ydYQ4j`+1pR`?cSq zSf8|!(VM3Qm@+QlAr7trleHB*5h;e4C6P~UZpR>6^I z5)n5?1JgFC_1D2*k>hg$h2Qd2mQ)%;UQ8k62|S@{Ef<(0r6t>tU|LZ_=VThFAK9VI z8id4kAn_9xDajcZo?2ZTiP(g--V5>qo!a-MeW2LVUyWW$)GfRY$A8xdnIc++uts1n z-_m_@hs9bujqJ2t?~nHHu(#&KVG}Y(C=;D1RZuEHl=PcM)-z?gh`((b_H+FdVo8K2l>ccsTv`5@OzHlbJL+)Irfedxs@wo?t50a-neCVcMg`f z*JMwY*D*09P1VlgE4ej=9tTzJ>%@Mpgvs)FqoH?n#je^lrV|}nM7%Z9{5eG&YD8H3p^@ z2cq6Wh8zI+?=(qo2lc$*$O^rzt=6ZF_|;j$eM0UaiB2{I%PFp%s_PfbK5s^uOiUlA zx1POpd-@+zFdIZmNE3x2?eYT|>zZ3O?Uohug&aY~KgFDM2C7+@e$7YJX*uD(#;S=d zHvzhKp~Dz=L#Ea{4{ny)tZub3w>Rer(d(Iywo`4r?Z-d4c$>VjG+<-t&F!@?_=M0KqZsDXs+Ci_ zK>XRWN-I0C8bXb=GWgiPIjayMmYf(OAdF5GBg;qjoyltUaw=R(J2oNWH%N;SL5K5~cFO9s!@$Y4n_J}i2jW3et zllPQCYHNBoA;q`drq_GVRpOuIBlBlToP>m<{~N$tfdc`@co)j5BB z7wfO;Ej@my^2_PdvV5z@S)LGUYFfZ#c$q*K@}1LRPj`?h4w78cnv-_-tphr>k~`Ok z?D!;u?leB#k)u7wrtno)Tsb;m$lD@{ht_n4Ge@JWw2t zkEg|Abgrwx#o^I5$e(`lUe6RqG*g)N?SpgR)T0WT3O_<@4|bYl>ig+%8TP=C9@as3 z30Hw4>SWSk{_(=K(-R!LbM9H0tA$CmJq;WpPKV?$As#t)D<16(WwSG#VvV)tN}Nsw znjpn+K5eSVM*Kz8%1RCihRFk?u8}g)coX_!@u$kvopw`~p!mGVD^H(d4M#Gy{Bxty zC4thUBX*0pr!zoh?yi+!Pth*K^($fhP&DI3(9?8h#Z~z+nU2*0>IPv^M7u+Yk-n?3 zzU{kI6&IK6(p;b7gogd{pj4B*y!ZKra+NmIXoVP_L&T4Z&@%|32j@3N6&44vl z+{zd%$IgR7X0Y;P{f^wFZ$V)vpj7w-i)aLe5EQwg{8@9WG zJDKdD&r!<-q=#qzZU3yEc^!dG>oW%by}gg}cp1t!lV?fpPTkn2JeY?q+#_V5_x9mo z(pp{L#lcyi@0(xW<-nPgt#(1cB~;l4?}gGFJH^3M2+0H#Mj(!)gRsC6mS<6r3ZCyN z9p%QO+F1rhxDNP9=3Tdu|2NU248uVj2O z0N@4%Wprx^L6fke7(+pKKjhgo5%@w6Vsi~HOB>f5$lKQT!fSZl_4WvmHlh0xwhEPm z+3cEbRTXI#>CJ3B;kFAQ4Oj_f4^&vavaFKgXp1_gFZ4mk2QC;b9*!$ML|;14Qb3TB zV%r;-(xsTu=kf>JNsdX~d3A2@oPSy3(TnbE2qmu?l>z~oORhGb!Z~w!A!x0XAbGQ7 zPC_V69#3GlcwKThO5lHFQCIlrzc3fFMrsap8co~TOV~K-96-yyXo*<;82`RIar{K% zlZLId08L!U8%F2Wi~8FFy=uh1zgFW|hTR)=Nj^)5U0HBAOBhhow+Ci#>|{qwu&)@o;iAAb zhq(kwn`JslyXtc?E@DDL`T?w*!0MdG4EkSXysv38RP7hBiDl4#mHYY=%Y=kh7!wg_ zMh?~%)M(m^Qmv9$D3*kEc%T5+ys-9I0sXAL?nuvZ&0t6!?-B9`4T@Ye2o<+H`{yLg zHN52>2sjmM707*CiR~F(L}yqB7@njs%V@f8HBfG@GFbInoS?U4gnCL$w+A87QZrR< zto^=&VDSlKC}#f7@Lg^9#&-+rReVHHVGl<-*K}8@Nz-LH|2(m$36hLE+*n+@*6x8m z0#&_N7~|EAu1Wy1lkE?>v#r;O)vHQVL}hgRxf33!OI3kbbagf^>iVYJNBKUtlo;3w z+TO8zg0|3DsaV>o1zr{XrGRzm_3P=+b_r}OV*6_7SB73zfq1`8elRTEY$3{~ZXi}J zz){oF_0BdD(VE31bi~dMAP*Z8-x@4qkyAB@alo^wSj>XkRH&M>n^UAMrFQomGu)Zu zMV6^&3wJ@poNtH~wImu?7)8J#hHmxR;$`r7JoX2>F{~P0Rfkm1>vx9r`fc9z|ERdH zzKVr(pY29aBmL0ojgpk8v{=MBLdPnk z?($hiCfEhH{ko)D1lQ`*&!4OUy$M{^o@)d_9c<9X_^CNfn4)6(B=2`jPx<;%Pjjxq z^(TzQixbGTt{cOP5}^4h|7$Ly%X_+$!6*3kWTO)!E7EtMtikb4;!EU*BBam~QoH>! zDkNg$4EIy{p14fddmPSO{SX&vj610Q%SE1!0u#IIR}$J2B3a9(U&adfYZ{IiWu`iV zySy$+iwv9&rcXJ153YlUsVkXnBRHs_SH^DkKe6Rxk-T4NXF}} z9sf*$(ZZXMAwW&xDTO?p=dRw}`4aVKtn48ExDU`vJF>+E-*`Yt+5BhLeg>NX2P33! zh+q|0K)N=AJJ)fnzAY8Wx5LQiLDk0?@TqNSXM(XT-2k}(W3H^g+CXWdLBri!Ud2ma zmpum%f5rnAqErD9#M-F+#_nmF^QbFC9w7BgOMCtg>equmgTB_*4M1#mTOS)TmO~t< zu~fj7vIt4^J<$bHrPLs;BZ`K;VhqK_8Xf{7D?=lOD{V1U0q|mew2ttePDIW^gA3O6 zf{h7A@Rt_A1{-8mrubW;1;7Ei+E*9HTaX~S`tEsCq6a)9JhH1$sba>jD9ik~5$Ul` z=1eF1K?A*YWT|$$-xJLD9qQGNORC5;iK*g)xZPwYThF5=_SCJdm`lR&gsE4_bkWSc zy^;>kjW{%0p`T3HPN1^_z9;@jBcVzOTzi(SYYuc9?^7I5RcDXK74lPqD!1vKH9~BQ4fED$=9BMzq={Y{y5BvS^~Vjk^NkG*SL4dn zaRbQV&-iNv;fGPXB_Dy+^Np28SVfgSK7FRp+kHr!^$m2Qaj%@gCA(}t@SXk}O73gn zfP_Abu&7rFI5cJY>#M#4>{I<(7<{S6LDp4^quu+f=jFF&AD^K`D+$voL919bAR;X} z_F|IE?I9r3C%%aq>UT!RU)G4>G_lVcsa_djj0Eua?;_ijR5JXdQfNiF`DfK|JOs3J z`2%0grenOr;5DIYaRMoo7QLJ@s8(Cm8vkD zQm!!ku$A;{Ulz+n?s1f|=%>1!i{G|AK4V02HIO!aj@O0CD+Dj4v-)ACE`#Ci!^_sH zc1VCI9|BG{RnFIxSf0D=Ne8AN#Y~jhv<}J+-fR{cuRjXDhNBLC9dp&ezC*$2zG8+( ziCi@p(uAF<54^C0+6h<}*Hcg5O(~<(xaZt-bv_o8kKH;e{rodj*?Ri2oAivDP>GyJPi786WL#U zDCB)VVv6rq2pmK*UFe&T*64RwDMJ@^(BbvmFyH<7y`D9~>aHtC_(Odv*>^OL)UK7- z)LG2GWK5aho@!l_{7Nnc40t=x@-oyuY|u{k@&H!gG?OL=1y6rUe7i!J-e_*sAgUa{ z(~5r}aPqXvbWdOjeFxeN37EA5N7T^h_KGss@PlK=(^dgqK$17K1D0SjHHs;u9acXU zuUMs-awRIu->q!DKNY@a=+IiVU*`XY;x4|y1%m;-^@2omKDSB}QfI^2j1a;C=bg@= zSIFC*y2?dF);JUS(e0qj0|yF086=Jn`%ue==aUolVMryo9P9SW4i7yGcIwNmzsu>POBn(xyc1btSp zoGu@yR(+8V{MxZmX~0CEAr=+%C1eXfHy1&j;plL9>Yg_RX2w^UAW$(kP#h@64UXM`g#IDG1tZMpDTA(y$t&e>c zgR#*5bOGGuT|49wN$|T2#qL6(UCp)#blYl!Y|=R{=SF=PcME!`ShnaVSwmxWM9gxz z9A;JFIFoX4n($%fl9Q0MM0$|8upeFH-03Xq@|>fG4U+JeXhLUxFo`Fm4;PY6s@zb`mZl#`G`~*gVwsZHT{|1bv#>F1cC#_<+g#9`IMa~U)hkz%}NMC|M z+Lhg&xza``-w!&tPcxj%C%PiIM&O-gEjC|7u<;%P26iGHp20D(*K0&6=|vkFD`Ro) z^D7NVhL#Bt_RTPuDuzgjVLBjM2_l3bwoR=ZLv+|JLcr6HcDGmysL&Mk-WNdEIG1@K zd68Ywvm=e9j6QkPF^rM?z`%l^Z?}3fab_+jF*sa7m7;PMZV%r#G(Lu-N~d*yxYVTg z%K%ZHCa`giWFDG@UQokSobQI6uaB+1+%*tS2Up_=$vXoMx#zrbF{X)Pa|rPZr%fQ- zaHGA@HmPeg@_>zm?JG=BmeRJ;5G;KwR^0B|ZcEUr``aC=YZUx|DmqBZY10)q?7=OP zfrW%Jh^3BD$pAq6!*CgrPsOn!LQWvfAkXBJhW30=UN~XaIZyQdJPKzHToz!YK7>Kia z&1<$}b!2OpiPTI>WlND^Sh#dgLrr&+0T@Vwy-R(6TBV?djV7oG9j9n8>+zuRE(Za3 z2bP&}UJgcKHSKA1QuN98RFlEm>x@QmWJ4C?l3){$T2Zl~QX#6=OO*KB9k|BJObtvh zm_H{angVf(@#vDlTe1zCM(9yB$C9TFe{LdPR~?uoH?l}<=cLiGkmg`ZwlWtxHyb{~ zdWV?iC~I|@7NTk$%keH*>!IXx#-qnAn@)Q*%qv;%wJdy!CT~vVAq>R?Pgp^V(^88Q zkNq0-V`)05y@b=`$`bD!ww1EKqbhHXwzB#e9y&tY9k$ws4}Pq3?R4|P*&Tp2F#eG& z>Z&-)3YouXF|ut=)*f@Lf z>qp>U&i^6!jk)Ch<%m9jk7O|Xml^6|L;!BO*KXOPUotOLB3R2(w1(>j9)R~w+@#rO zza(Mg{66OwB0y9?O#juKxZ_9&Ny2LkoQ02 zFEPfJ7>;5bJT&c6i_h% zI;{d_BpMJJlL4%bUV?}9XHnxrqVliiQLA(jE+gkDCXcm!x6{nAwgITRItFR6ZIJ7F zA`8YxtOL&F@FPE5CYCa8H~S$~&CQO=$Q!ofAE|b=7894)YYA!7+g4uA&dzSEU;Yd~ zh`S!C%+Vi0haBqNrBbYn@qck-b*5EL;dJ%iH#bXBW#6hvQz>3t^LO+E3#w-rgKFw+ ziL`k^c9{Zr!PAJaOckc|))~ubAXk9J-_3IM-&5x^h6f!4_~!}qGIo4o{h_{c8(1{JgFFp8IV!W6p44b#8)mPNk?R?)E*Ss(y!H*%hvP-jK9 zq96cbQur!IDAaXw4*a0wWM%bQu5ip$F{+TOo}%RQ{+j`sWrX`RgZC&j^9Nf)nA7z? zjORbds*sFY@V|>Pj!qOXP|yGr(fsv%qyz;erAIh3iAfa{BKhj~2HcT%6>QUz$GDqY zW1O4i5ZgFmXlbo%o*aLO~ z$u0oWqMEU=v}X@Ox7CYCd)iUKpsh8=WBhSPqT83{=w}==smj526ucKaAmh&B8Z6Y^ z+~2;nZ-5MR_gh-!%R9|YXTB5dbai!QT4$XV>IzoHzJH1Q{qXo0&o3r&8dau`|0U~f z?*9*{uGguVtz0qrW8bN~!nyiH6}OOs-d-UdVzhEUpjwkVA}+F(>pRkY*i>T-%y;5=U-0@uA#GfsQ$ln^Z^YCSGOeM<-Kc(O z6@XfM@8rbLLPwS&$2E;XEYMl?I)8kkxM&PKA5>Gkob7tEA#v#wNMXDRC@8DRP}XJr z2Y1V|LgTh~qACa*hxgwg%HN!+@CMLZ5O0i;kmoSj=|MEzQ7X0xGhoiZNdu`o!;6g= zmvNkoZ6TJcN#mtJ>xwTlbmBNvrS8 zWASS6r@GE8%*hU4irksxMcYo2EMG?na~ILD z$VTzCu3OOxS^dMBNV1$w%p92ngUwmo-pkBCn(?A5CYXltUwDSsrkH@l^;Z7Ce{b0FU73+|4N8PYT8oBT`fnGcgc3%9g>3z^`LHy@P4+IR2Nq z&pbIE$F}E{kvq#xiaEZe=q>5nWHld}ah`mD8bdb;qmNs%`$AqD{N0%F{LY#5k4C%j z1k^!^nM#Trl>J0f`9!f`xuo>;fPsq-IJuJV5e>h$LUsaWzD9f_Vs7N$)L zZA4CdeuE^I+lfGGis)we{-C64kM+BLN8paDzUj}(4capTWeU!3Fh7rF5r1&>YxU19 zH?6xa5WhTBH6UE`#kER`bie4cIWZjd3164xce*idHU!kT@_+fh1F!lIV`jKWX;(K( zMrZ@;Y{skm;s9FJ6T=x))e9?BSQt$%RDra4k?528?Y(Qf7unT_DQ_K~^@)j#0&UY5 zbwbn32mKN@jJkzQXyc(?Eh3IV{?oUGf3R-L4t+UU;hC{uiGyw#W*ARA09 zR`3f*5^&9Xo{>xWh@q?F^6RDYq1wLKGB^X|Gs-%7f17as%Y|AAw)Y>#FnZF!7ffI9 zKqnVE3UJ*(s#e--N4p1n7FV~7^|hOq#8qZXcsvXAJ-4=h9UwG^<74?Zp#V*SjhIkp zxju13&itgot$t%%@%+y6J;Rdo7?kd&Wk|;4Y4S#ycfE+^{}EEXFN%!&Lnv{Z0{R#H z`oro$)Z&P4#532bDvg_?8=G;yG{^L`q-oxQ$kes$dxregB)?e)hSSl%@7Pv;enP{4 zj66{2A*1}K+TcG2{`n8(fz#ODpMnHq!rPFs=gLdfgP7PRS4?=Y*qn29FGaHfy*6B& z2xHhk4!jWS9WVGqY=PJBG0@zYaSs|&gLqB8 z2mFFMPfYw~XADkk4Y(*y33{#~q{WjFC}2P&T6pf_3Esq_hI zAlEX^4FpSrZoHZpF?S}KK_FK1j%e=87_7juL0Ou?qdcK{a-8N_vzZ6`lAda`NlbN> zIDziei7uR-V8ZEnm^?Y=tF6laj~7|QrhY-uXMa(_fyb!Wvo#~ zbW|nO;dca|oM4%P0QUzzD6h$2pDpPzD-$Gir!Oh#Ab+S~7zLwBiM_u!TBdDX7Y3N~ z2%r*I>W5!5l!>khMO}tGlmB`_=5B7lroE2W|J#?CELZ)fjhMcd8Ei}a8<^SL%cIuL z`Mg_oWf6z-quTa*VdPc~j}I-;x-r4K1KvS7{6J#pu;S86o*uNH?1v}+iV97F#mirZ zOrR5nO#Ry7)V~D@kmVUrx`2o+FE2|I2K*}}t9WYfQR{aB@Sgbi_?Gqjlm9RL+CP+Q z|Ki?Q_^6ux?MgrYGl%Qje@2YqQr{!`G>^xre7$P=5;~}d$A2-i<&caN+s^L3R?xl6 zNJ!*m@&EP|>EN#3$$z9@I0Dlzlmv&bkI+}b*dRfOBXmJJpDC{ zKU+-|vRGC0Q`+fL-<$2oWzMZe$_1K>{e%_nOU$4!l?!uj&o8eizr&Y2DQ&yCay{7j zP2FhdROm)ZxDW4nWCj5O!%Gcp8^M&=txzp#V5r#d{M{!DcLitjulNs%WjW_>bW?t1 zBagKzGv@#Ep9bm64S+roLMsTs1LkX?uc`4SFU|VeQ2{;~PBt*N73Q`6VI&N={FN_zPJQ4jBms_jdv)7MoCB3MaV8O5> z3)YbVvq^@&Ldn(}?iThw!zfWpdZ^iNE`;0ajYbL2k_dz~aE;G{0>g1VP%-1LTeHDJ zhALvS^g;)(nzR-eNvhkxRf6@#3R^Mmq!)8(R`N};tK3M}nMe@2bL=bxZrM5E*|*^- zMVinb!R+8TG&PIqz0-418fWzyJBrr_GHu#+=!FVh36=!S-g$#P!*iFG{jMsJ#i^%W7xyZ8+>|bKaMP&15H*n} zz>2+WpyAT;tjqigvgU zJ%ihmaNe>6h5Z*Ke@3R_Xc3*DjxSoxTL@XAxGB*QTMK%w8|1cg9USjII052HKx>v= zZXVq#ugXpMlU0*rCodj*`OTYLs&q7zxdsbDa#hjiwCG}uE8wJZ_ZIq600Vq0bewnl zGET^RRMGuam_h?@+w~rt;EA8fwy6)~cp{K)1tpZN-tWaeWn9o?@y~Bv==1&HW`;TJ z5p}S>K5cqEhkkl`9NgLzR=G*(&gu7Z*KLLqIN|+e8U5n^v3QemwQkN{_k$N-X&PNR z{PTCjk)@;dPi!=StPNn{u*2T#ML(l~a{yxtI5||Gd>b@sa+st_Tc2+8vYyT+yfiwm z(VsNF5QY^~Q|v6YO*%BK^UGS=lDpvK<`z{;;A%sT`GoG)Hd=Ns%%RP%%J)4n;t@Q( za=TYjCUTF&KecR9pSh$)|3B2dWmFv9`aKwd;O_43?vMbDySuvv2yTI(jfEh=J3w%E zcMI-LAXww>jZNp3d*Az$HUC+&=EL-tVpUf)Rdt@)&pG>%{W=>B-T(Q`Q>ww6lGPjO zPD3NyuX3WHjsy#o1hRuZn}%N_dZ}TD66@B5hc#T!ppOUf_v1nS>+#TT3%&~Lh}uJY zK)+nJs4e{=c2yKI6|(*#Tc{ChD^9A;KG(xh8QI_&y{HS6UA2S$a2*0VQA03S!@1hm z43!0cbq{@Iq8~0tZg^;E(7N-H@6AoHHo%RZnX#v3&Ex~OP;8*GRaQbm;g)LRjig9; zc;kn=!Hb%?4`}7ThNjaBjlYs8F=pQeB+DVSgYu@rPOPJFpx{P{Ic6Sdtn8P-j!dK# zCnbV}lPE`%XqVL|Me|wLFnZYo)%r;&8Y&R8dAk0n^I(Ld)6R?2auXO%`mhO-BX;Ay zxPRd;F}D#ef+2%rCrS2Cm9YOEy1-5pBLuWg` z_RP&zs)GjS?#v&oD)%e#f*`fL5Vbs6`(NpN;(=ny8Tz7lLMQoe)BT7##tlR5V;(1# z6S#m0#0WMT&~q4VKD-hvLuAaulv7-~*M!~>rnJp;f1?^o=8M|>T8^^0px>x4RWxnX zpeguvH!CiX1?p}2?-FzA2v z+W#pG`exyuQ;Yu_hyVZLRQBaI--a22e@|B;=+O`!t(wy-Jcx+TN+Es)9;TNtl?BdmOLm+AQ-h)$;uPfT7!@S8m{ucN!Yl!NI{Mj*c-E z9Zyg_3-F7Nx3^x%1e`F?{yqJ@kysoiogc-QS;zn5pTRLPF_juLVUh@b=-i(z;jkVf zhE~EsFUzDi0)yY@l3pr~G^R+s0C(R5M;uD2L(JrOeb>yp{pZs{M)Gi zz9rS5Bo=*KCnqO#@weG3ox{TicYcu2nE(7Kl_HH4L3hS_hs9u4!{*MPKS^q=$NQl= zD=OFtn<+RD!hcS<`OCDT7Hh1{kCy6oXNs`2%Jf3%l(W7;^?Fl8{RK-)OMmU`XcsPT z{W;y#sNN-|^xAV^7CMD*K71n6TUothv8oUWg)veDMnnM4M4bN41%R4AqRncnH&iuC zK(E0mCW%Qq$6>Mhy}LU=MFqWBvm^{E5w;E$_@bY2{7aCECW@7ij*oR9U!7wQ*pVTt}X!j#9?~m?+j<0HgQl|JK>wkdD z-FLMj6I0W(q2VpK|M-HlQ{bP1RR7YUmLro3Sxnrq5p2pTPJ>ws|Gn9{lhX0|} z6wnkx_CLyT{@5**e25sz{SNV)B#9@%A2|bm)$IsaX~R>5%upa(T3d%NEa()O|D|d+ zS)xM!;;xnoI#khNs-SFVYwMdS7OqES6=)&Ie-q~UV~@bx8!S$>DziRlV#3?ECh^X> zh5xvO|8iw=^4BG#?#9isEb<-%byRZ0DI9+$lHrN}L2kN^jQtC~EjIKF$6twzT|nx@ zmCk{GSbdU-fFV*nyU+5!)-ST9l|)wpW#cx4_rLe4A|&afwXj2$?@}a;BlSC!`-K$k zySi3kQ3PYV&!=5}+=GmRLa5Z&^~*31;T**MM7v%7YY|4)6qNI*9CIG!=n?GT89;`z zQP2{M3usa}bf;sqIc*ELW#`JCpT|;AxWd@i$oiq<=~1AJ>%yFi@NRzJM|3TVyL6g=Zuw@k`WQztAX^NtHL;MkslMWxK4f6dUhKb;f-6JVwjku z%sRht-a=$v_-Jcx-SWr3hnZeYi!9+)<=1rKEq6Q&KfjAj4f~syRh5lj*1ZFG)3!Z% z&e(zUBu#kC%X!@>Lg|Q?9se;lmruX#yR{JotUZh25g}n?CsWct%za%uGx>tV$ zyow!54^wycgNhP|b%_;s3j75G7Hn=<#=tNi59Q4L|JBS~cH$zPe2`ZZK1+2}nV z?%3}S&a&Cc>%1D~%O1Rb_aAfeZ9mKoRfZq)#L=+-vtj;D6f8bWP2VACc%VN#gb-X_ z;DmOMWyLoXy1gboQTtC@PWgPHVN1t zm_HZhe!(@K%GO5=0kl2kls-N_Qje=lEUm36pCiMTT@gr-#u98+{GV*iNx2{>){jkx zF}5QXBQ+oaXHzG6<9Blj+ONef#%o#zEk{n>X_?G_s84VtXjcp`IFSVk8=WKP@rc!Y zjXu0fnm#acLQaRWAXrE(wFAeVsOIC+btZ@}WV)^?NN-CY1P%0NNO9Rj$T6e~Joz-F7lSgl;3q1^%&+ZSM_MA&~O>+ z^}Lv*-Kn+Bp#V&W2*)bY8upethWUTPkAJM>^VI1_fg^dRh7s5M`9!-&z=8;e=!63hO*hwMo%H6i_WVg9~EJeLq^5AR4-=Q zt!2IEo@~AIi|G4uBZRpy|HMVEF1v=BX(gw|J7FU+Lb^g{n>(?6S z?>AfT1{oD|rQHdL%&EMAqAxOVQ+?F^z{r4G$_W~A{9mxXBJJnryPr`&je$1ya)e4J zL-aRjq$%6T{sOhsoUy*9{#3c_6&RoK9yt=GJ!1CKF(A5fLkH0-V-sI5T>i}9Rh?Ok z+Ti&Y!<8e9JsfH#-xw`$aWz;-bN1zd`zG%Jot~{vq#Wh(I%sAfkA1M|YZ9~`YTtP; ztfu2GTMb-Lam&Y-utJo(F30+!*eYwOQD%6?jXNGIh(X<^P(ihI%G*=Xn=-SE#(;bOgUC{fhWd# zm~rP#x<@8&E^HKP8Th`;AaJ#+=V(Ryo9L(1vVphv(;OpbJZ!xdY&8ytak|?ED*5O{ zKk|}t)QF;=x{-`v4|{R1Pc{~>O>Js&;ZWHE>I?v^=~Yj~1Dt$A`sp0*-3AXX6oj~z zwfL)5$o+z;|LixlgTBG$Su0V^?@MvHEQWCSAr%EgbvO3w$R3B1Dd^u z*JHO^5bKDi2U>@Gu;1&?NB)p=HxE&hEfjwSR-pdO0o%~u*vSPh=1dm8EBZgd&c84= ztDBGuq9|n$V0U~g^x@PcJSu@Jqiu=2JNtF*-Y~Tj0sQ>UrztLam-`##$=Y5<&ujPD)++q@JPNy(IY|^czFLwNSk>l?hB}Wf6Ng(XG%J4*n07^? z+$3jxWIexE!(6f1tc25W_0mMjc>GOXoh73$4g(NUF;@yjdgj{hWryZ`CGYTw zcud4k1I4DKGpZk{gSg=YPW~hGtyOb?e5GI zh%~pNu0h*;Lq07=;Mtmsn)DfzLMpKcXFdeCCBXS8EyoJUnHY8=I-Hk$YDf;JBB%Pq zi~Y&ZfZgIi9e&#z`CtNHQN&<A5}e;)Ji=hC>yd*wjiz)YX<9&+Tky+p-k>s_lh-LB4_D;sXPaHT`r)9&ua~A zezGR(VQi~v&+8xAQM^`crd`NB3XRn7em`+1&%N^g#Zw*2*#HR%%*TlIBKRV!n4%I1 z(;EOiX$z$D{?O_Wej0qwBOTbHZ#N>@jzCbPQ+YjY4!%1N{8WrCHqccN zNM;P#uf6SVNKNrjyYkCiin!YFk4rY&xL&4|Ey0Y7^QT(9^wWRv(@${Y|B2<|x{T_w zZdyHIlOVYZR?VrpXRl&Wf|jUJn%02c?_trKeGs=PXT!|2cgL=Yl|riHH8Rkd(r?r* zVfbCIHVoP9HO_4dxv5m#@Bk_mk{)8IFU_G}XW~Yw#Gs42i!0b`XwDE+zFX0J1hrkD z+MnBPo|1$i)4gJ3%&9gk#3}PVah#n~tvYVoFRnROEz2zna8h-dYipR*>uXbeA4QaL z_&MVQ4PMFu1_twTWj?7yxhMVNX-q(QHHB{Hk%U6>(!8q4p5g51wuVxignF*t4P*4V zl|g(~ypYNWu>H+(;wGq2}h%g7k2kfGkxuQJnbE)$x(`$v^)%v zKk(l0t5lN|ULg-)Jf4RvS`{!t zY;yoijcd(WP$uf_p{J0XajdFLt+^e$FH*7Z=QCEFbPWQ*tenHrMOuC*9c5W%Pk29CI!9wgu!*z-t7tW3ae z2&LIWgHq09^z=p^r(SD2yK?ROJE>@XQbzFt{-|)VEu6da1)%Z0079Kg6kj-8l=ILN zjY+nu@kfoY4h>RQncahc(c zHe$Czz%(ZIQSGRAhC>(e>cDuME1`z|E^PKO(ph$Zl;@pVwf;l#Hb)-{pCd?WBz;rvAReJ9H-wgtaFW^9BdpTbGN-MO(2f1OtmH z8V|o-JT6JgDl#%kP9xRNxY`lix_-u2s)hA%&eL>+WK!fk^!){xZT0l~SGWKxAk2Vd zD;h05Cz|HD9peC^>(ZiWkzpcVb$35l!h33ADa@ea1f9CnM%0qxreLH%dz7NJno)W< zC;@-1onJQrUnre8uWGPZAP8g5yEKBINV0Grhs`L+u*=T{)-_b~9ik4*1t&hD`%`8r zTLEW>I>0A5M4V9YsJx*y#cFARzEj+0R8AvpG*NU0$tcvzZeN>-2LbS4CSg|M@3x>B9IZ$xV6y z=*S+lvTrJ}R}pRLP*}xl9YBzd#^G7V8&S9_@F(?nncXwaH{oy=Sx2s?tlFG28E9Hs;1d z`XEh#Z{H1m(bZk$;QJbgoHu&4clp#6*`WUOhtCI8^$zc`J140Tp2c2g5_uP^Y9v!3 zREpyV@!Q%B9V4Wz(aCEVTVA(JwPcccjRo*vD8~COCyU@EkBaMet^ED#)|x8Di}*JW z7ZJWLXIGxiwMH$xtVX%BV_iIC8wqjdLtx+`Zz~obf?rOmJsBk_+&Lq}xq9pag~L9d zhDzIZY9RGI2v9xV9c6$M(C0d%xQfH5*pV4*>pSN1_zqnn%uiY%YRQ6NBkm^cksh5~ z^f*eYCSH+Lf%KtAJx}U_FzbydT}uoKQElwaB=AJCRmQ{*+o7$j`*I!aO*S+EY*8D>7GGHB7pP_3us|QEse~`J%MB8acVyW9 zSNHuJ2Y<@guQ>=DL)Nj5QVWUC05SL0pR+{o5aKgD3~P7o1Cbq%w6wH9yAyp9#!wa; zlBcuQB|GD=sM9!;!r)}n+Lr4adgeej}_Toqy-E^1_ZgdVvA-ENNfW zK0#2*`W7v;8v$O+JRF2~<=p86W^J%*5PGg6!rQSVRqx(FW+ndoBDafuEEQPswE z4Hrg!y~0%k^bS6E%(6QXcpf*+Kf&T1C5<0yl^*#qO z_FPBN#oJ-{*yru)ls4|R@bybPpQVw7)L4sE9R-A_NDE`Ozy&f9>oa5AXiRQ&MUrfQ zKF(9Bu}EH)Joh%*#dg~dr%R6G2o_c18_h^X6MZ}L@Wj+-(vNzxhJ$lr-nMF7?!-bY z=!8ij?zeUSbZiY*wLRm1#wrJoaiwv%Z>*JgdzYfqY}35Za1iW;NyrickLRiFj_stG zAIT&~k>xqUgqT!^7njc;C|5hLn`rFg(4=yFikz}AUrrC2C}Pd%fr1%w1lyY?^}mmFOq>8q}8>O&*R zl-$Lpt12t5qX*lvu||91I!oi>nn!KpY7*kz{SqMaQ9-6RGU9gD(n};btB7#P(vEBi zsuoPYW7#nCP%8O@m)@fBBK2mQDY04iPPCIZZMT)DI_5?H8|oCw>Ojc%uQ}P z;Mo#wNHRsd3^it?Bqen71^I0ar|~&#j>=mwgR~5C;%&)sg0B&opAn1vsn3OS;!zde zK-F_~;Agke=hif7eYi~?A2`o$g(CJR_=7;k&UCIQe4zl2`wBP=99*RUEG|K-ait?2 zyhP=G@y8Gmb6I#LITXeRm3geJT35cYjau z@F_cJ?Q(qY6=Q}nH?=mIvDz+)WW?KaI#mkYdlHVM<@8!+X^`e zF12d+*5p`=t($ki;9*=b=#@$bNj-J_;SCrKyfUC?GJCVDc zZrOcyoevucqnCyUd zqs%kP1Lu22eO5SgtwvfA>oL>!IO#g~IX16u6f8O$c`^cWzP;@uOXUt^MnR-brsnuA zEuxQmN%NOULpNscf0#Yt#WL^8Pkj!#9$-&A2&b5-{_yiVpU8khE(QGq4@nMlBjl1) zAgMjNh#TgD=9xYJa>x0i=(mO7-Vpe^u=3PU`yUqY@(-E|42dNTA%{ftAeT1ckH0>! zt?RwY74vsm+laHyCoAEm7Ab$pa5@o3{p$pSn{7uXKnPB5?s%}frb6~`Q` zuU4Mo@Ekl)OOsoqj>DW4v6v7bI*5-d%PEl9oL5BQpd>(T+Bi=>MJe7-6$(Gqo zs-Gdoa_k3xUe!n{8`m5wcsSz@9eTukYGS{!`j|~FT43PO!h|dBQ`SpD%%ybdGB>Nf zLj>a1C&ZoffQ-Y%#Im~@b;>A)AgANoq{FwTk1vAtzA7ZRl`VNheyd!T9ErF}R^Gq> zDZ=(cZ<1_S^~uG>?@}ZVL{wpL&1MOARnT6yk?<7Ybf1nG{amOhvFmKrs@1j^d%1;U5@uDN#Q1Eccn|lEzl%0cSVt1InZ)i~M76IP0jDt17|}opSAy zS@#52+@2aWti3-LCFD(D?cR^6mNV^BtL*a%xD@RVEJw}bJ7%9T>ugDdm*cFjcf%Ia zU&tBz>^K8;mF#``^}m4@h{KLanb|#2|IP)F995N$obgd=^^aCXb;F%eWd}Pu%BSF~ zwdfi69*TC?!o21ydwQr!@Wa`ibfpV^{V2RkBAO62oR;wVt#=TDW|~WO3!8omj*Lf9 z;8sE=vg6dJlA}0RuRB$n_8Sj^|4m*#Oz0Y3dkMkIgO_E&AVHhUSz(in=} zcmeakfIkmNaB+Fq@E3>m8+F@DE~_IA(EJ& zaueM&H=G=GmEIoD@ZnjUe&D}$pd+e|px<#KP(l0CfWMu;N0-W;b zpcU#8Rx{O<&PkY{yr3{Ss@S2F8)3-qQ2NhlZjj3B)KX#KYWiy3%cD^uObhvII z`VVS%f7KbDa!+b|BXL?a@8>i)P9iInKsx^-6K`H$gScmZt)Js^X9(MyP?5F4=hB$x z)0{WXi-^xm4*HFl^J%Yb)p}vfEy;bYp895%$Gu88dz#Gn5kT)Vut$!mW={$gSEp=RY}CsZAt zYtiKiH4Y^F3ldLrS@xMIG(Y>*&&9J#!4A#QSNNv$Hm}lS4JpY_3D~kkJ5Odjo_6(< zS{Vw#2j=Q4BgDSG_q&D?cIHQ-_`z8fG|2)~n~D9L))pC11B{MV|80yea+_>C)?bzi zd7t_}4vK)X{3AOAvRTv7?eH!v$G$Ts&l99_{l@TJTskYX1l%|%^PW4gu1Y5nD)wU$X}7nFNS z^?9Wq`LWne2R*?_wk3*>CKTI1^Mkch#KsL222mdX*25$czvNpLWq(id zeuK~?pX&wxW47{g#wBHuA9M(5Tx5nb6#!QH3{EoG890)^RMN5AqN z$TR{oEL^?SGnW-B%cxaW1%50oqdust!PeXcYOGnmOMn;UbhIOEStYIv&3X%4Yg0OFl2=$(%sRX+o9zM#=Ib?`sN9 znPLTj8@|ROA?&w+=I}^~otl#s&EwW9lbjP)A0g@vEu)HLp?|^X)-Yw2S#>Lkh`Ef- zLq`aQas|o<8qC3+GalS+b-R}dQ^5^NBaj7`Zr8*>AefTH(Lrq~xyanGm3aE_@{P3A z(kXp)(l^_InGR9M9ZKRg2|Riu-!}r)i%@BL|I;S(RQe&Nkt5zOOzzq)9`?4Y4y11n z%6k~jPt^1l=sWr8Sg(B4+U#G{2$IOdy=+c+HJn-TX=Vj%LjPYV;J<*lfDK`>k@{+z zhhrE|f|4uR*ALlW!TsI53tul8J*WAY4U{jIu$s=oyvL1+0kX!8dpp`KMb~)TMSG~p zxgPDyJ!Hswr`sJr&7yx*O83I?q>B2&Wj?I#vw(3Ovln#p2nSWjMMaBqeb~By;R*gV z9XOe*!~k4c-rQOQy0nmGE9`S`@H~$kzAfWq$|#_Vz$*_v{aulf-@r zy@rx<#{FJe8#|#~dn%K#_u@1*{8nT^ao3#X00AH_bBJ_FYDTo9#G{F6#y0By4sq60 zva?~7N@E0-(>5X3MKq@KiRQ{O?-#4JMwRa}su@6k`EZ(mLeW$t8nl}Sxr1|7>}ocJ zvoyoI;Ts+fYoLWQ8{IxCXdvQ*NTtA4cW92F7wkJpRx6#kGqKk_Q=CPVT_(Rbj6d$Y z$7la4lW;y;uZdIRpgH3JgRH+nscK9ieKynT%1)*Ivf<(M-gXt3l7V-^TKV0RL=LxV zV0AGeIk&-$4-@@e>B%pJgiy4IbkSKy@T~iGL76jpJl@@!@)iA#9=@+H-4G8^SF(`m zTkLSGA6GVxqi=7^P>>zMNNOM%F@(qeN-zw11 z9xt85M9kSLP<`e9i2N>YgrFy`jsr#n>W=W} zz&)gEH^S{VJ`el>`jF$V9vP{wQof{^L~arjsie@kDk+;A?fL?G1y^%F)Z=H3WN|g$ zmfPd?^5Nhs`!P%373{X2MIG8se*L~QBSp3(N;k)2joGv8OA?x1-+48o)z6}Xbz!lk zoA2Z$k(-=k%kIswU0QnUGAqDpEGiwdn|o@5;xBlA+Ngn7F48z$!;N20W*Oe%m6YFyhd0h-8VygH(*OFxLmzd`Ds0m z;kFV$JbaX}S-H&nIgJIp$$3Qo@?|*v&82cb+l@4A>5`x5aUB!wjrq*=D}`IWj|d%4 zLrp9RHWtpvlYFTn=g3)6W1LU(vbT>rJrl*erE`MLA6taxGc#_hreBqQBLCIpUjIRr z5FW^|N7h8tpJX0ac(daaa5xFFl96%LSTfP8mrGbIh0PGQ+EO{tx`J>E0h%R7wb{n zR{h4Cnb1<$D=A3ZC3Xc*7>Biwa*aylZk^W#GjKSL3SZUNtgHoT)ww}?9V`nJR~J@VsN zY<)is$&UlqYv>B%zDS|OSn;l(1OPV)x5GKt(TCk&zaegOTk zQ}^BIv&4m4ga>NI&sN^O2W3Dh7bTXdrDdKo!oR%HJGY+MqXcQ6deExH<=xb$k#b{7 zSv*c{0m>eP%#G4%3A0;jjo~Rq{vmq1-qh0#awVa&R==R(FW2{qm(K)t@E<*@p zl=mz_o`i#sTn|1Qdp=(q>$vR(c!Pjkwm(TZ*;|#qKtO@{<0_6vI+K)Ts2L4Cd_#?1 z?LjD~mY(-EB?8;-%+=lAbj>W)t5`Pjlq5%f5^T1Ya7&Pf85ETc3|7R8dOI6l|8&>X z_@2y9!A3a&(#Lpa*cE2h<^OY4cTaVkcNYf&A=m5x;=}(>YrXGD*SAd5T-_UzWSdz! zWIQEpJaJnxk=M6J`5w_&>A71=(*rB{$su4#qC2D6-+^j&$)jey>F)&|hCI7=JXmBB z#GZzC`*lRy1upVvtPYFAZtgJ8jz8l73CW2Zin}H_<78rVQ=Wt?(WSFamCZ&`K@}kk9lB*gjd)@pbxsL ze+KXFF6=y5H9t>}p~^e9U{WzTIEXr&**Z8%l+UvvU}|xLsy~C*OLjGHj=ldN#Kk0L5>No-#^Y6hn9>GO65PMbHPG3a zx*Wylx?tX_uLn9Bzr(#?hPT8%%ZyZzyV|Kx9m`0+Bw1@r{I2v>m)JMI+t;7mkuo@f zbT*?IaIQ+}{F0WxnexT_nw`0ZBjO9^S-WZ?0#n)2_6?S*2KBS^zH}WX0;=krA5tsq z>1if}II`FuAr#Vap=x>c_T5A!gqBp&^=McYX?-b$^emgS7sM8EzS#)*w682RxS75l zZCFYMAcCJO<;%Q-g0}*$f=zhnUFUK%ucQwb0*Ev(-RqCw^PNiUEM7;n_FNkWepk9v zOQhd>mm1dLLctteSr`Hn5G}Y1TXBI+9k_De9rAGP?M;S_ZOvzy$O5;>W2lz$rB6pT zQEQpwL>o3)mj!wf+8!G`TGa30osY-D9ZVC0lQ4G!yOq@c6c?GWQLcF9=(n6&OI2Ie=AqU`!;9_?^$a>e<%K<+)?n+UM&FSqLD1rx-OgKvfx z0i)mz;LjeS72u14(m!Kxn=^G0T{sgcKB4WR!k2#scz?%wOV{{|g5Rr&o*?ugv>DwC zFEN#K7RMForb5vQOM=Yp>rBc4r*UK*Xd%M~y71;c8H{n!i|3Ou zqb<~B4`9}R6uVkk`_-0}gF>jjyT*fj=a2IZyxo;l+J+bZfozoVOW6;Jxv`(!Z8BZw zV*TvSeFPdd-n&>ss|X_ek8+`qBS767R~yJ!gIB56FpRIv;T`qMQ(pK(a=0RwVOi6~9`}``kch>CU5k{P50o<8s95IBQmk> zOvJh~?OXLiaSkXo-GQUrQFs$u8df>oO~8J%Y= zpRnKU@u#?sWUJ|^QTo!Qp_PuYGrhcxzyx0o->BgJQ4!q&_trQqKe`Qo1NPvSs2Kb6 zFY}qsB_`b3YM~KOV3uhYFll93Fnu=8KK|sYeL+~I#&1!MGB>eM)y*fDFFsyw=KC|x zI@Z)mFCEDsJlbOt)BN{)fhnZ_&e~;FQE%O6skU$0y0?e)i!=og01JHdzzR|~Y&1*m zsc|#A%8r3to4%UAc{|P)53@O)fXj)`Y8|)HmtW@HS5PL`L~C{wtN{A=JG0d@8?$Rh zIq#2!bFPV>`ISFVXl$$}zs$+^HC6r5rCY1}BvTlo2XoJg?N6A95qo{z-PM#>xN7x% z!Ie(%46GT~cdQx{y2Galc+4LK+-FY%K4GHfJZIw%oT8CJ#Njb0UhyJhUJVB_+40#? z>Y=63zL{}VT7pKfvje;hMs8Qt`EeN;j*BIut$mw-X1^X7avWi` zRU1D?70&q=HDXhSsEA+)N%3NA8zLdyi-(4~rG}Yx?%PvxN4ovakt7X0h|s+diYo4l ziV#=Ak-T4|6FX%3=0h7hwoA|0f{O`zXeb$aLKpcuE=fGXX1yc7p-_KLmmk{|J=9Pb zFs!=V`|}6267KKWq_(U=bKzNZ9J;TMU}QfMS+CFKz-@!jhZSn^5cK&B#7M$953|Uq z^u~Q1nc5OnIp|$b69XHghK>p%d&V`)`kwoNwq=Y_8-POqMR-n*WLfzJ+uFSNi|D%8l`7m4SU72Wu9)C7~$$s%O^7a}pL|CM9gV#FM_*W72N> z3wsPc>NAl`v3>Pg_!NEVMl}A1E{TqXw=R-gto!6u`7xh%E6>_=np|U4Iz*XpuM25_ zLfF`_B*Q=}swdo+WO>q!{DO^*l~oK(QlKaH#{FNLW>V?SeSAs#k+h@Bz^4uryconf zJfc;^c$IRdIvykn@rnwJPlP@ZIj~5;ZkhvN026D}&A##uxs}&7&}b~i?D1qR!u<#l zetu3}a)o(SkL?W~Jq__8BK%h%N#7wB+h)I2OD z%#7Ud#E(oNz6ztZsRrafL&KP|gr5_WfTFUys6kt`G}c@RDT>joj`CBehW(;tET5<` z4P_l>z2(Xbkuen4s$)^fKLFiUF3z5fC9IBW_Mt+)PiqTBVMZThkdbtUr=(6D08EUe zP6K&7j)O&)mI`?kDQtJ)9C>1EGm<#$Um+~VT#yX|J1g1OO|~*p&-ZNa?xFp}|BAWo z+1T5ZpBl67xuCFfBa#1gg@bsp*?6^L19(PX+wt`RJ7}lupcM__G+~NzZIjc}OrlhS zf`a5-J6!f>q7)V{jVbT2XWO8K?QR8DXDgCoE2ATQ^QVXE0Bg`QTWIuCLonEH$>XCF zU9y^oO5nc!uvvhWw9jtfyQ+qUxIfsC<4+X3cY0?38KBd_8n|JZzZRJnU4;hY+LatP z?(6Mam#@n1?4zzyxt4w$D1alm7_HUz^GHDCnpim(9nd1%{E<0 zbOMwg??8%^e7Culi^|J4r{Blt=DjKm$8tc78+x_$v6|sn3nrp9%iGpH;nM$(_}|{K-iV8u-aFrFML8hvp&FzMG%Dfaru~ zO~k=LoaD1*zWIF9#xucbu$s@kN^r>l8D=UI3-;=lAFlMJS05E>O?;e}2m@KZ>yRxK zaSzh3kmH#2#A_olyDTO7$d`twrGnpxzHofBzP?o{~NLk%?P|TswwCf5WVzcIgUQeerC8+#> zX4!R5*R@rA&lN@M^~;8&FUGxNqDER;;rgLxmowjX3E{UbTPRt$C{W&U-l?rE8_S77 z8GEPi{rml&56!34ZWl2id4+hN19%V@$ zh%K9fm`QhJDK?i&iI$R_dXU`g0QL@FTz{fhEI=FI6P3}rZ7IF(*7D2-j58!cJZWc{ zV=7Cg($@$DH%;tiB|8NJj%PC0N_U|ZUc;OM;@H` z$J}Z>2(O*VN^Fzy`K&u&h$n+F!=@K9m!VU4snpv)pjBcjg{0=W4y^A9p4j=Li{{ zga$)gia7c2*x7(56#w&x_)KBS}IO9X>D0?8>O3hnwvhZk#gH zfLQyz<>-bB40b1QWpPf zz`V5UcZ*N|7hT^0)nwOn8^w--3W%V90)ik#q<0koX`zN*RHR0l5L!s0fFMYbE;Z6S zNC`berFZF_sB}W;BoIh)qwo9u_xtZ!_pHUD}xo zP-`tr&Tnm37TcRuXLGPDK|d-Ml(_qCnT|_Yck8fVT}o!5vVBg8)vu(l%lOM>KWtO$ z=AaA33`4)`&Ew>FBP6U)7}N-h#>WV!nehF9pRDj0gbOJnq{==ahx+V!RE@Gag00ee zwrFH8o}^U9g|4LT%Bep*FGMNa$dSd<$mP^*{}(Of%Q_okRl+8;>m$xwXUf5vUDhr!O?KSkDP zYX~?C{IEH;nrUOAd{o~8?Q~UEz>iu4&86yLb&r=hxV4P{$-_ON_ z^9nmxAO6!((YZd=qnn!cdz|fi`Fx6p?pli&+6%tn{I>U#_-e%kxoi_-hjx$gEtK!(vRR6tz1Gx_p(Vb7tnydNC2JO6dTf{~9`fZ1*nAnPR#r67yE!VV3FR}- zMAYM~6Ja*j-|q9*#V7sg#0A%D?=3PBEul4&C-!02 zB+80Vk8M)*ya@-1k|4$}8|sa|_tZfLWaCtShXxN1+m0OA(foGq0@U6j6Pet>@t_v2 zGMe#&7<7Q8-zz11Zcuc!q2{s|ayld*)&?qFxw*3Z2>IU3(sC+(9Wcn6Y?Ldo+;CWl zvUqzciFA+4)%NN1m4i{6Uefkx#bNJs@q=kqJ?@ws(U8|i%q!lRx)H5=>;}}|*_#&I zUWaE@?Nx20o{%yOHQISxJexTmq>`VSPfYRVDVJW@4hb*wx$;uNDIv&)bPR)B*L*}J zlByYQwj5%?E3fL~93NqQxZREt?JJhA)DZ6$;PT!%slA}7S@IjN@60~=j-aHT#pIuhw$%mG6cx30J|svl=b5zcWn&8K6w8$) zDTgs1Qqf;@-X+nX*jOd64SUGWtXQ_!$_w52_>jH2Gb>&kXFZF&9fKf^vd7-Nabh6h zx_U1;rE;)%p%Xj;usxQ1pyXAyW0jrHp)9hc#s-z(>ByMSo!bfn2- zQNiIRY3{%%>2aZwMyE4hAqD}Qwvn46k4D(O@Jvss=vsj>H`g4-y*#C6YPP&U9!yn; zEPERi#S+_E@!32zB!WvmvTrnhuv_w;zHYhuLf~hE>`K#By$kxv<~m7Z^qpkfbGVyh z;k@7JL4Exv>H_-Nd~$-Zolgz5`?U2=aoAcmRw!(nw^j1_>8q+`eLrU?K3vCjb8hqI zQ*_tuz3GNvhC^FqpZPm`NtHYVIS!cC`{yS|Vy>pLzlN)vEtwxc zl9cFEMwX|(-V-Wt%VUKlpWhF9Cs7K0M=@a?y2a9xuweP}OIc2{JfD}g`EQz<)0{;O zGp;FTx|}mzx<_S*)3b>!8h?38j{5ACzQ@I4#J!GO`stxeWKqr*B8QY&~|~Im}JSKSR#z%G7SA!@`Y%p?hZDFjI>X| z?w?Y$(Mn_Uv z5CH59(uKa-FBFC=A%M+x?Ktg#*^n%C6=#BW=L&9gxiwkQVd#4(+4DzRt>SHR!_Dk+ z8L{U0G>smqxRj2Co!i0$<{uCw02YnuWn&9!r*)RN%)_h0jz2WCeb8@u#g%w?I&g=X z37n7_tZutxed&ePKxO=0{Sa52&8;`@S3cHxb6YEZ_z=XYeA{7Gpky7~{kz8Q?h6~{ z==K&f$cBEJs?KYrgU5%7N5qX??kAd; zags2*N{mVLqvx70X@JnxEao?`tw3>4#yH*nelbe;!YLnM`BKsti-7S+@(xGR=U0vK zs)i6x{emkeQh%pV$7&>7w9h;zgb%R+ju(h1z#bUAB~AVs+S!c7)w-&;%Z)I zZmdhKbZOAvRGS*%uJ+`k$w-u?1$8J*hwi0AVY2)|W~+F*0zddGDM$}%3+kED`b|xP z1|Tbi-T)!Nu#MwAAE|EO@1?5V!_jh!B7EVwq1A%mrLcv2w-rt39oiFS*--v+;-y1l zcAUd4>;iYLf7d)7iDkp`+gv3PP)V)N-q+k73VagF+1V8P^4yu{^*k{-%I7Ct0&4a% zcW%xX?>*Y@(BMmwCR>ITs+9d0XbtxKg1BRBr0`xBn);GB^5fm!ky6=0`On&gDKanF z)5`B18^qkbU_)?>;a*>AADyG3{WA`HU;IopwuNw4+;&NGooy;Sn~|H&^IX zCftp<2l*>Mi*{Xp`N(D`;bTJ}1wxaQd^*!?C4-;k8!LO-m0XdqdPOXKRZV3TwIlXj zkgL8|TR=YGY>(W;Hfir9oUQ7;O0BhR{6HK5({KCA7J5}UD17{Q*Fu@EM7}5e^SNGn z<1SB6KS|!zz~*yGUF#GTQ?Cc-cDW^2 zMvb;QC`0RW@&I*|sIB0oTLpF;b5x(V%iq4~H86TQ_~ZrO3AV9l`*OQ#VwuXBpkcg@ zi*~?sx!nEq9{XPKnaF->dcLzdQ$O+|ugu-69Sq{h(m$uK_uSjpiW*?+UdipK#s= zZzi-VU^;^k0{5eDK@Z_Vrb-dr^~_ur)1Q=qK1WhylsK�p;450 z*q5Z;x1zpw`jLZL_S;r56Ltss)CXBRuhME=^0fA{7#kw~sNHY5HM?~-X7krk6|O6g zsG$)r+aZZEVjG?_5kW zwjQ)5<{2jKfM=VK6JvJ=B54hD{1NE7;Jit|sE+-()7ScqWz*EJj9gb58|EosC8>;* zV27(1$(7fap04^dM9gL1>C?bXCmMRD24((jvQ>orXl4<(4LzqamT}XmQ1Q0t;lQJ) zqkPBq+jpWDrn>LqS05e2`5X>kJe`VrY=TP}nV8Mln_<7&bI)o=xGDnr_+^f_)vG5G zW49ZaB^K*weY=YI!TzJx*H}H&Uq$SLDsLBPYOk98SVpqv(k|+Tew`D&rLKz|LT{bX zCdOg1MqTw^{fYHEj(_zh9pMazzXsV!UWD7YH!hY?_awtzL3g;RO(IsO`@sC!FB09q z`jd6G7j0{0=@a`)!(7wXgA#WeF@sW_v~Ns$-8~L-yiWw zb!v3;Kn!j}d$u7-h3c9e{hDFcA%n-@RF%sb^T|}V-`!~F3>qHMHrxGCF?n&}(W6kA zIG4LOh&LCoFs81?GX8mnW|hxNtE9JH7T|ARXQlmC5Fc$`)ecsbOEZoLZj`bOaQjza zHvAvp2O8bnj}~OsYcA!OMO)Qr%WFRTdfUG$c)Ld##TngP z_eOu3{{Am4U<13mJd>y)Q7PRHo%FSjRtQ?os+y_yVZ~4buAA=%U zJIQJ3pvB5U#VJH^q*y-c`d4DYkgm{GnZnAZ2;*X}`mzEJm3?j%mvVUZF1$V|cSjkatURsIAwc8r`^VJw~()Z`}d?GdCa7avO*W?%awZK_*sMvBJv7~Y5O(Va< zuV3=PWxHirMy7`4pgYI4n+x#uXMdC>WPOPFX#cyDwil!_dTVxTWgX*E-?r=b!nwYA zGLHahQbhv}zeKk5j-Muw+s(ucPq-=%Cvc-Thv~UT=v|tUq%Zp3Bw~-b!(OJ!VL>4v zTS?-|E}SL!0Qy1e{TMnC;*w-}86*4Up z?tcJvwmrvbArOXclKZPS{a1kXM{pH4>B)DyoDdw9B)fYXNbg1tzHpd)$6<&h$AooI zkX+UTNAJ)SgZ}Lr`}%Q)H2L#b;kh!cw+g}%ID=r_UgG7e*kYc{=KLJQd6d)B@#Khz zVUk>SG1bRl4x1u1&&8vhdXb01u9SLF?7wwh*>TdaSC(I%y=CTbd+PBm@H9=uohc)} zr0s9{N0>EzHak$qQUA9PB9h8=^8Maycl(d5>b(fFO9(PvzI1+k>sdZyvmI&vc#Szx zEpNh@{b5C5(j@GFZLL+}?(2Et5(lTB@O`Pu1?)#|FK^#ATCY0SpT0{;AL7P>_u||_ zJ(`Ot`=+lKF8V|6&af0}zLWZ?cKQ<`2$NkxSU98pWWra4mZzOD4eamDwuG^BnYbKCfe%=M1y!+(TWDpiAZ zT3YKm-=KJeQMtj#X%jlr%)w`7>EHR5#m+|T7_|t6a+$aZZj&+rRW-$q|Fp8dz|TGW zx0U_4=7q2^#9V)I&KpjKNnY;j!^_t#Khx>E`Nm8jP=)U9r@r79wZ~$dV}Y@gYgb=S zGH#9@G2KK&+ArqfOJGagA5XA+5figNO0c}>QutzdtV$?aaV{qST4^;M_P2ALcX^j* z=A3Z{itUf`3bMdyYX0I%lI;Z{;lA_Db>bUmBR?&lex%+$==AQ{#Kg4;zL>bMwrz|_ zUc9zTJ>8JEI`^T$L5i^TP;7iu_D!Fz<=ATkQMTuv@t4`scZUS|Z8g?KfQOrEG-g%o za?WBD4dCr_k^&uyr}Q9DL*OeCCkELg-rb$bG~fMfCoHr%b~w9d_;vaP=#AYvZ=>h8 z7w|R7=|MAMz?CQ5!Np2U$#r}8rGw(HvlaVN4K#*F$3L0Ke@I*eTAXYT&{A%*NlQ6) ziFg;i#(`pKB?Hr(DkfvzgteWPOsccvL`{&BT+u+zEwcrw%vKg3DKco?4U&4mv)Ml?M@%9#O9 zi8f(cJc&M*mbk8N5~Np^Ow8ktnVBY?>+b46AacbnboQ%V?ALIuu!$IPi515<$#xc*+d({ z=TsD`>AE=NzT}R8ub=Z3L;F%YYJG=kyyKJTZKhQ-CFxAAKGoCys?=|jYzemb__@kV zn1(S(zN_Ebk9HI|gI)%k%Hkt?AvvYQ2WmvqAJrVX2*q!_y2H_>Zz6sZHQMlgmmIx` ztRj8I?>xR*uGQ8JtbFh+Og?@2+d%;J5_H*dze&uK1NQu6f_$?* zDYt&4cPGP2Q6YK0A)Stn=aV&>PLwb0xiyE@ACZg`W~U>gM}gktnfCQZ-xiZSdqQiL zkQ=O-rS(ghoORTt-i?+PnyNw1bF*B{h=`BE78wVF`~G)lS`b0b=Nk@%zl&<(RwpvH zc3r;}OQt$(Hn(IKjY%;m$2}H}{qZ=EdG(s!qv#8QFVw$YqDuSF(_bh! zEC1v@`ZN6XtIy9)oDdj#^pJONP9v2}z8%zZKTdlx4n^$UY%a5G4tcqh+}6$8WVX9u z!8opxyy>_zpH3)6Sl+oeZZ3|4z%%prpU=3aYZ<`er5O3A;YVYL=nisjgnMTfM4ck0#Szg^L&rP;$B zxjmww>zp{@C9&X}EbH0?wtejb7BkL|9Wjokk2Xr-^;6jC9Kzn@Z2J_n4Mod9^+JsL+^PZw^`;1MQE<6(OHH>3owrbp19}saZ^T zS!8V=Zj_rVazK0vJH)-{;}|#DZzpR-!g5s4a(!v?rQKa~&ky2fq zp;W)kg1Ph5kzFqG=hGkZR~B7Qv-=azk-fh*B{AEL_57$AEk=Qf8TMS?ORE8lCA3@0v1t7TM{*aTUlhhY6S4#y< z^HU(WkY?{E0Ibt7d#U+7+`ysv!gN&bJqd(;n@vkIILEBawXs?%Us`_(@ z-|~@>Tc$acy(n*uPBL(HdZDSY6@xOdRDJ~V+93tyQ4lS=?I^N{Mbl)B@8#e0Ff}uPJ--a{OzxF}f%hod*99F;2FAGxNvhIV>oDH96 zo1f2SsKo1oiz&yRN6ktOMJf9$rP*-Kq7EgiERNjRTK5l$x`#-<@{6;8TJOz~GUv#V zN)4CXuHruB$ibb+Z&RNOo#Ea-9HjZ{u(~YMSd$ygY`Fu*@w1jDi%eeDwU_*l4x>>` zKMb}T&a*4McK)h;XvMDl`?SuarQl{wGP_tnnsbI{MwI64XD6G0V!s;~7Wa(?Z|{qP zgoQzci(U_K{*;j$1MqA~)kJU6{&COEjS)6QpxzzbJYeHbUb4~-8>~4?&-nRU3UQ=| zgrCTetBT20MjTtl!Ldc$_duf$*jGLl74GEt{~r1xZ1vy~Qrj$(qs_p-uc64MG2Fn= zaAf&+_TDI~ILh9q(5OCIs=#{gBwT!sCJPLbB0DIzlU zYO=&vPCYs2&HV$UAs1jA^92jm)XyR^;Ltg!YxTADy&~V1Xm$efe777`0X19eQj849 z?4Q_+;e_oNvZQ;)P%1Xtc%j}K#+u|M=R`A&N^fVvC*po_`6I*+Yh^wEP|h{$d4xYD zcXi6ZyvU`>dbElQI)ZlK2MJ0;GVK?Y%UmLX2_^>qM<2ZO$9&NTzl~f(CW{x53dMuP zz+pRwm)$&C@_EX|bK?P7*MfE>eg>xq3JMuLe;(F-DEOXUU3#x4HFJ}CLzjwZP0mPA z)6ubl zXa@y1@0pJlSeSty=$fR@U#KRh-dRMrmR_4m0~xOFGw3_3skoHI^MMyHB>3hAvV1VA zl+_w-;3%YRz$u8bH31dtf9|U?(bNQy^!c3)a}9FGib|_PE`e6ein9`+_X0T5zMRz_ z`&Ncz-ZR(C(01v6RkFyGU+6JFFJaf)Ow5;xBW{fe`sQS(NV(+3xx)3GV~b68{lWcT zH{=>7Go9fJg=>>UP^oau<0TE8dv=4wp*|U?Xy!nyd&+vzs&L*spJQ)(b8+z=s;`uN z+nr7kVGK>5L+87a1=S-fH5nTE=$v&qToiT;_UFWm9IBl&X=gVXXK&;e+nX1)M^TO{ zs*8!KA?eUM2Klwu==#P~YrIdIVDXd9<}sUbh*Nf+PD=6YX1I7P9L}z0dNEFDh5*a!RH{bPp{ z783f|_WX`pdDiT38&-52^{sugUueHfRx-P!b0%lDATG+mZLs|C1cJ5HZLoO2XY9a2 zu26NpW^KDDmm!HGKjWyKUB}e;y2LbVHg-f8+pixwto!4Ll1z43al@_=>)kfXI}TvS z(zcW`ggL5wccZWr6>5_?T^y-j&Xcn8!?tXA&lWj$!-pfc7KXGattyh9{fvYI2kTkA zhZ_A3V+}_3!YOhDVkpFWxyp<3ZoHVf?(B?g7H#>|)vz_@3EFz9ZYM2gloTcOaa`GR zaen0BdzIJ3!Htm$Cqq=@fsUlVdpxI7{nUwQMQpisgAcjcx!f9YcqcNsiBgW!Zc;Sy z!4Pt$;E3#~PS>I;cg4edQP7;qV zOZBL((e`8C8Sqw|97;U8F6kU0Tx)yskL&kcs&!@B6E-h_9;};t_Pm(Yx&0Se7!j;= zYZO-coUVGz&c0c<|2P{F+`W!d04*<%f~$R+LJ|O0}3Cg9mB|3I!9W&QE8qd0Nt*lkU?jO z(6{6giK3TDqIS6(DTuV5zcnZL+Fnt4^Tflzr-To`uTcvmt+@2NeenlQp2WVWm+*AVYUu#fPCDjLH)MPS#ehxS>U5r|%mzYyQ3=nv`SZ zeayNm%Z!}V)64s8-u`pCd;@6PF=9Q$5*Z#u1tC5>!rAqwuwpM!BFR{4x?y6dE=kefdYvPR}ogsNs2IK0^;{T6}Xsp%K!=8!3#3D!59 z-BQIjz$V`m_JIbjWvk3zg0g+AdByjVlStzT9f$Wd1jI!x^@)eh6&Y~cqo z@~GCP>TUyaPq=_qIk`QFtAiAu6|#E2{(LnInF?>p_(X_fAApOlcYx4GyAAlyM=7Oj zHZ#TbhPc(DBl$w`9q8EoTzxJGdj988ilU-TVccBUA%UsTdnhBi+IxsN=B|4Gb-tdK zQh+Iu;ZSebIN@&9>|_I^^YZLaA#m%S(q>8t>qdY%vNtXJ^gZu_MHrJrCia&Yn)h>4 z(%l0}X4iQUBK^%P2AsfK@@MBEfUlF>igp77Ai$ftr-T^!ouY&E8`a0@iQSxj$f7d1 z4q|RAvM8GLaDR%lgk=U3f849Kf8?{+j$j~@E2-kcMGNyLX5H0 z%%L*@nQ0lxXU4fJ?i_V;+?r(LsIPM9W@@P1WQIUpvgYJbMN8<{asD=bNo(Z$nn@#! zLqkL(!~Sjb2yrcyCQHIee(N8(ZG^*2tZ03^Qt!@Aq(uJG;~H>e-93<}9s3bZ9FURN zH~}blDxkT!|A}1$rU&j{%NZ&PEwsnp?tX<+?wyPEF?<_7?mGGwLz*bD62)dm_Kf#{ zM`^gIDq;UvxG05BVBS*F*ExBN0bhD2dLz+U3bcO@X-tkQ)-XS=eLU&%MB_KQ}4 zSQL^V1BJi*Bz8}H)%mWFi7~Ok&RJ7ucB}212MtlYg}x!2xEU33*JD-W%tsD??`R?; zx%NoIpEy!J4}WYE4vT_YTQ|S3~;2CduQjGtBI-=n`^EWpn{?G;f_CkxG5_o+?) z;j`PIwb8HZE&e-Qk#pe0FUdVER`5i!m1Nm6FYK_qg<$0Zi&jF{By5zE6PFaQpxdIH zE}t_+WtX{fW$Fg4ujtqq_K{z<_;LWw>6-N&KSkJkIP-7<-n_3X$Yg94oPgXu!OJ*} zD0Fz2?HjT`;SpJq;Z{=7bc8i?gn1r4Hzq)kX3!qe%+TVPmVb!oqh-y$SH zJU#LcN=%t@M3-|s7i^(LzL7KFj&&7h+BiGCm1yvat5s$9s(yf2mi^}*{bA!oq|0mYh?O3d$BV0k+=9&!Nw23l}5i; zk*QVuBXFN9(hf;8>Bx2aIx*-I@jbU$d0HZ^Y$JK6@MRw7WNk!%dq|1wLt9cy*ZaK^vV>LDsuMc=fF>9RZ<3ga=+}JGcgv4uwt>7*T z^PH^jj}!9pieH;|5|k~wg(Hvk);lfdT;hq#-crBt$MRdViH6o}w11?+!vz35X=^md z#VUQylEritjc7Vqohdd5{V_f}={D`lf{=fF=U!5$U|DAT5-c805Y{Zs;Py)@TA02q zXr`bwXO+7nA!D`bz@TTIZ62$+m_DHbMVRjpT}B%;L9XOl1IJ;&8*nf=-fBPi1Up$< zy>AT~nKgCp!G|taVE$Yzi);A_7@2ym$QJ`6M=8IWtYC67v!Jc-R;&gvLQbW)B1R_s~ z&g9;ywW@n)$aV9wp?xDxFRjuc0K8~X>+5i@ylh2L#bv{$iakX)- zMIKmd*>)k_9T`5JkVvhEN;#@WegGY=xf$)ZFIRi2XM{JC9w+7mCeY``$0fkKI;Q*w z5hz95uyAG0A_(HZm0va2CBty^Xt`jD>{(r}zCn8n?`314`0xT zk=XmNXjN>i@<&HjD~Qq&FQty!EbSZEY`2Rw(Ks`_kHH2KIW{YU`)PF^&H9?&J2 znV+M&%ediaz4ViLyPxw_QY8A<@>>~&X$6Ypk?3zztrsbcKzlH;ou&L3APDm(2aF(tfS6V}v8 z;*C}i-Y{OYE-&m(C@(OWzM2q$R%yd&x%lf5UhihyZj^QX;}T~+%?@57n>wr<9Z;Tg zu9k4~_X5Ln`up&P^7@(Fc=cyT~{qhK}-i)7mQvV5I!$9KtG#b3HBT7-yw9 zq}QPO%yNSOmAGYW=BzD7ZmUMn=5x1?V(EyLZM9G9LqD?3vrSneClgqq=Hxxl1A>j9 zb&aL5N4Nq+P7u|D0To(R$tddq-lSiJhtS{!g~InxNIarDr3aT67jxKlFX%*;j7f{IIb|Fz3_BN;Ov-P*rNAItj(C}jr9A=A86rLZboi~esF3Z z9rQQ)(thxztkZA%Hf~fvQ*oCAgg;7^vf2Aiv8Q0U3^l-V5g=45#d&EHfoNo{K3v-* zP*Xj2N3n(G*!+YPL6%pWMS|qxIV_^0Nb#U_44l5;lvho!Jf7FnY=AloHylmHj*!d~ zA{4y&*H8S3?D?a=G{c!l1_$|jyE_a4$?p(B-&XVK=&F+1$|~f%!+0Bq4=PPYdhO+P zzwmu;X#C5dw$U$x^xtCYF77+<)j?+ORHpuiAbnb}E+Uu7l@ue-(%Lu46|je4M>0z0BXp=Gx2I5z?H?Q8hP$cR-m8m#8_zwS8vOm314r>rOX{gyZHB z-zI1wlrH7kH+Cjq-Sx+2kZ1Fhx^KFt&|h4p-_hTUlQqJpf)?WyVn%4*j$c&t;NANm za%ItYQ3u0;oVzB)-I)-PEGJzXy?t?TtgFf4J9_Jt8KhvE@%Z3t^z(r_&jH$=X5#C~ zPr-zXP`;r*Q8$LW@jVy_^bQcY+W0zUOtks2vW|29CLd({c=W@l@sPfB@2uvd4R>J+KjgJii?W0xWuK(P{zgL#P)Q97!#-j{!1Yo! zg`iwXI;?H`%fX5*yAkrv(#u4eyInsFFK=O~jgcQq^k^vU;V}0Yy&l39k#WxsknYhp(1dC&2ryR7^Yp#RDmPENn0=L7(d zq(O?2x5isRBJ-}@%xj5;KSU9lN+zo?pd~TeQQFOxMK*$_$6&eNHBl%?7iRnTEPsNvoj0hgt35IRiv5|}`Nvb#EhY8Q^MoWr*TNN)9 z`b88a_#^=U9q)(F!?aSHZp?uq<{8LxOWd14~0+P^v z3j88|-{K1Oij*C>KHW`;!sB@od$KB&y$Cvp$?jl-HZfU5s(V>}|Z;F3#Ib@0R@=>}`I1i^b~f@F7Ll>u&C)Zh@aB=ZDy z!!nN)T1_L%f8t$@p6m12jmT@RW*C)XC#_M2^wrRElObalQ$=e~s#2kfcuJ9hKOIQ9 zwZ1PvdXud(b$;pirF2W=7x_Xj!&F{Edqic4G~Zh4WUjF2olwJ` zzmDcX<*p?ZRV_OA&3M)}-1GqY=8KkM_dE9JQRoWnc^LjjV(vJOaR4pXo{2}0VYLrFbjsSm0>wU)EhXG~amcQPokH z>E<*qkA|!p>g*9jRlE%BG^Vn*eK?D6)G`j0#IP0^GuN_jsCuYKF4Ns0MY@(U@67|4 zx=HWiG-8%sJYk#>Nl}9pkX^=4JJx>`1^}MQh&Zowyh8y`SM~pBXrK;@MOG~idY7hq zh8r6VjC=G=3%Ex$wBI95#5ZnX;8Sx9?pB5y3@Qw z36ydfeR@`U3&ynxHZLQ9ty5fcxZx*LNBAgZE$C04)vU0n+U?uT#(|RTJq>jtks2~# zv!1K?DQrMG007{1@{bTRl9c_%2kpt z75y4ttS#X-o8vZ%6)M)VcDv(eFtk`WWj?Bi1d~ZD-LEE0r}lHD)(gstWRrJ%1@Be4 z$_v}YAL^SaH^3IL_H#xGwNGgWqgemHI==;KF#QD(M(L*KiJvX3F_JvezbNm zI;%|0Iu93ADAXv5*smN>z;Y_psA;6bOa``85;~V5XX(LS&&2gBYUcbMcV=A~+CBo3 z2)s-me#CG*?Cu2Cq>g_Ne+(_^G&%7p;PhiZ9)IriwoR(ooAm3pG?em8uQGb(1mKpY z#^{e|kgC)#Tc@w>L%on`QT8;6YhCAU1Ja60U@WUb@UZrKS?WwQBH`<8#}!&S%EC@M zv9r^SsjNt66-8B@zX>F`Pt1N|SSEb$+i1;GB2@}vfS@7^ELcE0X-H0-OUUkZn2iiedSBF3N7$sG^S~3sBYL7gBc8J#XK1PHA81ALnQ z5C=~T{!Gnqn9*;P#r#e5OaeGWfGc$F5l?LvFRv=Vr89cf4g$&OT_1*9gOi8d`hWsG z8s=mKyor+`1vj4`JT`6>_;UyF^H4}oG_{NT(9aKnoFJkPgZ(ko^OT)-Vr$&+nBrAn zA16>8TR7Q5W2XN6LW{|mr1LQ*RBd;OZ=LOb@@QH(?VG&g^A8y8KMw;$T`LDOxev~^ ze#P>PNUU9ta{5BYm*OT!y3-{Sw?w_}4C<9t}TMde(sVcJ+s z|Lrq9f8sKK+TV98v3H`*_{%onTgo|aDF(+4lZ#_)4NEB}#l8+in~txj zC>Gowfd$QI2Wi3}kppnX^iM8Aq{ zKqr=m>XsJymCxkNiH`kO%=5bKCZ>2gdmAy4#5;`xXkIl55oH;qvX)7 zu?hvsaYy?p`9V>RfFewjbli(BwpYS}29=xta_8p~XUk&TwwH1s(OzB|ah2-ff1dn* z$fl^&-MHC{()Ns-!SK}=m*lI8+xOFQM5&NZ26r@|d#k8YF9g0;V)?MFhJByL!~6a$G$Z4aM2)6I+bRsRZ8Gx*-bLU~;B=7b3 zqVa+a;`zcN>+DKz`~;hS6g>E(!&2&}OkEwF^Z*p~qD|w{;gs3Y0g!lv+!HMp(XFdx zDq(2f!}9z=WnFR;=Xbtt3IID-+vPq|iD1NA{zH77H3RL%e+EQ#^m)}u7OMRvxrz)> zK9HjrnBFjUg-CtIk|0!>AzvB;A#GtxW64}~)9g?k+v3r5rjqYLuC2POuW`9mH_WU; zdQss$q`Lbfg@*j?7I*)!^uOU;+kca1HB|?ycfc;$t)ggUoyOezeYFsp_?NZ&mA6j8 z-dHDbJ`YbFQ`Gyi{*B_Ac0f#U#BE%ADLwyr{n6AFV1gcQgZrnGVmbD}QpGaDu z1OTsiJD}Ij(@Bt$qf$nRyprI6_%dHi;)XBylZeyL7+y1Z#PGzGY>A4`d*!-!DWGU% ze0Iq?Vr9??Dv5BEUVLd+tb*Y(VqSthP*JXw6BWh&S<}>xpTP=UG)YxfIoV-D>w%I3 zQqd6Z;y=I(rd2(os=d22&PxR;UWT@_L3n8^dH?lew2hpv2xj(hQoJ844lMq!lzR#f zZO0$ZnpZ933tL#0IyoGkEieH1=U;LG>MVZl$_)J4>Zs%VY9H|@8IMuG zyzvVcc;$w@%QbtVfqh=r#w=gMm8f5fD`bo;KakP~AB61JfUbvXhWH&0j{m zBKpr|C_;hrp+qVs71&h|o9(jR?sQelau9V3e)??w!3c6vcyN5Su#*#Q3fw$PQD72g zQa+n(O*ExtEoW(2%Vxp@Anm&jXW2t6H|?vP|I5DsX>`xU7tD+_@D2 ziVc-z^eY7CX`F*&8lIOJ`4QbA8gcK1O&e5K7LQXhb|tf)dS)y%puuw3)N+x0s_1_Q zW=UwfEQ(q({k47|uj+7ooo($8Ap`M)eDQ0hh;NW(?|2r_xS3t;9F!qZ`|fr#_A3~0 z${NubRU3Xay4QOn*?o+E%m3n{V!!E5Ya>JNDot=d`nJ|^ZZ~4nlkQyu*?sNV??VM9 zUyS#_Wcf;YmmaZ=n70GYhr4Me9=n##)-3lxfjbBw1G5$82L3-N2JpkC@dGn3qgkK=GY`D{VCTg`pv_grhMo!~gW+DM^#{86uDSIwa4lj6L zu43ec1s1F?G&VN5oUeV}fJMzp;Y5%az1>>svEp+MLVeqsDMO%dS(sO}+IEIlQS{k9Y&$yn_{g zJO1>&gl?Tp&!BbcBe^Zy{rv5g8f$7x?U_ZZa_$-Ajh6ars$V)-yHa-1k~>pnFs6-+ z3#hYMhf`wPyQXzEshPpB$B2P=1a728cu-t{=qR0(9|SQG>qAE@2cl)R!qwbN4T7{gs(1`Js0pp$<3-+G=gyEKPWbwSY11*gehtw|ut$zGu)Ip+T zTMOY1=k`-+TbTY;WhGaszkbW#cxSgEm1Z!pvQS?B(sjyh`Q-6g-hay$?SBg0&B{}o zJQQrG;ETNv7Bp+hw`W|&@ujV^Y(rRusl$|SoNj*Q1hKBdqjvrg%%wp5J3YkNMRfAd zJqROT6B8--gXDT|8T+_rZ1eH>bIk-^{9yig%@7%d9ZFknEHaRl)^GByYd}h=@kfv~ zq9H;e$Pbm)O>qy7dP$CkBQ(X z1VH8bvztr?AhenteyXBshKV?q7v{g7$677#Q?MZ?cnM*2fWxfZ2Aut3sk z@i53|cl%VD+?6&u3@j4w^i)bXk6bq+6(?`TzoO0TGCZ4chEc)8wFCAJN@i?a>gf>o zEE#|MnE}Hv{*8Z6Ysqoz|M2z}P;o6?n{Wd`f;+)A!4f36y9f6W+}&M+y9GiZI0T1A zgM0Ac?(Xgmb4YI9d*6A#Z~mF}&zf4j7Tt&HKBubouD$oOpQ@ssKl|y6E|K5cbd1se zLP?t*h9_h3{pI8U?J3}r)mfh(VO8%2MYf+mELDs#u&jjND*t$X-@si$W%)#!tH(X= z)k4cXSAWVZie?%)-$;BF)^yG#e;T9T6p7WC4|be<858p&Kynel`-eB9))z;Yf9|1d zDnkt4Arhku-_^JD-*!e!w>MB7XnA_NyU*7-=NUD5HJM2&^t|I)xb~24UdHjX6LK2L zdg$0NW1Ld%T#kX4|Z*Bf7^FJe9=b(ng!)qGn#&Xm>a}g$roR)o~I-hl# z^sT@~qRFcEOuo2bi6vs&*>`6TKYml9Fk3PocCa4-7O*04C=pyBUTz>jCwQ{oun3#N z4PU*#v)U3uOi}JJohr+|NFN?_7%OU`%vWE{a_G3Na_G`%caZRFPCA_!SY&qkK_&f~ zDqbn``VesvhnCf}^C)brME-Mmd3jvCW8Q$9SDEDMxrqg8{~THFUtzl;0;|R%a?w*C zx9n$BfN4wiD^%DZXuQ1?8IEZ}iW2w9ImPPF7d7 z5oTEfVd-(xy~{*xt!MaCWZGX~Cz&d4_9uL&PrY3C7U*k1m<6~pn}5%d91+9|+V%Tw z-}i7+jme7t;XwUn3K$Ji$as10T@L{O%L9+x=TaaU4*>)#BzEfnrKT@m6SS`1fDCG3 zc~J`m;#bmZcxSm1vQbSY^H+qPg>x0l`8awDxaLra14IZwM_h!Wv1@fbDmBg4n9f7} zPo0BnH9%L(#W&q=qwfS@2%w8qX1*o5q7@5fu&quWW|44G5d z)E(zG{fr!$G0r3NflJ37|0jL>y9|#nulNJ@t)ZDdaEbMoCICT?_Qi?Ji5P7vWjKcJ z{Cx1<#q)DVoW0#n(`oX*n((Ahu!hdV&+q-;JL3TK(|MjguNfH1KMHq9c!2m7p60w?;0DNsBI(A)*F_UFL+nlfijMpJ6k<_x zjHF2k9Dl`+25ebm6|nfN7zh*dh?K^c#P%3FZ&E#09adUTG|JJ+ig*<_^Pda=+mqDi$;HHdmgUB=`h#oh>p|mrC>9g9+I^%) zb;u9Cp6_ZLsrC|~%$wMb|0n$8SM&}v{%-gQu?phRK6b1jdr_;H_mY^m$UVp-&$Li7 zZu-Dtp3@-MYFkMxm4sOHrVF<2aNyCT%@^x^b+PbxMU+CdInl^!wWIv~Sg^gM9uN*t zFo_VK`2RihO|Z|W6=2Lck#~KS?8_I5V>Q# z3JJVt1-$pVIoNcm#o$2a$%#j;EO)*I5=!sB$bU$GKSLtV1R6ImDL5I@AI3EvVm74o zy91s3-*)8%19128$?ED!zDw@nMC&u9Hxe|d8C{&0L*e+|!<1|W3AbNAwvDIlE}UA8 zBrgEVY8ovu`$;{Yl!ZcOmy$+i777$C%nrb7{7NHjH+ds`EY__uEQhZC1-A9W?UaX`pW#Vr$(>x(wacFEwYH41*Msv5n0VEAnm&GAAw#Td2vdmv2Vl@zz!)yzSOI13hROa-0_of88?8YWHea% zU(HEQx2d-705rYl>b_$`$ZeNv5DAkuB0cz;3V@9F@cD+r1!CMCE_%po_1h3&HwLsHHClU9T|NwG@ha?Nj!3i^?X+mdI=CBD6{cc^uG zPgzh-*|`P+?XB|pQck6DsFN}8-g9_10@*pB4=WhlkN;1?bRsN|)4--O&h0VeekFR( zdTei=53=F&#TO_9U?GCJpM!mUs(`|cGG_is>jTqgHOo&wmLGl*`5~WEsD6OS5B7EIgdm?9`QHY1@Jen1-u+7yu0y~YNv;sGICK< zJ%M}*>Z%(4RT#}IrYO_mjeX9-!BZ&*;pS?VoegYVZOq9Zi1#jwUfjC?Yp9b+SmU0C zsgmM>drhMoPRVoCyWeAV=Tn0J6_@`5Kkn-Poh7pu1e^$!tdgPke!H(8WtXoI0_JpewX0hjsCCXH!gIc_`;&1 zqCXI}G5=Vk|Ck&8U~_-r25-2YMD=&Efp}tI{4O;h!1ej7eDDeMLbXatj1vdwW&ay5 zdo_2ax$g&0*6Me8`e7fWxr?vdB-ne-6c`s=vCnS_d;ISs4cffK%5?|Hho2zv-=zhb z`?H~Xj?iBpK|bZSfAt%1<=;BuDMtPCohK9YyDUL6pK11wd^ZK}ruNluZ(&D_rR!o4 zdPx%VTwK4!N{WQ}5&w;l?`+Z*>23V@t)?XtA#5;?dA(QPVQ!eLNmi%2x|y4c@wuyE zq~yCzNQ=$!&K~;h4W=lS)1ts$Gdq8oMz`Q5^$sgB$fJ@;Hb1-Z)wK(=2?j+ZdKV${ z1_)wBg>*1c^9Rbx0eKY}e8<`yYH2kMGYUG?uL^G-uLRCHE`13in{lqDS9TewdTB9-MvIr({54w!ZJ|9gxIy=3r>dI;KwlMs=wgq6JBE zBXY#DabV20xI!7cuv~W-lk8L=v;Ov|zGuzEUI_)%B^No>);W8R-yu z7?OzcEXqIKFguyjt!vVMwb&5j;^dhn1}4lFNl6|4VOUtTGRdvkuq!?9GCBLczu9Hk zDHU_v!l}H(W2@P1=j4?@YP(eBQHQzXYObTh;NzRI(Cf6Vjk9XU`3SHnHIHXaq?oDW z%vLyl>d3efTpNJ-Gp|OGWlg z==n=qN5WbEw6$fe)ZX*)rmlUrjq}?v4xVmU7uD_iukJe!`EMKszoaocFEB^AU(2M- zMSEITGmk=`hGDLs?d1mDFO05#=5lPs$1%St>MxJ9;;+C6>6*zPhULr7H%1wU(kM~2 z`nb){pKS5?eh^6`uSCduc;1-kWb)KiG^ZSpkCm4CMt*26@FNYK3uqM@O(e z%UZt3O@)%#k7kG^qtv>aF09F2Vw&Nf+9PY%beOkdbeud*$jHAg0IfVMm@v6>wnq6Sv z+_-@9)S9?XhrRdMT1s(TZB6rl#o{{->6x8uDdGv^K9^cDbXiHiQ-}7KBhH8Klv=gG zp=<*~TPWU&tM-EvXst4jpyxkkzVn}|u#Lrtjn6(tRmAO)J1V8DC)L|T4O{TvxmH=- zDBa87iW821G2%s+&)8_N0rQ&O<`HpzWA((NC{=iKyKP)-Iia?j*2qt&!K|{Xk}_6d z-L!FFke4)XvPFq%J}S)PG>R~j!lmR)sL|s<(BkwY*jKH@jx$S5J8JR70nt+p8my*L z%b1>L_V`FQPB9N(PD8A~r`|W4%7Z3G(eeR4h2IRewut7HcTZ`@d2^e}-=}?BuD{tz z1OmLkZ43Tn^?E0>go1ogmS*pyZ)0*1JD;5nruskFQZPty86!{jL*eZHBt_XqOg)P6 zf!}OMZ#t|VA%8r`;dEGv9%`7WGYkve^eD16n=h8#e8>>d<|~*`yv-kMZXQJ*Jw`{A zrF@?0Fkg)~v}+{IdGOMc{RneBV=~0QLXi*2i~o}hZqaQd*oYGm)j1W9MTzIzN4Evn zFwXJ9?8^6+4yKERV@B7LH*U{y;6?PPHLqgr>`&vob{|cb3y|K|?@{uMZXm2*xXCoz zs*_N#%bw#El+4dm%^v!qEu_rU_GRI*6xt?XJntQu$R8|lPV-z`5=kjJ65}fIuD!>;mSFjN1QpcI<@1wm!OX@b%#tZl4-|wq%9^Raen=HHB z*Mt_Xkd?WbRgW)6OqdPKN#Dw@x=;QbZ7A+{5dK;qS^;sqJRW#RG|{2znf*$LcR08& zDQq%<9L<$YX7~pOG@kS2bF=BpfcKRLCCdoFjJ{-L=DrL^=MnkrQ_hB1r6N)k==vT5es=_3SII`)zC%=90?Z#%v{JqUPV$G4y2rF#?4IMPEfd$1es^ty8R~DB& z>}Y;A8Gk$05~kF~r@Jg_xOW*>#EZwVsw$mYdAL}*7%}4b zhGsW-c47ER6|8{al^ryz_U-nvW-?YXEKEsFEpNqh)7mWAsmg6UEgNm{G2Kz*Gdx1m zusv8>-mhYCeE0)Sp9)c5`PKLB_b-z;j)YUr?+!U_t_165_?RUYFD&0Q@sZeK?RI%} zZI#EPm_E!V6n@`k=O<8`H8xulx<5~&_Zq!f!83DGus$a~Nv~sDC%{LSj!_ABe-D-F zrONkuA-ioX$;{)dwr;(w%VB@`13$8rY983yI+u1~!LEh-uJZe(>D>=lM}ws7*!Y{p zbocYAFKLx}vW_f#>+g9UetL4g2}|2pX8ruVX;j0~`c^XF;jm;(UG|<+h0W+b|Iz6& z2<8r*!5ugj+3LZe4kk^!3)V_uz-thhJx-2OTQ%m!r3D{uHQ8J-1&tAqw zZ4~82h`Rb_bJ;sroQLy*w#G2Np{)DV39(TXQ`vC~$GTE543Asw%v+9Wm4A9qUZik; zIX6BC|Gm@mPjBn5>Y)G0jROL)--V9pq7+kMe}Z z0a?P|<;m&#zkdIJ_v!v0{d{oCVe?~&*Zoa?O%3~6m&Ht_g!6)HuG8L>?(F@@zdTM7 zNc!fxaxM3LmU;U@9vT`N&aFW<>xCj-&l{7UUl?!hP6sXP7nx_Rp8wTDJ`_hkFl6)6 z)A_HjuM6H+6{LEcNPNr9m5TjtIh$h+Zd4h~ksj4_p8vMc=sxSz`~<)JE+ml31xmw( z;HH9687^t-hU36gmzC%7pFf**MH1E>cjBL~M)B=@*07R)e7Lu4)Q&P#|6E-CXPEfW zr^*e(N}6uWq*J-opPGXGS}h%Tc!fz#=M)$uyllyMnrS!hzsE0lBuDzI!}WTCd1p9o z`D>{JZLiu??+4e}uh-~*2MfXP`;%D48(i(xKfjFX%5vJD*-y*027JxGo*E>ak(Vca ze|tFzOYD)(G{~)3{Jv_W+E@Or;6sIo&-$)C5J?f}a~8WbaYDOp(%Z)( z5Yb7vastthHsmb`(~Wz`s4*Co#tJzk9O=#Pok(!F<`yiV2faoDwZycK|=_fo^R_SE!qXN`C6sjsWQRFrhLXwc$qPR+b#BqJvm`UC(J!H+fQ}O5yh=L+WTodBPsU;Xw2HCj*gM5TZW(DjX1R)i`>M6GR=2g}q5iw@ z@bI^by(^CzNKZ>9{-f*|t8+bf@@-ks7U{>o|tNmOdg8Da|b#n zgXd3OePcHyKVY#K^LA5~<8|mm(ybP;p$kP%;W$`3PX_;`D*OPGRvO$cqiHTv_{ zBtnAtq}?_Vav0`!x2wbOZ|x{GEhG2S3z!xrzkZs`A1beO9!GIIZJ#cfIe;Tf!dpOM zvJ3iaMasYZ;Y>7JY`xI2ZsM(d>=L8d60rp`loF4w;<9VfLk(5+>-nkQ+GYF3eJBs* z65Is34iW&ez(sH0>N=y-zXld|7icHLuMz)ySZDMfIqd}b%=S9|DFoq~>gF$|prS7H zd(j(!sO+y)U?I-MOBF$m&u!Z?nVSCmk09ep;?NFk>TNnz?5q~QKVjB^w%5J zoR4hU#D%^;|8N1I%qOffROSaq0^HOpjEZOL?ucAOUf|>NIq&r;v|`;za$k`W5RE?i zoYi)n4^fa2B}_U5=^{PYw5V>G<23Pza+O9UwG){kyXO&3iS_HEumtgp5nRaq<1)LQ zn7zvzvw_*Yj84^&f+N=3yf;%qPgQd{Q3~A_hdSLQJ7T!taVhK!r@?0oMD2G8tsbMe zMTiUq!~6{ygA9o6f4x}z+0Jk`BGUVjJOgzXh-kugM>=mqv;v~wk#tN<)K0RZZtJ}} z^POS!Tqw`kPQNmnp3KQAZ?#pU{Hq84@us*ydH7eeHMtyQWMrl{JoB~6R%YR6n_rK6 zQV)$6vk(M>hbHOdfRm0RR`^!2h`YT2oD0U(4~cfhg36;qNptTk2-GsEDGm-(tC^WYG*u}od=@{ExI5* z!W4(njVa<+(bUPwT8gYXrJdbf$n%{Hg*?GK7v!*^h{Qlz+l|`=6NtwKcj@$K8D#On5Me`ho!0c)#hhOuRbKyNWp=U z6ZR>mjL*uf@aq%Sp~@euZ`Y&`CG?IJVMr_r>|8YPBt- zOxxg(;C^Narq4h5Fy=#9FPb%azX++Jl$S;kw5W>)7|xP509`7DUCb_GAk zlbu~T#o&eD!XTQ>ELv#X8=+w(zs4Q-!rC${rd+R({mlv;6Z~M?Fjbu-?NM~?^&00T z`*(@>VWXE2_KVAEHD;`CUz9b^&6@?aT@P`DiOqdVFY8S!69-L*r5{4ux&1t!MBIK# zXupN`N%EgYwlrww<9}Xua+&AFn{sT2dt*tm3vX@q27aen^iY>&ac|KJ00Li|N1@*rc2kUzcyRL=4eQyu_&o=9kIJF$7uorQ1GSXy6eUVyP@R3f zu;qxyZGlteKSWBtFcSedj=GhiGKVDMuC#js#2eTEc%Uu zdIWW4M^UREhf;xLEt=01F%;Qv5IZ-;-j?QP_n$J-qrXm>f#sQ*YUvzC*uSN3gAzIC zm2)EdELs^9kk2vWfE!WOC)(QUNil*6GLV3CcId33H`X;Vk*##J6&<<~|3LGa_xqLt z^D9T^fPj2li#?5Y?-kaf@FI`b9TD+xc3#9#u&|l3V5_6k3$e{*gcyw--8JV@SC1Dd z$;CQ)X3⪙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