mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-06-05 03:10:04 +08:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f1fd4b6e6 | |||
| 9c001f2e40 | |||
| 58a5aa26a0 | |||
| 8306fb96ea | |||
| efab9be488 | |||
| 4d9369dc67 | |||
| e8a8e7c677 | |||
| e58d33284a | |||
| 937d27f8ee | |||
| eeb90ac70a | |||
| 1ea993880c | |||
| 09a0089c80 | |||
| cc2b367c0b | |||
| 5b6d1e9290 | |||
| ac6c9c857a | |||
| 18898f1876 | |||
| d532578ecc | |||
| 98d07ad1f3 | |||
| 07531d29b7 | |||
| edc570adff | |||
| 6bee0893de | |||
| af345c88e9 | |||
| c7bddda1db | |||
| d6fa42fefd | |||
| edaf5bf0cd | |||
| f65daf7259 | |||
| 3e3307c0d0 | |||
| 64e90b91aa | |||
| 32a5bd32ad | |||
| 0784901a66 | |||
| 9f8fa99d70 | |||
| b1435c6e34 | |||
| b0189d95af | |||
| 08d6465ce5 | |||
| da0e40c72b | |||
| 91364ba901 | |||
| 22c94f805a | |||
| 631046b962 | |||
| b26669b085 | |||
| 8497d3388f | |||
| 1524bd39b5 | |||
| 4363b09421 | |||
| d47f96f1a5 | |||
| 4270a303ab | |||
| 98ff1afc19 | |||
| 8b2205810b | |||
| fe0e3acf09 | |||
| 9a56b0a70d | |||
| ed174d54e9 | |||
| e2de62e38b | |||
| 0afda910d1 | |||
| 71c746b9bf |
@@ -105,3 +105,6 @@ src/modules/simulator/simulator_config.h
|
||||
src/systemcmds/topic_listener/listener_generated.cpp
|
||||
|
||||
!src/drivers/distance_sensor/broadcom/afbrs50/Lib/*
|
||||
|
||||
# colcon
|
||||
log/
|
||||
|
||||
+1
-1
@@ -256,7 +256,7 @@ endif()
|
||||
|
||||
set(package-contact "px4users@googlegroups.com")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
@@ -104,8 +104,9 @@ These boards fully comply with Pixhawk Standard, and are maintained by the PX4-A
|
||||
These boards are maintained to be compatible with PX4-Autopilot by the Manufacturers.
|
||||
|
||||
* [ARK Electronics ARKV6X](https://docs.px4.io/main/en/flight_controller/arkv6x.html)
|
||||
* [Hex Cube Orange](https://docs.px4.io/main/en/flight_controller/cubepilot_cube_orange.html)
|
||||
* [Hex Cube Yellow](https://docs.px4.io/main/en/flight_controller/cubepilot_cube_yellow.html)
|
||||
* [CubePilot Cube Orange+](https://docs.px4.io/main/en/flight_controller/cubepilot_cube_orangeplus.html)
|
||||
* [CubePilot Cube Orange](https://docs.px4.io/main/en/flight_controller/cubepilot_cube_orange.html)
|
||||
* [CubePilot Cube Yellow](https://docs.px4.io/main/en/flight_controller/cubepilot_cube_yellow.html)
|
||||
* [Holybro Durandal](https://docs.px4.io/main/en/flight_controller/durandal.html)
|
||||
* [Airmind MindPX V2.8](http://www.mindpx.net/assets/accessories/UserGuide_MindPX.pdf)
|
||||
* [Airmind MindRacer V1.2](http://mindpx.net/assets/accessories/mindracer_user_guide_v1.2.pdf)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
PX4_SIMULATOR=${PX4_SIMULATOR:=sihsim}
|
||||
PX4_SIM_MODEL=${PX4_SIM_MODEL:=xvert}
|
||||
|
||||
param set-default EKF2_FUSE_BETA 0 # side slip fusion is currently not supported for tailsitters
|
||||
|
||||
param set-default SENS_EN_GPSSIM 1
|
||||
param set-default SENS_EN_BAROSIM 1
|
||||
param set-default SENS_EN_MAGSIM 1
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
param set-default MAV_TYPE 20
|
||||
|
||||
param set-default EKF2_FUSE_BETA 0 # side slip fusion is currently not supported for tailsitters
|
||||
|
||||
param set-default CA_AIRFRAME 4
|
||||
|
||||
param set-default CA_ROTOR_COUNT 4
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
. ${R}etc/init.d/rc.vtol_defaults
|
||||
|
||||
param set-default EKF2_FUSE_BETA 0 # side slip fusion is currently not supported for tailsitters
|
||||
|
||||
param set UAVCAN_ENABLE 0
|
||||
param set-default VT_ELEV_MC_LOCK 0
|
||||
param set-default VT_MOT_COUNT 2
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
. ${R}etc/init.d/rc.vtol_defaults
|
||||
|
||||
param set-default EKF2_FUSE_BETA 0 # side slip fusion is currently not supported for tailsitters
|
||||
|
||||
param set-default CA_AIRFRAME 4
|
||||
param set-default CA_ROTOR_COUNT 2
|
||||
param set-default CA_ROTOR0_KM -0.05
|
||||
|
||||
@@ -7,7 +7,7 @@ import os
|
||||
class JsonOutput():
|
||||
def __init__(self, groups):
|
||||
all_json = {}
|
||||
all_json['version'] = 1
|
||||
all_json['version'] = 2
|
||||
component = {}
|
||||
all_json['components'] = {1: component} #1: autopilot component
|
||||
|
||||
|
||||
Submodule Tools/simulation/gazebo-classic/sitl_gazebo-classic updated: e3722bf913...1c5818e56c
@@ -35,7 +35,20 @@ function spawn_model() {
|
||||
pushd "$working_dir" &>/dev/null
|
||||
echo "starting instance $N in $(pwd)"
|
||||
$build_path/bin/px4 -i $N -d "$build_path/etc" >out.log 2>err.log &
|
||||
python3 ${src_path}/Tools/simulation/gazebo-classic/sitl_gazebo-classic/scripts/jinja_gen.py ${src_path}/Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/${MODEL}/${MODEL}.sdf.jinja ${src_path}/Tools/simulation/gazebo-classic/sitl_gazebo-classic --mavlink_tcp_port $((4560+${N})) --mavlink_udp_port $((14560+${N})) --mavlink_id $((1+${N})) --gst_udp_port $((5600+${N})) --video_uri $((5600+${N})) --mavlink_cam_udp_port $((14530+${N})) --output-file /tmp/${MODEL}_${N}.sdf
|
||||
|
||||
set --
|
||||
set -- ${@} ${src_path}/Tools/simulation/gazebo-classic/sitl_gazebo-classic/scripts/jinja_gen.py
|
||||
set -- ${@} ${src_path}/Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/${MODEL}/${MODEL}.sdf.jinja
|
||||
set -- ${@} ${src_path}/Tools/simulation/gazebo-classic/sitl_gazebo-classic
|
||||
set -- ${@} --mavlink_tcp_port $((4560+${N}))
|
||||
set -- ${@} --mavlink_udp_port $((14560+${N}))
|
||||
set -- ${@} --mavlink_id $((1+${N}))
|
||||
set -- ${@} --gst_udp_port $((5600+${N}))
|
||||
set -- ${@} --video_uri $((5600+${N}))
|
||||
set -- ${@} --mavlink_cam_udp_port $((14530+${N}))
|
||||
set -- ${@} --output-file /tmp/${MODEL}_${N}.sdf
|
||||
|
||||
python3 ${@}
|
||||
|
||||
echo "Spawning ${MODEL}_${N} at ${X} ${Y}"
|
||||
|
||||
@@ -106,7 +119,7 @@ if [ -z ${SCRIPT} ]; then
|
||||
fi
|
||||
|
||||
while [ $n -lt $num_vehicles ]; do
|
||||
spawn_model ${vehicle_model} $n
|
||||
spawn_model ${vehicle_model} $(($n + 1))
|
||||
n=$(($n + 1))
|
||||
done
|
||||
else
|
||||
@@ -127,7 +140,7 @@ else
|
||||
m=0
|
||||
while [ $m -lt ${target_number} ]; do
|
||||
export PX4_SIM_MODEL=gazebo-classic_${target_vehicle}
|
||||
spawn_model ${target_vehicle}${LABEL} $n $target_x $target_y
|
||||
spawn_model ${target_vehicle}${LABEL} $(($n + 1)) $target_x $target_y
|
||||
m=$(($m + 1))
|
||||
n=$(($n + 1))
|
||||
done
|
||||
|
||||
@@ -27,7 +27,6 @@ CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
|
||||
@@ -39,7 +39,6 @@ CONFIG_UAVCANNODE_STATIC_PRESSURE=y
|
||||
CONFIG_UAVCANNODE_STATIC_TEMPERATURE=y
|
||||
CONFIG_MODULES_CONTROL_ALLOCATOR=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y
|
||||
CONFIG_SYSTEMCMDS_I2CDETECT=y
|
||||
CONFIG_SYSTEMCMDS_LED_CONTROL=y
|
||||
|
||||
@@ -26,7 +26,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_UAVCAN=y
|
||||
|
||||
@@ -15,6 +15,8 @@ CONFIG_MODULES_COMMANDER=y
|
||||
CONFIG_MODULES_CONTROL_ALLOCATOR=y
|
||||
CONFIG_MODULES_DATAMAN=y
|
||||
CONFIG_MODULES_EKF2=y
|
||||
# CONFIG_EKF2_GNSS_YAW is not set
|
||||
# CONFIG_EKF2_SIDESLIP is not set
|
||||
CONFIG_MODULES_EVENTS=y
|
||||
CONFIG_MODULES_FLIGHT_MODE_MANAGER=y
|
||||
CONFIG_MODULES_LAND_DETECTOR=y
|
||||
|
||||
@@ -14,6 +14,8 @@ CONFIG_MODULES_COMMANDER=y
|
||||
CONFIG_MODULES_CONTROL_ALLOCATOR=y
|
||||
CONFIG_MODULES_DATAMAN=y
|
||||
CONFIG_MODULES_EKF2=y
|
||||
# CONFIG_EKF2_GNSS_YAW is not set
|
||||
# CONFIG_EKF2_SIDESLIP is not set
|
||||
CONFIG_MODULES_EVENTS=y
|
||||
CONFIG_MODULES_FLIGHT_MODE_MANAGER=y
|
||||
CONFIG_MODULES_LAND_DETECTOR=y
|
||||
|
||||
@@ -209,7 +209,6 @@ CONFIG_STM32H7_SPI2=y
|
||||
CONFIG_STM32H7_SPI4=y
|
||||
CONFIG_STM32H7_SPI4_DMA=y
|
||||
CONFIG_STM32H7_SPI4_DMA_BUFFER=1024
|
||||
CONFIG_STM32H7_SPI_DMA=y
|
||||
CONFIG_STM32H7_TIM1=y
|
||||
CONFIG_STM32H7_TIM3=y
|
||||
CONFIG_STM32H7_TIM4=y
|
||||
|
||||
@@ -28,7 +28,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
|
||||
@@ -31,7 +31,6 @@ CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -30,7 +30,6 @@ CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_VOXLPM=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -4,6 +4,7 @@ CONFIG_DRIVERS_ACTUATORS_MODAL_IO=y
|
||||
CONFIG_DRIVERS_LIGHTS_RGBLED_NCP5623C=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_VOXLPM=y
|
||||
CONFIG_DRIVERS_QSHELL_QURT=y
|
||||
CONFIG_MODULES_COMMANDER=y
|
||||
CONFIG_MODULES_EKF2=y
|
||||
CONFIG_MODULES_LAND_DETECTOR=y
|
||||
CONFIG_MODULES_MC_ATT_CONTROL=y
|
||||
@@ -12,7 +13,6 @@ CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_MUORB_SLPI=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
CONFIG_MODULES_COMMANDER=y
|
||||
CONFIG_SYSTEMCMDS_PARAM=y
|
||||
CONFIG_SYSTEMCMDS_UORB=y
|
||||
CONFIG_ORB_COMMUNICATOR=y
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
CONFIG_PLATFORM_POSIX=y
|
||||
CONFIG_BOARD_LINUX_TARGET=y
|
||||
CONFIG_BOARD_TOOLCHAIN="aarch64-linux-gnu"
|
||||
CONFIG_BOARD_ROOTFSDIR="/data/px4"
|
||||
CONFIG_DRIVERS_QSHELL_POSIX=y
|
||||
CONFIG_MODULES_COMMANDER=y
|
||||
CONFIG_MODULES_DATAMAN=y
|
||||
@@ -17,4 +18,3 @@ CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y
|
||||
CONFIG_SYSTEMCMDS_UORB=y
|
||||
CONFIG_SYSTEMCMDS_VER=y
|
||||
CONFIG_ORB_COMMUNICATOR=y
|
||||
CONFIG_BOARD_ROOTFSDIR="/data/px4"
|
||||
|
||||
@@ -25,7 +25,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -24,7 +24,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -26,7 +26,6 @@ CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
|
||||
@@ -27,7 +27,6 @@ CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
|
||||
@@ -27,7 +27,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -28,7 +28,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -23,13 +23,18 @@ CONFIG_MODULES_COMMANDER=y
|
||||
CONFIG_MODULES_CONTROL_ALLOCATOR=y
|
||||
CONFIG_MODULES_DATAMAN=y
|
||||
CONFIG_MODULES_EKF2=y
|
||||
# CONFIG_EKF2_AUXVEL is not set
|
||||
# CONFIG_EKF2_BARO_COMPENSATION is not set
|
||||
# CONFIG_EKF2_DRAG_FUSION is not set
|
||||
# CONFIG_EKF2_EXTERNAL_VISION is not set
|
||||
# CONFIG_EKF2_GNSS_YAW is not set
|
||||
# CONFIG_EKF2_SIDESLIP is not set
|
||||
CONFIG_MODULES_FLIGHT_MODE_MANAGER=y
|
||||
CONFIG_MODULES_LAND_DETECTOR=y
|
||||
CONFIG_MODULES_LOGGER=y
|
||||
CONFIG_MODULES_MANUAL_CONTROL=y
|
||||
CONFIG_MODULES_MAVLINK=y
|
||||
CONFIG_MODULES_MC_ATT_CONTROL=y
|
||||
CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=n
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
CONFIG_MODULES_FLIGHT_MODE_MANAGER=n
|
||||
CONFIG_MODULES_MC_ATT_CONTROL=n
|
||||
CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=n
|
||||
CONFIG_MODULES_MC_POS_CONTROL=n
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=n
|
||||
CONFIG_SYSTEMCMDS_BL_UPDATE=n
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
CONFIG_MODULES_FLIGHT_MODE_MANAGER=n
|
||||
CONFIG_MODULES_MC_ATT_CONTROL=n
|
||||
CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=n
|
||||
CONFIG_MODULES_MC_POS_CONTROL=n
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=n
|
||||
CONFIG_DRIVERS_CAMERA_CAPTURE=y
|
||||
|
||||
@@ -31,7 +31,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
|
||||
@@ -30,7 +30,6 @@ CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -29,7 +29,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
CONFIG_DRIVERS_HEATER=n
|
||||
CONFIG_DRIVERS_UAVCAN=n
|
||||
CONFIG_CYPHAL_BMS_SUBSCRIBER=y
|
||||
CONFIG_CYPHAL_ESC_CONTROLLER=y
|
||||
CONFIG_CYPHAL_UORB_SENSOR_GPS_SUBSCRIBER=y
|
||||
CONFIG_DRIVERS_CYPHAL=y
|
||||
CONFIG_CYPHAL_ESC_CONTROLLER=y
|
||||
|
||||
@@ -14,7 +14,6 @@ CONFIG_DRIVERS_IRLOCK=n
|
||||
CONFIG_DRIVERS_PCA9685_PWM_OUT=n
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=n
|
||||
CONFIG_DRIVERS_PWM_INPUT=n
|
||||
CONFIG_DRIVERS_ROBOCLAW=n
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=n
|
||||
CONFIG_DRIVERS_UAVCAN=n
|
||||
CONFIG_MODULES_ATTITUDE_ESTIMATOR_Q=n
|
||||
|
||||
@@ -35,7 +35,6 @@ CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_COMMON_RC=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -9,7 +9,6 @@ CONFIG_DRIVERS_CAMERA_TRIGGER=n
|
||||
CONFIG_DRIVERS_IRLOCK=n
|
||||
CONFIG_DRIVERS_PCA9685_PWM_OUT=n
|
||||
CONFIG_DRIVERS_PWM_INPUT=n
|
||||
CONFIG_DRIVERS_ROBOCLAW=n
|
||||
CONFIG_DRIVERS_UAVCAN=n
|
||||
CONFIG_EXAMPLES_FAKE_GPS=n
|
||||
CONFIG_MODULES_AIRSPEED_SELECTOR=n
|
||||
|
||||
@@ -17,7 +17,6 @@ CONFIG_DRIVERS_IRLOCK=n
|
||||
CONFIG_DRIVERS_PCA9685_PWM_OUT=n
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=n
|
||||
CONFIG_DRIVERS_PWM_INPUT=n
|
||||
CONFIG_DRIVERS_ROBOCLAW=n
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=n
|
||||
CONFIG_DRIVERS_UAVCAN=n
|
||||
CONFIG_EXAMPLES_FAKE_GPS=n
|
||||
|
||||
@@ -11,7 +11,6 @@ CONFIG_DRIVERS_IMU_INVENSENSE_ICM20948=n
|
||||
CONFIG_DRIVERS_IRLOCK=n
|
||||
CONFIG_DRIVERS_PCA9685_PWM_OUT=n
|
||||
CONFIG_DRIVERS_PWM_INPUT=n
|
||||
CONFIG_DRIVERS_ROBOCLAW=n
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=n
|
||||
CONFIG_EXAMPLES_FAKE_GPS=n
|
||||
CONFIG_MODULES_ATTITUDE_ESTIMATOR_Q=n
|
||||
|
||||
@@ -141,12 +141,13 @@
|
||||
#define GPIO_HW_VER_SENSE /* PC1 */ GPIO_ADC123_INP11
|
||||
#define HW_INFO_INIT_PREFIX "V6C"
|
||||
|
||||
#define BOARD_NUM_SPI_CFG_HW_VERSIONS 2 // Rev 0, 10 Sensor sets
|
||||
#define BOARD_NUM_SPI_CFG_HW_VERSIONS 3 // Rev 0, 10 and Mini Sensor sets
|
||||
// Base/FMUM
|
||||
#define V6C00 HW_VER_REV(0x0,0x0) // FMUV6C, Rev 0 I2C4 External but with Internal devices
|
||||
#define V6C01 HW_VER_REV(0x0,0x1) // FMUV6C, Rev 1 I2C4 Internal I2C2 External
|
||||
#define V6C10 HW_VER_REV(0x1,0x0) // NO PX4IO, Rev 0 I2C4 External but with Internal devices
|
||||
#define V6C11 HW_VER_REV(0x1,0x1) // NO PX4IO, Rev 1 I2C4 Internal I2C2 External
|
||||
#define V6C21 HW_VER_REV(0x2,0x1) // FMUV6CMini, Rev 1 I2C4 Internal I2C2 External
|
||||
|
||||
|
||||
/* HEATER
|
||||
|
||||
@@ -79,6 +79,11 @@ static const px4_hw_mft_item_t hw_mft_list_v0600[] = {
|
||||
.mandatory = 1,
|
||||
.connection = px4_hw_con_onboard,
|
||||
},
|
||||
{
|
||||
.present = 1,
|
||||
.mandatory = 1,
|
||||
.connection = px4_hw_con_onboard,
|
||||
},
|
||||
};
|
||||
|
||||
static const px4_hw_mft_item_t hw_mft_list_v0610[] = {
|
||||
@@ -101,6 +106,7 @@ static px4_hw_mft_list_entry_t mft_lists[] = {
|
||||
{V6C01, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, // Rev 1
|
||||
{V6C10, hw_mft_list_v0610, arraySize(hw_mft_list_v0610)}, // Rev 0 No PX4IO
|
||||
{V6C11, hw_mft_list_v0610, arraySize(hw_mft_list_v0610)}, // Rev 1 No PX4IO
|
||||
{V6C21, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, // Rev 1 MINI
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
|
||||
@@ -46,7 +46,17 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
|
||||
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4})
|
||||
}),
|
||||
}),
|
||||
initSPIHWVersion(V6C10, {
|
||||
initSPIHWVersion(V6C01, {
|
||||
initSPIBus(SPI::Bus::SPI1, {
|
||||
initSPIDevice(DRV_GYR_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}),
|
||||
initSPIDevice(DRV_ACC_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
|
||||
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
|
||||
}, {GPIO::PortB, GPIO::Pin2}),
|
||||
initSPIBus(SPI::Bus::SPI2, {
|
||||
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4})
|
||||
}),
|
||||
}),
|
||||
initSPIHWVersion(V6C21, {
|
||||
initSPIBus(SPI::Bus::SPI1, {
|
||||
initSPIDevice(DRV_GYR_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}),
|
||||
initSPIDevice(DRV_ACC_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
|
||||
|
||||
@@ -28,7 +28,6 @@ CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SAFETY_BUTTON=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
|
||||
@@ -25,7 +25,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
|
||||
@@ -25,7 +25,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
|
||||
@@ -4,7 +4,7 @@ project(googletest-download NONE)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
URL https://github.com/google/googletest/archive/58d77fa8070e8cec2dc1ed015d66b454c8d78850.zip # 1.12.1
|
||||
URL https://github.com/google/googletest/archive/b796f7d44681514f58a683a3a71ff17c94edb0c1.zip # 1.13
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
|
||||
CONFIGURE_COMMAND ""
|
||||
|
||||
@@ -46,4 +46,7 @@ add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src ${CMAKE_CURRENT_BINA
|
||||
get_target_property(GTEST_COMPILE_FLAGS gtest COMPILE_OPTIONS)
|
||||
list(REMOVE_ITEM GTEST_COMPILE_FLAGS "-include")
|
||||
list(REMOVE_ITEM GTEST_COMPILE_FLAGS "visibility.h")
|
||||
# Remove float warnings added by PX4 which trigger in gtest-printers.h
|
||||
list(REMOVE_ITEM GTEST_COMPILE_FLAGS "-Wdouble-promotion")
|
||||
list(REMOVE_ITEM GTEST_COMPILE_FLAGS "-Wfloat-equal")
|
||||
set_target_properties(gtest PROPERTIES COMPILE_OPTIONS "${GTEST_COMPILE_FLAGS}")
|
||||
|
||||
@@ -5,5 +5,3 @@ uint8 INDEX_YAW = 2
|
||||
|
||||
uint64 timestamp_sample # the timestamp the data this control response is based on was sampled
|
||||
float32[3] control
|
||||
|
||||
float32 retract_gimbal
|
||||
|
||||
@@ -93,6 +93,13 @@ bool keystore_put_key(keystore_session_handle_t handle, uint8_t idx, uint8_t *ke
|
||||
|
||||
void crypto_init(void);
|
||||
|
||||
/*
|
||||
* De-initialize hw level crypto
|
||||
* This may be called to shut down hw level crypto
|
||||
*/
|
||||
|
||||
void crypto_deinit(void);
|
||||
|
||||
/*
|
||||
* Open a session for performing crypto functions
|
||||
* algorithm: The crypto algorithm to be used in this session
|
||||
|
||||
@@ -245,4 +245,71 @@ private:
|
||||
T _data{};
|
||||
};
|
||||
|
||||
template<auto member>
|
||||
class SubscriptionSelection;
|
||||
|
||||
template <class T, class R, R T::*member>
|
||||
class SubscriptionSelection<member>: public Subscription
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param id The uORB metadata ORB_ID enum for the topic.
|
||||
* @param instance The instance for multi sub.
|
||||
*/
|
||||
SubscriptionSelection(ORB_ID id, uint8_t instance = 0) :
|
||||
Subscription(id, instance)
|
||||
{
|
||||
_copySelection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param meta The uORB metadata (usually from the ORB_ID() macro) for the topic.
|
||||
* @param instance The instance for multi sub.
|
||||
*/
|
||||
SubscriptionSelection(const orb_metadata *meta, uint8_t instance = 0) :
|
||||
Subscription(meta, instance)
|
||||
{
|
||||
_copySelection();
|
||||
}
|
||||
|
||||
~SubscriptionSelection() = default;
|
||||
|
||||
// no copy, assignment, move, move assignment
|
||||
SubscriptionSelection(const SubscriptionSelection &) = delete;
|
||||
SubscriptionSelection &operator=(const SubscriptionSelection &) = delete;
|
||||
SubscriptionSelection(SubscriptionSelection &&) = delete;
|
||||
SubscriptionSelection &operator=(SubscriptionSelection &&) = delete;
|
||||
|
||||
// update the embedded struct.
|
||||
bool update()
|
||||
{
|
||||
bool updated = Subscription::updated();
|
||||
|
||||
if (updated) {
|
||||
_copySelection();
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
const R &get() const { return _data; }
|
||||
|
||||
private:
|
||||
void _copySelection()
|
||||
{
|
||||
T full_data;
|
||||
|
||||
if (copy(&full_data)) {
|
||||
_data = full_data.*member;
|
||||
}
|
||||
}
|
||||
|
||||
R _data{};
|
||||
};
|
||||
|
||||
|
||||
} // namespace uORB
|
||||
|
||||
@@ -392,6 +392,10 @@ jump_to_app()
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BOOTLOADER_USE_SECURITY
|
||||
crypto_deinit();
|
||||
#endif
|
||||
|
||||
/* just for paranoia's sake */
|
||||
arch_flash_lock();
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ LeddarOne::open_serial_port(const speed_t speed)
|
||||
uart_config.c_cflag |= (CS8 | CREAD | CLOCAL);
|
||||
|
||||
// Clear: echo, echo new line, canonical input and extended input.
|
||||
uart_config.c_lflag &= (ECHO | ECHONL | ICANON | IEXTEN);
|
||||
uart_config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
|
||||
|
||||
// Clear ONLCR flag (which appends a CR for every LF).
|
||||
uart_config.c_oflag &= ~ONLCR;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <lib/systemlib/crc.h>
|
||||
#include <lib/crc/crc.h>
|
||||
|
||||
#include <float.h>
|
||||
#include <mathlib/mathlib.h>
|
||||
|
||||
@@ -1208,7 +1208,7 @@ GPS::publish()
|
||||
|
||||
if (_report_gps_pos.jamming_state != _jamming_state) {
|
||||
|
||||
if (_report_gps_pos.jamming_state > sensor_gps_s::JAMMING_STATE_OK) {
|
||||
if (_report_gps_pos.jamming_state > sensor_gps_s::JAMMING_STATE_WARNING) {
|
||||
PX4_WARN("GPS jamming detected! (state: %d) (indicator: %d)", _report_gps_pos.jamming_state,
|
||||
(uint8_t)_report_gps_pos.jamming_indicator);
|
||||
}
|
||||
|
||||
@@ -325,13 +325,7 @@ void RCInput::Run()
|
||||
updateParams();
|
||||
}
|
||||
|
||||
if (_vehicle_status_sub.updated()) {
|
||||
vehicle_status_s vehicle_status;
|
||||
|
||||
if (_vehicle_status_sub.copy(&vehicle_status)) {
|
||||
_armed = (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED);
|
||||
}
|
||||
}
|
||||
_vehicle_status_arming_state_sub.update();
|
||||
|
||||
const hrt_abstime cycle_timestamp = hrt_absolute_time();
|
||||
|
||||
@@ -346,7 +340,7 @@ void RCInput::Run()
|
||||
uint8_t cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_UNSUPPORTED;
|
||||
#if defined(SPEKTRUM_POWER)
|
||||
|
||||
if (!_rc_scan_locked && !_armed) {
|
||||
if (!_rc_scan_locked && !(_vehicle_status_arming_state_sub.get() == vehicle_status_s::ARMING_STATE_ARMED)) {
|
||||
if ((int)vcmd.param1 == 0) {
|
||||
// DSM binding command
|
||||
int dsm_bind_mode = (int)vcmd.param2;
|
||||
@@ -758,7 +752,8 @@ void RCInput::Run()
|
||||
|
||||
_to_input_rc.publish(_rc_in);
|
||||
|
||||
} else if (!rc_updated && !_armed && (hrt_elapsed_time(&_rc_in.timestamp_last_signal) > 1_s)) {
|
||||
} else if (!rc_updated && !(_vehicle_status_arming_state_sub.get() == vehicle_status_s::ARMING_STATE_ARMED)
|
||||
&& (hrt_elapsed_time(&_rc_in.timestamp_last_signal) > 1_s)) {
|
||||
_rc_scan_locked = false;
|
||||
}
|
||||
|
||||
@@ -767,7 +762,7 @@ void RCInput::Run()
|
||||
}
|
||||
|
||||
// set RC_INPUT_PROTO if RC successfully locked for > 3 seconds
|
||||
if (!_armed && rc_updated && _rc_scan_locked
|
||||
if (!(_vehicle_status_arming_state_sub.get() == vehicle_status_s::ARMING_STATE_ARMED) && rc_updated && _rc_scan_locked
|
||||
&& ((_rc_scan_begin != 0) && hrt_elapsed_time(&_rc_scan_begin) > 3_s)
|
||||
&& (_param_rc_input_proto.get() < 0)
|
||||
) {
|
||||
|
||||
@@ -138,16 +138,13 @@ private:
|
||||
|
||||
uORB::Subscription _adc_report_sub{ORB_ID(adc_report)};
|
||||
uORB::Subscription _vehicle_cmd_sub{ORB_ID(vehicle_command)};
|
||||
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
|
||||
uORB::SubscriptionSelection<&vehicle_status_s::arming_state> _vehicle_status_arming_state_sub{ORB_ID(vehicle_status)};
|
||||
|
||||
input_rc_s _rc_in{};
|
||||
|
||||
float _analog_rc_rssi_volt{-1.0f};
|
||||
bool _analog_rc_rssi_stable{false};
|
||||
|
||||
bool _armed{false};
|
||||
|
||||
|
||||
uORB::PublicationMulti<input_rc_s> _to_input_rc{ORB_ID(input_rc)};
|
||||
|
||||
int _rcs_fd{-1};
|
||||
|
||||
@@ -59,6 +59,10 @@ extern void libtomcrypt_init(void);
|
||||
#define SECMEM_FREE XFREE
|
||||
#endif
|
||||
|
||||
#define SHA256_HASHLEN 32
|
||||
#define OAEP_MAX_RSA_MODLEN 256 /* RSA2048 */
|
||||
#define OAEP_MAX_MSGLEN (OAEP_MAX_RSA_MODLEN - 2 * SHA256_HASHLEN - 2)
|
||||
|
||||
/*
|
||||
* For now, this is just a dummy up/down counter for tracking open/close calls
|
||||
*/
|
||||
@@ -151,6 +155,10 @@ void crypto_init()
|
||||
clear_key_cache();
|
||||
}
|
||||
|
||||
void crypto_deinit()
|
||||
{
|
||||
}
|
||||
|
||||
crypto_session_handle_t crypto_open(px4_crypto_algorithm_t algorithm)
|
||||
{
|
||||
crypto_session_handle_t ret;
|
||||
@@ -378,12 +386,22 @@ bool crypto_get_encrypted_key(crypto_session_handle_t handle,
|
||||
max_len);
|
||||
|
||||
} else {
|
||||
// The key size, encrypted, is a multiple of minimum block size for the algorithm+key
|
||||
size_t min_block = crypto_get_min_blocksize(handle, encryption_key_idx);
|
||||
*max_len = key_sz / min_block * min_block;
|
||||
switch (handle.algorithm) {
|
||||
|
||||
if (key_sz % min_block) {
|
||||
*max_len += min_block;
|
||||
case CRYPTO_RSA_OAEP:
|
||||
/* The length is the RSA key modulus length, and the maximum plaintext
|
||||
* length is calculated from that. This is now just fixed for RSA2048,
|
||||
* but one could also parse the RSA key
|
||||
* (encryption_key_idx) here and calculate the lengths.
|
||||
*/
|
||||
|
||||
*max_len = key_sz <= OAEP_MAX_MSGLEN ? OAEP_MAX_RSA_MODLEN : 0;
|
||||
ret = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
*max_len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,24 +441,6 @@ size_t crypto_get_min_blocksize(crypto_session_handle_t handle, uint8_t key_idx)
|
||||
ret = 64;
|
||||
break;
|
||||
|
||||
case CRYPTO_RSA_OAEP: {
|
||||
rsa_key enc_key;
|
||||
size_t pub_key_sz;
|
||||
uint8_t *pub_key = (uint8_t *)crypto_get_key_ptr(handle.keystore_handle, key_idx, &pub_key_sz);
|
||||
|
||||
initialize_tomcrypt();
|
||||
|
||||
if (pub_key &&
|
||||
rsa_import(pub_key, pub_key_sz, &enc_key) == CRYPT_OK) {
|
||||
ret = ltc_mp.unsigned_size(enc_key.N);
|
||||
rsa_free(&enc_key);
|
||||
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ if DRIVERS_UAVCANNODE
|
||||
bool "Include GNSS fix"
|
||||
default n
|
||||
|
||||
config UAVCANNODE_HYDROMETER_MEASUREMENT
|
||||
bool "Include hydrometer measurement"
|
||||
config UAVCANNODE_HYGROMETER_MEASUREMENT
|
||||
bool "Include hygrometer measurement"
|
||||
default n
|
||||
|
||||
config UAVCANNODE_LIGHTS_COMMAND
|
||||
|
||||
@@ -52,9 +52,9 @@
|
||||
#include "Publishers/FlowMeasurement.hpp"
|
||||
#endif // CONFIG_UAVCANNODE_FLOW_MEASUREMENT
|
||||
|
||||
#if defined(CONFIG_UAVCANNODE_HYDROMETER_MEASUREMENT)
|
||||
#if defined(UAVCANNODE_HYGROMETER_MEASUREMENT)
|
||||
#include "Publishers/HygrometerMeasurement.hpp"
|
||||
#endif // CONFIG_UAVCANNODE_HYDROMETER_MEASUREMENT
|
||||
#endif // UAVCANNODE_HYGROMETER_MEASUREMENT
|
||||
|
||||
#if defined(CONFIG_UAVCANNODE_GNSS_FIX)
|
||||
#include "Publishers/GnssFix2.hpp"
|
||||
@@ -360,9 +360,9 @@ int UavcanNode::init(uavcan::NodeID node_id, UAVCAN_DRIVER::BusEvent &bus_events
|
||||
_publisher_list.add(new FlowMeasurement(this, _node));
|
||||
#endif // CONFIG_UAVCANNODE_FLOW_MEASUREMENT
|
||||
|
||||
#if defined(CONFIG_UAVCANNODE_HYDROMETER_MEASUREMENT)
|
||||
#if defined(UAVCANNODE_HYGROMETER_MEASUREMENT)
|
||||
_publisher_list.add(new HygrometerMeasurement(this, _node));
|
||||
#endif // CONFIG_UAVCANNODE_HYDROMETER_MEASUREMENT
|
||||
#endif // UAVCANNODE_HYGROMETER_MEASUREMENT
|
||||
|
||||
#if defined(CONFIG_UAVCANNODE_GNSS_FIX)
|
||||
_publisher_list.add(new GnssFix2(this, _node));
|
||||
|
||||
@@ -53,7 +53,7 @@ else()
|
||||
set(comp_metadata_param_uri_fallback ${comp_metadata_param_uri_board})
|
||||
endif()
|
||||
# arguments: type, metadata file, uri, fallback uri, optional translation uri
|
||||
list(APPEND comp_metadata_types "--type" "1,${PX4_BINARY_DIR}/parameters.json.xz,${comp_metadata_param_uri},${comp_metadata_param_uri_fallback},")
|
||||
list(APPEND comp_metadata_types "--type" "1,${PX4_BINARY_DIR}/parameters.json.xz,${comp_metadata_param_uri},${comp_metadata_param_uri_fallback},https://raw.githubusercontent.com/PX4/PX4-Metadata-Translations/main/translated/parameters_summary.json")
|
||||
|
||||
|
||||
set(comp_metadata_events_uri_board "${s3_url}/Firmware/{version}/${comp_metadata_board}/all_events.json.xz")
|
||||
@@ -66,7 +66,7 @@ else()
|
||||
set(comp_metadata_events_uri "mftp://etc/extras/all_events.json.xz")
|
||||
set(comp_metadata_events_uri_fallback ${comp_metadata_events_uri_board})
|
||||
endif()
|
||||
list(APPEND comp_metadata_types "--type" "4,${PX4_BINARY_DIR}/events/all_events.json.xz,${comp_metadata_events_uri},${comp_metadata_events_uri_fallback},")
|
||||
list(APPEND comp_metadata_types "--type" "4,${PX4_BINARY_DIR}/events/all_events.json.xz,${comp_metadata_events_uri},${comp_metadata_events_uri_fallback},https://raw.githubusercontent.com/PX4/PX4-Metadata-Translations/main/translated/events_summary.json")
|
||||
|
||||
set(comp_metadata_actuators_uri_board "${s3_url}/Firmware/{version}/${comp_metadata_board}/actuators.json.xz")
|
||||
list(FIND config_romfs_extra_dependencies "actuators_json" index)
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
{
|
||||
"version": 1,
|
||||
"version": 2,
|
||||
"translation": {
|
||||
"items": {
|
||||
"components": {
|
||||
"items": {
|
||||
"*": {
|
||||
"items": {
|
||||
"enums": {
|
||||
"items": {
|
||||
"*": {
|
||||
"items": {
|
||||
"entries": {
|
||||
"items": {
|
||||
"*": {
|
||||
"translate": [ "description" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"event_groups": {
|
||||
"items": {
|
||||
"*": {
|
||||
"items": {
|
||||
"events": {
|
||||
"items": {
|
||||
"*": {
|
||||
"translate": [ "message", "description" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"1": {
|
||||
"namespace": "px4",
|
||||
|
||||
+1
-1
Submodule src/lib/events/libevents updated: 8d9c555127...48911e7be7
@@ -48,3 +48,4 @@ px4_add_unit_gtest(SRC math/FunctionsTest.cpp)
|
||||
px4_add_unit_gtest(SRC math/test/UtilitiesTest.cpp)
|
||||
px4_add_unit_gtest(SRC math/WelfordMeanTest.cpp)
|
||||
px4_add_unit_gtest(SRC math/WelfordMeanVectorTest.cpp)
|
||||
px4_add_unit_gtest(SRC math/MaxDistanceToCircleTest.cpp)
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 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 <gtest/gtest.h>
|
||||
#include <matrix/matrix/math.hpp>
|
||||
#include "Functions.hpp"
|
||||
|
||||
#include "TrajMath.hpp"
|
||||
|
||||
using namespace math;
|
||||
using matrix::Vector2f;
|
||||
|
||||
TEST(MaxDistanceToCircle, noDirection)
|
||||
{
|
||||
Vector2f pos;
|
||||
Vector2f circle_center;
|
||||
float radius = 3.f;
|
||||
Vector2f direction;
|
||||
float distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_TRUE(isnan(distance));
|
||||
}
|
||||
|
||||
TEST(MaxDistanceToCircle, insideCircle)
|
||||
{
|
||||
// North position, South direction
|
||||
Vector2f pos(1.f, 0.f);
|
||||
Vector2f circle_center;
|
||||
float radius = 3.f;
|
||||
Vector2f direction(-1.f, 0.f);
|
||||
float distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, 4.f);
|
||||
|
||||
// North position, West direction (direction doesn't need to be unit length)
|
||||
direction = Vector2f(0.f, -3.42f);
|
||||
distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, sqrtf(radius * radius - 1.f));
|
||||
|
||||
// SE position, directed towards the center
|
||||
pos = Vector2f(-2.f, 1.f);
|
||||
direction = Vector2f(2.f, -1.f);
|
||||
distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, pos.norm() + radius);
|
||||
}
|
||||
|
||||
TEST(MaxDistanceToCircle, outsideCircle)
|
||||
{
|
||||
// North position, South direction
|
||||
Vector2f pos(4.f, 0.f);
|
||||
Vector2f circle_center;
|
||||
float radius = 3.f;
|
||||
Vector2f direction(-1.f, 0.f);
|
||||
float distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, pos(0) + radius);
|
||||
|
||||
// looking away from the circle
|
||||
direction = Vector2f(0.f, -3.42f);
|
||||
distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_TRUE(isnan(distance));
|
||||
|
||||
// SE position, directed towards the center
|
||||
pos = Vector2f(-4.f, 2.f);
|
||||
direction = Vector2f(2.f, -1.f);
|
||||
distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, pos.norm() + radius);
|
||||
}
|
||||
|
||||
TEST(MaxDistanceToCircle, onCircle)
|
||||
{
|
||||
// South, looking North
|
||||
Vector2f pos(-4.f, 1.f);
|
||||
Vector2f circle_center(-1.f, 1.f);
|
||||
float radius = 3.f;
|
||||
Vector2f direction(1.f, 0.f);
|
||||
float distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, 2.f * radius);
|
||||
|
||||
// looking tangent to the circle
|
||||
direction = Vector2f(0.f, -3.42f);
|
||||
distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, 0.f);
|
||||
|
||||
// looking away from the circle
|
||||
direction = Vector2f(-10.f, -3.42f);
|
||||
distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, 0.f);
|
||||
|
||||
// SE position, directed towards the center
|
||||
pos = Vector2f(-sqrtf(2.f) / 2.f, sqrtf(2.f) / 2.f) * radius + circle_center;
|
||||
direction = -pos;
|
||||
distance = trajectory::getMaxDistanceToCircle(pos, circle_center, radius, direction);
|
||||
EXPECT_FLOAT_EQ(distance, 2.f * radius);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ inline float computeMaxSpeedFromDistance(const float jerk, const float accel, co
|
||||
float max_speed = 0.5f * (-b + sqrtf(sqr(b) - 4.0f * c));
|
||||
|
||||
// don't slow down more than the end speed, even if the conservative accel ramp time requests it
|
||||
return max(max_speed, final_speed);
|
||||
return fmaxf(max_speed, final_speed);
|
||||
}
|
||||
|
||||
/* Compute the maximum tangential speed in a circle defined by two line segments of length "d"
|
||||
@@ -110,5 +110,44 @@ inline float computeBrakingDistanceFromVelocity(const float velocity, const floa
|
||||
return velocity * (velocity / (2.0f * accel) + accel_delay_max / jerk);
|
||||
}
|
||||
|
||||
/* Compute the maximum distance between a point and a circle given a direction vector pointing from the point
|
||||
* towards the circle. The point can be inside or outside the circle.
|
||||
* _
|
||||
* ,=' '=, __
|
||||
* P-->------/-------A Distance = PA
|
||||
* Dir | x |
|
||||
* \ /
|
||||
* "=,_,="
|
||||
* Equation to solve: ||(point - circle_pos) + direction_unit * distance_to_circle|| = radius
|
||||
*
|
||||
* @param pos position of the point
|
||||
* @param circle_pos position of the center of the circle
|
||||
* @param radius radius of the circle
|
||||
* @param direction vector pointing from the point towards the circle
|
||||
*
|
||||
* @return longest distance between the point to the circle in the direction indicated by the vector or NAN if the
|
||||
* vector does not point towards the circle
|
||||
*/
|
||||
inline float getMaxDistanceToCircle(const matrix::Vector2f &pos, const matrix::Vector2f &circle_pos, float radius,
|
||||
const matrix::Vector2f &direction)
|
||||
{
|
||||
matrix::Vector2f center_to_pos = pos - circle_pos;
|
||||
const float b = 2.f * center_to_pos.dot(direction.unit_or_zero());
|
||||
const float c = center_to_pos.norm_squared() - radius * radius;
|
||||
const float delta = b * b - 4.f * c;
|
||||
|
||||
float distance_to_circle;
|
||||
|
||||
if (delta >= 0.f && direction.longerThan(0.f)) {
|
||||
distance_to_circle = fmaxf((-b + sqrtf(delta)) / 2.f, 0.f);
|
||||
|
||||
} else {
|
||||
// Never intersecting the circle
|
||||
distance_to_circle = NAN;
|
||||
}
|
||||
|
||||
return distance_to_circle;
|
||||
}
|
||||
|
||||
} /* namespace traj */
|
||||
} /* namespace math */
|
||||
|
||||
@@ -92,6 +92,16 @@ struct Dual {
|
||||
return (*this = *this / a);
|
||||
}
|
||||
|
||||
bool operator==(const Dual<Scalar, N> &other) const
|
||||
{
|
||||
return isEqualF(value, other.value) && (derivative == other.derivative);
|
||||
}
|
||||
|
||||
bool operator!=(const Dual<Scalar, N> &other) const
|
||||
{
|
||||
const Dual<Scalar, N> &self = *this;
|
||||
return !(self == other);
|
||||
}
|
||||
};
|
||||
|
||||
// operators
|
||||
@@ -359,23 +369,12 @@ Matrix<Scalar, M, N> collectReals(const Matrix<Dual<Scalar, D>, M, N> &input)
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_STDIOSTREAM)
|
||||
template<typename Type, size_t N>
|
||||
std::ostream &operator<<(std::ostream &os,
|
||||
const matrix::Dual<Type, N> &dual)
|
||||
template<typename OStream, typename Type, size_t N>
|
||||
OStream &operator<<(OStream &os, const matrix::Dual<Type, N> &dual)
|
||||
{
|
||||
os << "[";
|
||||
os << std::setw(10) << dual.value << ";";
|
||||
|
||||
for (size_t j = 0; j < N; ++j) {
|
||||
os << "\t";
|
||||
os << std::setw(10) << static_cast<double>(dual.derivative(j));
|
||||
}
|
||||
|
||||
os << "]";
|
||||
os << "\nValue: " << dual.value << "\nDerivative:" << dual.derivative;
|
||||
return os;
|
||||
}
|
||||
#endif // defined(SUPPORT_STDIOSTREAM)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(SUPPORT_STDIOSTREAM)
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#endif // defined(SUPPORT_STDIOSTREAM)
|
||||
|
||||
#include "math.hpp"
|
||||
|
||||
namespace matrix
|
||||
@@ -372,10 +367,9 @@ public:
|
||||
{
|
||||
// element: tab, point, 8 digits, 4 scientific notation chars; row: newline; string: \0 end
|
||||
static const size_t n = 15 * N * M + M + 1;
|
||||
char *buf = new char[n];
|
||||
write_string(buf, n);
|
||||
printf("%s\n", buf);
|
||||
delete[] buf;
|
||||
char string[n];
|
||||
write_string(string, n);
|
||||
printf("%s\n", string);
|
||||
}
|
||||
|
||||
Matrix<Type, N, M> transpose() const
|
||||
@@ -816,24 +810,16 @@ Matrix<Type, M, N> constrain(const Matrix<Type, M, N> &x,
|
||||
return m;
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_STDIOSTREAM)
|
||||
template<typename Type, size_t M, size_t N>
|
||||
std::ostream &operator<<(std::ostream &os,
|
||||
const matrix::Matrix<Type, M, N> &matrix)
|
||||
template<typename OStream, typename Type, size_t M, size_t N>
|
||||
OStream &operator<<(OStream &os, const matrix::Matrix<Type, M, N> &matrix)
|
||||
{
|
||||
for (size_t i = 0; i < M; ++i) {
|
||||
os << "[";
|
||||
|
||||
for (size_t j = 0; j < N; ++j) {
|
||||
os << std::setw(10) << matrix(i, j);
|
||||
os << "\t";
|
||||
}
|
||||
|
||||
os << "]" << std::endl;
|
||||
}
|
||||
|
||||
os << "\n";
|
||||
// element: tab, point, 8 digits, 4 scientific notation chars; row: newline; string: \0 end
|
||||
static const size_t n = 15 * N * M + M + 1;
|
||||
char string[n];
|
||||
matrix.write_string(string, n);
|
||||
os << string;
|
||||
return os;
|
||||
}
|
||||
#endif // defined(SUPPORT_STDIOSTREAM)
|
||||
|
||||
} // namespace matrix
|
||||
|
||||
@@ -50,7 +50,7 @@ class AxisAngle;
|
||||
* described by this class.
|
||||
*/
|
||||
template<typename Type>
|
||||
class Quaternion : public Vector<Type, 4>
|
||||
class Quaternion : public Vector4<Type>
|
||||
{
|
||||
public:
|
||||
using Matrix41 = Matrix<Type, 4, 1>;
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
* @param data_ array
|
||||
*/
|
||||
explicit Quaternion(const Type data_[4]) :
|
||||
Vector<Type, 4>(data_)
|
||||
Vector4<Type>(data_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
* @param other Matrix41 to copy
|
||||
*/
|
||||
Quaternion(const Matrix41 &other) :
|
||||
Vector<Type, 4>(other)
|
||||
Vector4<Type>(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +148,23 @@ public:
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
(*this).transpose().print();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename OStream, typename Type, size_t M>
|
||||
OStream &operator<<(OStream &os, const matrix::Vector<Type, M> &vector)
|
||||
{
|
||||
os << "\n";
|
||||
// element: tab, point, 8 digits, 4 scientific notation chars; row: newline; string: \0 end
|
||||
static const size_t n = 15 * M * 1 + 1 + 1;
|
||||
char string[n];
|
||||
vector.transpose().write_string(string, n);
|
||||
os << string;
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace matrix
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file Vector4.hpp
|
||||
*
|
||||
* 4D vector class.
|
||||
*
|
||||
* @author Matthias Grob <maetugr@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math.hpp"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
|
||||
template <typename Type, size_t M, size_t N>
|
||||
class Matrix;
|
||||
|
||||
template <typename Type, size_t M>
|
||||
class Vector;
|
||||
|
||||
template<typename Type>
|
||||
class Vector4 : public Vector<Type, 4>
|
||||
{
|
||||
public:
|
||||
using Matrix41 = Matrix<Type, 4, 1>;
|
||||
|
||||
Vector4() = default;
|
||||
|
||||
Vector4(const Matrix41 &other) :
|
||||
Vector<Type, 4>(other)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Vector4(const Type data_[3]) :
|
||||
Vector<Type, 4>(data_)
|
||||
{
|
||||
}
|
||||
|
||||
Vector4(Type x1, Type x2, Type x3, Type x4)
|
||||
{
|
||||
Vector4 &v(*this);
|
||||
v(0) = x1;
|
||||
v(1) = x2;
|
||||
v(2) = x3;
|
||||
v(3) = x4;
|
||||
}
|
||||
|
||||
template<size_t P, size_t Q>
|
||||
Vector4(const Slice<Type, 4, 1, P, Q> &slice_in) : Vector<Type, 4>(slice_in)
|
||||
{
|
||||
}
|
||||
|
||||
template<size_t P, size_t Q>
|
||||
Vector4(const Slice<Type, 1, 4, P, Q> &slice_in) : Vector<Type, 4>(slice_in)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
using Vector4f = Vector4<float>;
|
||||
|
||||
} // namespace matrix
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Vector.hpp"
|
||||
#include "Vector2.hpp"
|
||||
#include "Vector3.hpp"
|
||||
#include "Vector4.hpp"
|
||||
#include "Euler.hpp"
|
||||
#include "Dcm.hpp"
|
||||
#include "Scalar.hpp"
|
||||
|
||||
@@ -260,7 +260,7 @@ TEST(MatrixAttitudeTest, Attitude)
|
||||
|
||||
// quaterion copy ctors
|
||||
float data_v4[] = {1, 2, 3, 4};
|
||||
Vector<float, 4> v4(data_v4);
|
||||
Vector4f v4(data_v4);
|
||||
Quatf q_from_v(v4);
|
||||
EXPECT_EQ(q_from_v, v4);
|
||||
|
||||
@@ -270,15 +270,13 @@ TEST(MatrixAttitudeTest, Attitude)
|
||||
|
||||
// quaternion derivative in frame 1
|
||||
Quatf q1(0, 1, 0, 0);
|
||||
Vector<float, 4> q1_dot1 = q1.derivative1(Vector3f(1, 2, 3));
|
||||
float data_q_dot1_check[] = { -0.5f, 0.0f, -1.5f, 1.0f};
|
||||
Vector<float, 4> q1_dot1_check(data_q_dot1_check);
|
||||
Vector4f q1_dot1 = q1.derivative1(Vector3f(1, 2, 3));
|
||||
Vector4f q1_dot1_check(-0.5f, 0.0f, -1.5f, 1.0f);
|
||||
EXPECT_EQ(q1_dot1, q1_dot1_check);
|
||||
|
||||
// quaternion derivative in frame 2
|
||||
Vector<float, 4> q1_dot2 = q1.derivative2(Vector3f(1, 2, 3));
|
||||
float data_q_dot2_check[] = { -0.5f, 0.0f, 1.5f, -1.0f};
|
||||
Vector<float, 4> q1_dot2_check(data_q_dot2_check);
|
||||
Vector4f q1_dot2 = q1.derivative2(Vector3f(1, 2, 3));
|
||||
Vector4f q1_dot2_check(-0.5f, 0.0f, 1.5f, -1.0f);
|
||||
EXPECT_EQ(q1_dot2, q1_dot2_check);
|
||||
|
||||
// quaternion product
|
||||
|
||||
@@ -39,12 +39,6 @@
|
||||
|
||||
using namespace matrix;
|
||||
|
||||
template <typename Scalar, size_t N>
|
||||
bool isEqualAll(Dual<Scalar, N> a, Dual<Scalar, N> b)
|
||||
{
|
||||
return isEqualF(a.value, b.value) && a.derivative == b.derivative;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T testFunction(const Vector<T, 3> &point)
|
||||
{
|
||||
@@ -83,9 +77,9 @@ TEST(MatrixDualTest, Dual)
|
||||
EXPECT_FLOAT_EQ(c.derivative(0), 2.f);
|
||||
|
||||
Dual<float, 1> d = +a;
|
||||
EXPECT_TRUE(isEqualAll(d, a));
|
||||
EXPECT_EQ(d, a);
|
||||
d += b;
|
||||
EXPECT_TRUE(isEqualAll(d, c));
|
||||
EXPECT_EQ(d, c);
|
||||
|
||||
Dual<float, 1> e = a;
|
||||
e += b.value;
|
||||
@@ -93,7 +87,7 @@ TEST(MatrixDualTest, Dual)
|
||||
EXPECT_EQ(e.derivative, a.derivative);
|
||||
|
||||
Dual<float, 1> f = b.value + a;
|
||||
EXPECT_TRUE(isEqualAll(f, e));
|
||||
EXPECT_EQ(f, e);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -103,9 +97,9 @@ TEST(MatrixDualTest, Dual)
|
||||
EXPECT_FLOAT_EQ(c.derivative(0), 0.f);
|
||||
|
||||
Dual<float, 1> d = b;
|
||||
EXPECT_TRUE(isEqualAll(d, b));
|
||||
EXPECT_EQ(d, b);
|
||||
d -= a;
|
||||
EXPECT_TRUE(isEqualAll(d, c));
|
||||
EXPECT_EQ(d, c);
|
||||
|
||||
Dual<float, 1> e = b;
|
||||
e -= a.value;
|
||||
@@ -113,7 +107,7 @@ TEST(MatrixDualTest, Dual)
|
||||
EXPECT_EQ(e.derivative, b.derivative);
|
||||
|
||||
Dual<float, 1> f = a.value - b;
|
||||
EXPECT_TRUE(isEqualAll(f, -e));
|
||||
EXPECT_EQ(f, -e);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -123,9 +117,9 @@ TEST(MatrixDualTest, Dual)
|
||||
EXPECT_FLOAT_EQ(c.derivative(0), 9.f);
|
||||
|
||||
Dual<float, 1> d = a;
|
||||
EXPECT_TRUE(isEqualAll(d, a));
|
||||
EXPECT_EQ(d, a);
|
||||
d *= b;
|
||||
EXPECT_TRUE(isEqualAll(d, c));
|
||||
EXPECT_EQ(d, c);
|
||||
|
||||
Dual<float, 1> e = a;
|
||||
e *= b.value;
|
||||
@@ -133,7 +127,7 @@ TEST(MatrixDualTest, Dual)
|
||||
EXPECT_EQ(e.derivative, a.derivative * b.value);
|
||||
|
||||
Dual<float, 1> f = b.value * a;
|
||||
EXPECT_TRUE(isEqualAll(f, e));
|
||||
EXPECT_EQ(f, e);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -143,9 +137,9 @@ TEST(MatrixDualTest, Dual)
|
||||
EXPECT_FLOAT_EQ(c.derivative(0), -1.f / 3.f);
|
||||
|
||||
Dual<float, 1> d = b;
|
||||
EXPECT_TRUE(isEqualAll(d, b));
|
||||
EXPECT_EQ(d, b);
|
||||
d /= a;
|
||||
EXPECT_TRUE(isEqualAll(d, c));
|
||||
EXPECT_EQ(d, c);
|
||||
|
||||
Dual<float, 1> e = b;
|
||||
e /= a.value;
|
||||
@@ -153,7 +147,7 @@ TEST(MatrixDualTest, Dual)
|
||||
EXPECT_EQ(e.derivative, b.derivative / a.value);
|
||||
|
||||
Dual<float, 1> f = a.value / b;
|
||||
EXPECT_TRUE(isEqualAll(f, 1.f / e));
|
||||
EXPECT_EQ(f, 1.f / e);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -170,9 +164,9 @@ TEST(MatrixDualTest, Dual)
|
||||
|
||||
{
|
||||
// abs
|
||||
EXPECT_TRUE(isEqualAll(a, abs(-a)));
|
||||
EXPECT_FALSE(isEqualAll(-a, abs(a)));
|
||||
EXPECT_TRUE(isEqualAll(-a, -abs(a)));
|
||||
EXPECT_EQ(a, abs(-a));
|
||||
EXPECT_NE(-a, abs(a));
|
||||
EXPECT_EQ(-a, -abs(a));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -197,8 +191,8 @@ TEST(MatrixDualTest, Dual)
|
||||
|
||||
{
|
||||
// max/min
|
||||
EXPECT_TRUE(isEqualAll(b, max(a, b)));
|
||||
EXPECT_TRUE(isEqualAll(a, min(a, b)));
|
||||
EXPECT_EQ(b, max(a, b));
|
||||
EXPECT_EQ(a, min(a, b));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -248,7 +242,7 @@ TEST(MatrixDualTest, Dual)
|
||||
{
|
||||
// atan2
|
||||
EXPECT_FLOAT_EQ(atan2(a, b).value, atan2(a.value, b.value));
|
||||
EXPECT_TRUE(isEqualAll(atan2(a, Dual<float, 1>(b.value)), atan(a / b.value))); // atan2'(y, x) = atan'(y/x)
|
||||
EXPECT_EQ(atan2(a, Dual<float, 1>(b.value)), atan(a / b.value)); // atan2'(y, x) = atan'(y/x)
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -50,19 +50,12 @@ TEST(MatrixLeastSquaresTest, 4x3)
|
||||
-1.f, -1.1f, -1.2f
|
||||
};
|
||||
Matrix<float, 4, 3> A(data);
|
||||
|
||||
float b_data[4] = {2.0f, 3.0f, 4.0f, 5.0f};
|
||||
Vector<float, 4> b(b_data);
|
||||
|
||||
float x_check_data[3] = {-0.69168233f,
|
||||
-0.26227593f,
|
||||
-1.03767522f
|
||||
};
|
||||
Vector<float, 3> x_check(x_check_data);
|
||||
Vector4f b(2.0f, 3.0f, 4.0f, 5.0f);
|
||||
Vector3f x_check(-0.69168233f, -0.26227593f, -1.03767522f);
|
||||
|
||||
LeastSquaresSolver<float, 4, 3> qrd = LeastSquaresSolver<float, 4, 3>(A);
|
||||
|
||||
Vector<float, 3> x = qrd.solve(b);
|
||||
Vector3f x = qrd.solve(b);
|
||||
EXPECT_EQ(x, x_check);
|
||||
}
|
||||
|
||||
@@ -75,20 +68,12 @@ TEST(MatrixLeastSquaresTest, 4x4)
|
||||
-1.f, -1.1f, -1.2f, -1.3f
|
||||
};
|
||||
Matrix<float, 4, 4> A(data);
|
||||
|
||||
float b_data[4] = {2.0f, 3.0f, 4.0f, 5.0f};
|
||||
Vector<float, 4> b(b_data);
|
||||
|
||||
float x_check_data[4] = { 0.97893433f,
|
||||
-2.80798701f,
|
||||
-0.03175765f,
|
||||
-2.19387649f
|
||||
};
|
||||
Vector<float, 4> x_check(x_check_data);
|
||||
Vector4f b(2.0f, 3.0f, 4.0f, 5.0f);
|
||||
Vector4f x_check(0.97893433f, -2.80798701f, -0.03175765f, -2.19387649f);
|
||||
|
||||
LeastSquaresSolver<float, 4, 4> qrd = LeastSquaresSolver<float, 4, 4>(A);
|
||||
|
||||
Vector<float, 4> x = qrd.solve(b);
|
||||
Vector4f x = qrd.solve(b);
|
||||
EXPECT_EQ(x, x_check);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,11 +92,11 @@ TEST(MatrixSparseVectorTest, setZero)
|
||||
|
||||
TEST(MatrixSparseVectorTest, additionWithDenseVector)
|
||||
{
|
||||
Vector<float, 4> dense_vec;
|
||||
Vector4f dense_vec;
|
||||
dense_vec.setAll(1.f);
|
||||
const float data[3] = {1.f, 2.f, 3.f};
|
||||
const SparseVectorf<4, 1, 2, 3> sparse_vec(data);
|
||||
const Vector<float, 4> res = sparse_vec + dense_vec;
|
||||
const Vector4f res = sparse_vec + dense_vec;
|
||||
EXPECT_FLOAT_EQ(res(0), 1.f);
|
||||
EXPECT_FLOAT_EQ(res(1), 2.f);
|
||||
EXPECT_FLOAT_EQ(res(2), 3.f);
|
||||
@@ -115,7 +115,7 @@ TEST(MatrixSparseVectorTest, addScalar)
|
||||
|
||||
TEST(MatrixSparseVectorTest, dotProductWithDenseVector)
|
||||
{
|
||||
Vector<float, 4> dense_vec;
|
||||
Vector4f dense_vec;
|
||||
dense_vec.setAll(3.f);
|
||||
const float data[3] = {1.f, 2.f, 3.f};
|
||||
const SparseVectorf<4, 1, 2, 3> sparse_vec(data);
|
||||
|
||||
@@ -71,13 +71,7 @@ TEST(MatrixVector3Test, Vector3)
|
||||
|
||||
Vector3f h;
|
||||
EXPECT_EQ(h, Vector3f(0, 0, 0));
|
||||
|
||||
Vector<float, 4> j;
|
||||
j(0) = 1;
|
||||
j(1) = 2;
|
||||
j(2) = 3;
|
||||
j(3) = 4;
|
||||
|
||||
Vector4f j(1.f, 2.f, 3.f, 4.f);
|
||||
Vector3f k = j.slice<3, 1>(0, 0);
|
||||
Vector3f k_test(1, 2, 3);
|
||||
EXPECT_EQ(k, k_test);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 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 <gtest/gtest.h>
|
||||
#include <matrix/math.hpp>
|
||||
|
||||
using namespace matrix;
|
||||
|
||||
TEST(MatrixVector4Test, Vector4)
|
||||
{
|
||||
Vector4f a(1.f, 2.f, 3.f, 4.f);
|
||||
EXPECT_EQ(a(0), 1.f);
|
||||
EXPECT_EQ(a(1), 2.f);
|
||||
EXPECT_EQ(a(2), 3.f);
|
||||
EXPECT_EQ(a(3), 4.f);
|
||||
}
|
||||
@@ -11,6 +11,32 @@ class JsonOutput():
|
||||
all_params=[]
|
||||
all_json['parameters']=all_params
|
||||
|
||||
all_json["translation"] = {
|
||||
"items": {
|
||||
"parameters": {
|
||||
"list": {
|
||||
"key": "name",
|
||||
"translate": [ "shortDesc", "longDesc" ],
|
||||
"translate-global": ["category", "group"],
|
||||
"items": {
|
||||
"bitmask": {
|
||||
"list": {
|
||||
"key": "index",
|
||||
"translate": [ "description" ]
|
||||
}
|
||||
},
|
||||
"values": {
|
||||
"list": {
|
||||
"key": "value",
|
||||
"translate": [ "description" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
schema_map = {
|
||||
"short_desc": "shortDesc",
|
||||
"long_desc": "longDesc",
|
||||
|
||||
@@ -61,9 +61,8 @@ TEST_F(ArxRlsTest, test211)
|
||||
_rls.update(1, 2);
|
||||
_rls.update(3, 4);
|
||||
_rls.update(5, 6);
|
||||
const Vector<float, 4> coefficients = _rls.getCoefficients();
|
||||
float data_check[] = {-1.79f, 0.97f, 0.42f, -0.48f}; // generated from Python script
|
||||
const Vector<float, 4> coefficients_check(data_check);
|
||||
const Vector4f coefficients = _rls.getCoefficients();
|
||||
const Vector4f coefficients_check(-1.79f, 0.97f, 0.42f, -0.48f); // generated from Python script
|
||||
float eps = 1e-2;
|
||||
EXPECT_TRUE((coefficients - coefficients_check).abs().max() < eps);
|
||||
}
|
||||
|
||||
@@ -47,80 +47,80 @@ static constexpr int LON_DIM = 37;
|
||||
// Magnetic declination data in radians * 10^-4
|
||||
// Model: WMM-2020,
|
||||
// Version: 0.5.1.11,
|
||||
// Date: 2023.074,
|
||||
// Date: 2023.2246,
|
||||
static constexpr const int16_t declination_table[19][37] {
|
||||
// LONGITUDE: -180, -170, -160, -150, -140, -130, -120, -110, -100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180,
|
||||
/* LAT: -90 */ { 25974, 24228, 22483, 20738, 18992, 17247, 15502, 13756, 12011, 10266, 8520, 6775, 5030, 3285, 1539, -206, -1951, -3697, -5442, -7187, -8932,-10678,-12423,-14168,-15914,-17659,-19404,-21150,-22895,-24641,-26386,-28131,-29877, 31210, 29464, 27719, 25974, },
|
||||
/* LAT: -80 */ { 22539, 20409, 18470, 16697, 15057, 13519, 12055, 10644, 9269, 7919, 6588, 5269, 3960, 2655, 1348, 28, -1314, -2686, -4097, -5550, -7045, -8583,-10161,-11781,-13446,-15165,-16951,-18824,-20807,-22927,-25201,-27636,-30204, 29989, 27372, 24868, 22539, },
|
||||
/* LAT: -70 */ { 14980, 13581, 12454, 11491, 10621, 9788, 8946, 8058, 7105, 6086, 5016, 3923, 2838, 1784, 762, -247, -1285, -2392, -3595, -4897, -6279, -7711, -9160,-10603,-12030,-13447,-14876,-16363,-17989,-19907,-22434,-26242, 30671, 24126, 19621, 16851, 14980, },
|
||||
/* LAT: -60 */ { 8431, 8183, 7900, 7624, 7369, 7114, 6804, 6370, 5754, 4934, 3932, 2821, 1702, 676, -203, -958, -1687, -2511, -3518, -4720, -6054, -7427, -8749, -9960,-11024,-11923,-12637,-13132,-13304,-12855,-10750, -3465, 4953, 7682, 8446, 8568, 8431, },
|
||||
/* LAT: -50 */ { 5493, 5528, 5471, 5380, 5305, 5267, 5231, 5103, 4758, 4093, 3081, 1808, 468, -708, -1573, -2132, -2525, -2967, -3658, -4680, -5931, -7213, -8355, -9255, -9851,-10086, -9887, -9126, -7614, -5249, -2342, 406, 2516, 3941, 4815, 5289, 5493, },
|
||||
/* LAT: -40 */ { 3960, 4053, 4059, 4013, 3952, 3917, 3921, 3909, 3735, 3198, 2172, 728, -835, -2144, -3000, -3444, -3621, -3678, -3852, -4435, -5425, -6507, -7392, -7926, -8027, -7642, -6746, -5359, -3650, -1951, -494, 727, 1771, 2639, 3297, 3728, 3960, },
|
||||
/* LAT: -30 */ { 2988, 3074, 3103, 3087, 3027, 2948, 2887, 2852, 2725, 2245, 1205, -318, -1925, -3172, -3904, -4243, -4315, -4097, -3662, -3454, -3836, -4592, -5288, -5631, -5498, -4904, -3940, -2735, -1532, -593, 81, 681, 1306, 1912, 2424, 2788, 2988, },
|
||||
/* LAT: -20 */ { 2346, 2391, 2407, 2407, 2363, 2267, 2158, 2082, 1936, 1438, 377, -1116, -2593, -3648, -4172, -4280, -4070, -3504, -2640, -1851, -1591, -1957, -2607, -3071, -3101, -2736, -2098, -1284, -514, -30, 229, 529, 972, 1454, 1880, 2191, 2346, },
|
||||
/* LAT: -10 */ { 1952, 1946, 1923, 1917, 1888, 1801, 1689, 1597, 1412, 860, -206, -1586, -2856, -3678, -3935, -3699, -3119, -2335, -1489, -739, -282, -324, -798, -1303, -1511, -1418, -1103, -605, -113, 123, 168, 326, 699, 1142, 1540, 1831, 1952, },
|
||||
/* LAT: 0 */ { 1739, 1705, 1647, 1636, 1624, 1553, 1445, 1330, 1075, 454, -589, -1816, -2866, -3445, -3435, -2928, -2158, -1377, -727, -193, 217, 323, 39, -378, -630, -684, -586, -326, -39, 46, -19, 67, 411, 859, 1283, 1607, 1739, },
|
||||
/* LAT: 10 */ { 1601, 1609, 1565, 1580, 1604, 1553, 1429, 1240, 864, 146, -875, -1949, -2771, -3104, -2893, -2282, -1505, -796, -283, 96, 421, 566, 401, 78, -155, -262, -288, -209, -108, -153, -296, -271, 33, 493, 978, 1389, 1601, },
|
||||
/* LAT: 20 */ { 1414, 1563, 1623, 1714, 1799, 1777, 1620, 1316, 772, -84, -1125, -2073, -2665, -2769, -2437, -1833, -1122, -474, -16, 292, 550, 694, 601, 357, 159, 40, -55, -123, -206, -398, -638, -697, -461, -10, 535, 1056, 1414, },
|
||||
/* LAT: 30 */ { 1108, 1475, 1735, 1959, 2118, 2128, 1939, 1516, 789, -238, -1352, -2225, -2635, -2570, -2169, -1589, -933, -316, 144, 449, 679, 824, 802, 652, 504, 378, 217, 1, -285, -662, -1032, -1191, -1030, -601, -23, 587, 1108, },
|
||||
/* LAT: 40 */ { 746, 1331, 1826, 2219, 2469, 2513, 2298, 1765, 855, -368, -1602, -2463, -2780, -2626, -2180, -1587, -934, -305, 204, 568, 837, 1034, 1125, 1114, 1038, 888, 615, 198, -346, -954, -1475, -1718, -1599, -1181, -583, 88, 746, },
|
||||
/* LAT: 50 */ { 449, 1195, 1877, 2436, 2805, 2913, 2686, 2034, 897, -593, -2008, -2918, -3211, -3019, -2529, -1883, -1173, -476, 139, 644, 1062, 1415, 1693, 1862, 1880, 1689, 1238, 523, -377, -1280, -1957, -2240, -2113, -1673, -1040, -312, 449, },
|
||||
/* LAT: 60 */ { 244, 1095, 1901, 2599, 3107, 3324, 3116, 2312, 809, -1137, -2844, -3822, -4075, -3817, -3246, -2502, -1676, -837, -30, 721, 1412, 2042, 2583, 2976, 3133, 2940, 2293, 1167, -254, -1573, -2437, -2742, -2576, -2084, -1396, -601, 244, },
|
||||
/* LAT: 70 */ { -8, 925, 1822, 2622, 3241, 3541, 3301, 2190, -8, -2686, -4631, -5465, -5483, -5007, -4243, -3312, -2290, -1226, -152, 907, 1931, 2896, 3763, 4468, 4912, 4938, 4317, 2828, 621, -1489, -2783, -3223, -3065, -2537, -1794, -930, -8, },
|
||||
/* LAT: 80 */ { -771, 149, 1000, 1691, 2080, 1915, 776, -1705, -4800, -6913, -7700, -7604, -7000, -6100, -5021, -3830, -2570, -1269, 54, 1379, 2692, 3974, 5202, 6341, 7339, 8100, 8444, 7991, 6025, 2161, -1488, -3200, -3553, -3219, -2541, -1692, -771, },
|
||||
/* LAT: 90 */ { -29638,-27893,-26147,-24402,-22657,-20911,-19166,-17421,-15675,-13930,-12185,-10440, -8695, -6949, -5204, -3459, -1714, 31, 1776, 3521, 5267, 7012, 8757, 10503, 12248, 13993, 15739, 17484, 19229, 20975, 22720, 24466, 26211, 27957, 29702,-31384,-29638, },
|
||||
/* LAT: -90 */ { 25970, 24224, 22479, 20734, 18988, 17243, 15498, 13752, 12007, 10262, 8517, 6771, 5026, 3281, 1535, -210, -1955, -3700, -5446, -7191, -8936,-10682,-12427,-14172,-15918,-17663,-19408,-21154,-22899,-24644,-26390,-28135,-29880, 31206, 29461, 27715, 25970, },
|
||||
/* LAT: -80 */ { 22534, 20405, 18467, 16694, 15054, 13516, 12053, 10642, 9267, 7917, 6585, 5267, 3958, 2653, 1346, 26, -1316, -2689, -4100, -5553, -7049, -8586,-10165,-11785,-13450,-15170,-16956,-18829,-20813,-22932,-25208,-27642,-30211, 29983, 27366, 24863, 22534, },
|
||||
/* LAT: -70 */ { 14981, 13582, 12454, 11491, 10621, 9788, 8945, 8057, 7103, 6084, 5014, 3921, 2837, 1783, 762, -248, -1286, -2393, -3597, -4899, -6283, -7715, -9164,-10608,-12035,-13452,-14881,-16369,-17996,-19915,-22444,-26255, 30657, 24120, 19621, 16852, 14981, },
|
||||
/* LAT: -60 */ { 8435, 8187, 7903, 7626, 7370, 7114, 6804, 6370, 5753, 4932, 3930, 2819, 1700, 675, -202, -957, -1686, -2510, -3519, -4722, -6058, -7431, -8754, -9965,-11029,-11927,-12642,-13136,-13308,-12859,-10752, -3452, 4968, 7692, 8453, 8574, 8435, },
|
||||
/* LAT: -50 */ { 5496, 5532, 5474, 5382, 5306, 5267, 5231, 5103, 4757, 4092, 3079, 1805, 466, -709, -1572, -2129, -2522, -2964, -3657, -4682, -5935, -7218, -8360, -9260, -9854,-10088, -9888, -9125, -7612, -5246, -2339, 410, 2520, 3945, 4819, 5293, 5496, },
|
||||
/* LAT: -40 */ { 3963, 4055, 4061, 4015, 3952, 3917, 3921, 3909, 3734, 3196, 2169, 724, -838, -2146, -3000, -3442, -3617, -3673, -3849, -4435, -5429, -6513, -7397, -7930, -8029, -7642, -6744, -5356, -3647, -1949, -493, 728, 1772, 2641, 3299, 3731, 3963, },
|
||||
/* LAT: -30 */ { 2990, 3076, 3105, 3088, 3027, 2947, 2886, 2851, 2724, 2242, 1201, -323, -1930, -3175, -3905, -4241, -4312, -4092, -3656, -3452, -3839, -4597, -5292, -5633, -5498, -4902, -3937, -2732, -1530, -592, 81, 680, 1306, 1912, 2425, 2790, 2990, },
|
||||
/* LAT: -20 */ { 2348, 2393, 2409, 2407, 2363, 2266, 2157, 2080, 1934, 1436, 372, -1122, -2599, -3651, -4172, -4278, -4066, -3498, -2633, -1847, -1591, -1960, -2610, -3072, -3100, -2734, -2096, -1282, -513, -30, 228, 528, 971, 1455, 1881, 2192, 2348, },
|
||||
/* LAT: -10 */ { 1954, 1948, 1924, 1917, 1887, 1800, 1687, 1595, 1410, 857, -211, -1592, -2861, -3680, -3934, -3696, -3114, -2329, -1484, -735, -280, -324, -800, -1304, -1511, -1416, -1101, -604, -112, 123, 166, 324, 698, 1142, 1540, 1832, 1954, },
|
||||
/* LAT: 0 */ { 1741, 1707, 1648, 1637, 1623, 1551, 1443, 1327, 1072, 450, -593, -1821, -2870, -3446, -3432, -2923, -2153, -1372, -723, -190, 220, 324, 39, -378, -629, -683, -585, -325, -39, 45, -22, 64, 409, 858, 1284, 1609, 1741, },
|
||||
/* LAT: 10 */ { 1603, 1611, 1566, 1580, 1604, 1552, 1426, 1237, 861, 143, -878, -1953, -2773, -3103, -2890, -2278, -1500, -791, -279, 99, 423, 568, 401, 79, -154, -262, -287, -210, -109, -154, -299, -274, 31, 492, 978, 1390, 1603, },
|
||||
/* LAT: 20 */ { 1415, 1564, 1623, 1713, 1798, 1776, 1617, 1313, 768, -87, -1128, -2075, -2665, -2767, -2433, -1828, -1117, -470, -13, 295, 553, 696, 602, 358, 160, 41, -54, -124, -207, -400, -641, -700, -463, -11, 535, 1056, 1415, },
|
||||
/* LAT: 30 */ { 1108, 1474, 1734, 1958, 2117, 2126, 1937, 1513, 786, -241, -1354, -2225, -2634, -2567, -2165, -1584, -929, -312, 148, 452, 682, 826, 803, 654, 505, 379, 217, 0, -287, -664, -1035, -1194, -1031, -602, -24, 587, 1108, },
|
||||
/* LAT: 40 */ { 744, 1329, 1824, 2217, 2467, 2511, 2296, 1762, 853, -370, -1602, -2461, -2777, -2622, -2175, -1582, -929, -300, 208, 571, 840, 1036, 1127, 1115, 1039, 889, 615, 196, -348, -957, -1478, -1720, -1601, -1183, -584, 86, 744, },
|
||||
/* LAT: 50 */ { 445, 1191, 1873, 2433, 2802, 2911, 2683, 2032, 895, -593, -2006, -2914, -3205, -3013, -2523, -1877, -1167, -470, 144, 649, 1066, 1418, 1696, 1864, 1881, 1690, 1238, 520, -380, -1284, -1960, -2242, -2115, -1674, -1042, -315, 445, },
|
||||
/* LAT: 60 */ { 238, 1088, 1894, 2593, 3102, 3320, 3112, 2310, 809, -1133, -2837, -3814, -4067, -3809, -3238, -2494, -1669, -830, -23, 727, 1418, 2047, 2587, 2980, 3135, 2941, 2292, 1163, -259, -1578, -2440, -2744, -2578, -2087, -1400, -606, 238, },
|
||||
/* LAT: 70 */ { -19, 913, 1810, 2611, 3230, 3532, 3294, 2188, -1, -2670, -4613, -5448, -5469, -4994, -4231, -3301, -2280, -1217, -144, 914, 1938, 2903, 3769, 4473, 4916, 4940, 4317, 2823, 612, -1498, -2790, -3229, -3071, -2544, -1802, -940, -19, },
|
||||
/* LAT: 80 */ { -798, 122, 973, 1664, 2054, 1893, 767, -1687, -4757, -6867, -7661, -7573, -6974, -6078, -5002, -3813, -2554, -1254, 67, 1392, 2705, 3986, 5214, 6353, 7351, 8112, 8455, 8000, 6023, 2136, -1525, -3233, -3583, -3246, -2567, -1718, -798, },
|
||||
/* LAT: 90 */ { -29581,-27835,-26090,-24344,-22599,-20854,-19108,-17363,-15618,-13872,-12127,-10382, -8637, -6892, -5147, -3401, -1656, 89, 1834, 3579, 5324, 7070, 8815, 10560, 12306, 14051, 15796, 17542, 19287, 21033, 22778, 24524, 26269, 28015, 29760,-31326,-29581, },
|
||||
};
|
||||
|
||||
// Magnetic inclination data in radians * 10^-4
|
||||
// Model: WMM-2020,
|
||||
// Version: 0.5.1.11,
|
||||
// Date: 2023.074,
|
||||
// Date: 2023.2246,
|
||||
static constexpr const int16_t inclination_table[19][37] {
|
||||
// LONGITUDE: -180, -170, -160, -150, -140, -130, -120, -110, -100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180,
|
||||
/* LAT: -90 */ { -12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568,-12568, },
|
||||
/* LAT: -80 */ { -13652,-13518,-13358,-13177,-12983,-12782,-12578,-12378,-12187,-12011,-11855,-11721,-11610,-11524,-11461,-11419,-11399,-11402,-11429,-11483,-11567,-11681,-11826,-12000,-12198,-12415,-12645,-12878,-13106,-13318,-13504,-13654,-13758,-13809,-13805,-13751,-13652, },
|
||||
/* LAT: -70 */ { -14100,-13781,-13462,-13139,-12807,-12464,-12109,-11752,-11409,-11101,-10849,-10666,-10554,-10502,-10488,-10491,-10497,-10505,-10528,-10583,-10692,-10867,-11114,-11429,-11803,-12221,-12669,-13133,-13599,-14052,-14469,-14813,-15000,-14945,-14714,-14416,-14100, },
|
||||
/* LAT: -60 */ { -13515,-13161,-12823,-12490,-12147,-11774,-11360,-10905,-10438,-10009, -9680, -9506, -9504, -9641, -9845,-10036,-10159,-10199,-10185,-10169,-10216,-10376,-10668,-11078,-11578,-12135,-12722,-13318,-13906,-14468,-14965,-15254,-15075,-14689,-14282,-13889,-13515, },
|
||||
/* LAT: -50 */ { -12494,-12152,-11820,-11498,-11175,-10828,-10429, -9958, -9429, -8909, -8521, -8399, -8603, -9065, -9628,-10137,-10492,-10650,-10616,-10461,-10319,-10327,-10551,-10971,-11515,-12108,-12695,-13233,-13678,-13975,-14083,-14010,-13806,-13522,-13193,-12845,-12494, },
|
||||
/* LAT: -40 */ { -11239,-10890,-10542,-10196, -9857, -9519, -9159, -8734, -8214, -7650, -7227, -7191, -7656, -8482, -9403,-10229,-10884,-11313,-11446,-11272,-10927,-10657,-10655,-10942,-11406,-11912,-12356,-12676,-12833,-12838,-12748,-12612,-12433,-12202,-11915,-11587,-11239, },
|
||||
/* LAT: -30 */ { -9602, -9222, -8841, -8450, -8058, -7683, -7328, -6938, -6426, -5815, -5368, -5459, -6238, -7445, -8695, -9786,-10696,-11400,-11791,-11772,-11394,-10886,-10557,-10563,-10818,-11139,-11394,-11504,-11440,-11264,-11091,-10959,-10815,-10609,-10328, -9981, -9602, },
|
||||
/* LAT: -20 */ { -7372, -6929, -6509, -6080, -5636, -5206, -4817, -4407, -3842, -3158, -2716, -2989, -4113, -5732, -7358, -8721, -9779,-10547,-10977,-11002,-10632,-10014, -9458, -9219, -9271, -9434, -9573, -9588, -9414, -9143, -8952, -8869, -8769, -8563, -8247, -7833, -7372, },
|
||||
/* LAT: -10 */ { -4417, -3876, -3419, -2981, -2523, -2073, -1661, -1211, -588, 113, 467, 25, -1319, -3245, -5217, -6815, -7899, -8523, -8780, -8710, -8293, -7603, -6940, -6599, -6563, -6656, -6771, -6793, -6604, -6309, -6158, -6175, -6141, -5928, -5544, -5014, -4417, },
|
||||
/* LAT: 0 */ { -909, -280, 189, 593, 1012, 1428, 1816, 2255, 2834, 3407, 3602, 3092, 1782, -137, -2178, -3815, -4810, -5227, -5279, -5102, -4655, -3933, -3228, -2861, -2801, -2870, -2993, -3065, -2935, -2701, -2652, -2804, -2876, -2693, -2269, -1636, -909, },
|
||||
/* LAT: 10 */ { 2559, 3190, 3628, 3970, 4326, 4692, 5042, 5424, 5871, 6236, 6266, 5767, 4674, 3101, 1413, 48, -744, -981, -883, -643, -226, 418, 1051, 1385, 1448, 1406, 1307, 1216, 1258, 1360, 1279, 1003, 803, 871, 1224, 1829, 2559, },
|
||||
/* LAT: 20 */ { 5415, 5946, 6328, 6624, 6938, 7281, 7622, 7966, 8295, 8491, 8399, 7930, 7088, 5988, 4865, 3963, 3443, 3332, 3487, 3734, 4068, 4536, 4997, 5251, 5309, 5294, 5247, 5189, 5176, 5156, 4978, 4639, 4335, 4243, 4415, 4840, 5415, },
|
||||
/* LAT: 30 */ { 7568, 7943, 8261, 8544, 8853, 9200, 9556, 9895, 10169, 10279, 10131, 9706, 9074, 8362, 7704, 7196, 6910, 6873, 7019, 7233, 7482, 7783, 8072, 8245, 8303, 8318, 8322, 8312, 8288, 8204, 7979, 7623, 7264, 7043, 7027, 7222, 7568, },
|
||||
/* LAT: 40 */ { 9266, 9487, 9743, 10028, 10355, 10715, 11082, 11419, 11669, 11749, 11597, 11236, 10762, 10290, 9896, 9615, 9469, 9468, 9581, 9744, 9921, 10106, 10278, 10403, 10482, 10544, 10600, 10633, 10615, 10503, 10259, 9907, 9538, 9253, 9110, 9123, 9266, },
|
||||
/* LAT: 50 */ { 10802, 10923, 11124, 11393, 11716, 12069, 12422, 12737, 12958, 13016, 12876, 12578, 12214, 11870, 11596, 11411, 11320, 11318, 11386, 11491, 11606, 11722, 11839, 11955, 12074, 12197, 12311, 12384, 12373, 12247, 11999, 11670, 11330, 11045, 10856, 10776, 10802, },
|
||||
/* LAT: 60 */ { 12319, 12391, 12541, 12758, 13027, 13327, 13628, 13894, 14069, 14096, 13961, 13713, 13425, 13155, 12935, 12779, 12690, 12660, 12676, 12725, 12794, 12879, 12986, 13119, 13278, 13455, 13619, 13728, 13732, 13611, 13385, 13106, 12828, 12591, 12421, 12329, 12319, },
|
||||
/* LAT: 70 */ { 13758, 13799, 13893, 14034, 14212, 14415, 14622, 14803, 14908, 14890, 14755, 14554, 14338, 14134, 13961, 13827, 13733, 13679, 13660, 13674, 13716, 13789, 13893, 14030, 14197, 14384, 14568, 14708, 14753, 14680, 14518, 14320, 14125, 13961, 13840, 13771, 13758, },
|
||||
/* LAT: 80 */ { 14995, 15007, 15043, 15102, 15177, 15261, 15339, 15385, 15369, 15293, 15183, 15060, 14938, 14824, 14725, 14643, 14581, 14541, 14522, 14526, 14553, 14603, 14674, 14767, 14879, 15006, 15142, 15274, 15381, 15425, 15385, 15297, 15201, 15116, 15050, 15010, 14995, },
|
||||
/* LAT: 90 */ { 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, },
|
||||
/* LAT: -90 */ { -12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567,-12567, },
|
||||
/* LAT: -80 */ { -13651,-13517,-13356,-13176,-12982,-12781,-12577,-12377,-12186,-12010,-11854,-11720,-11610,-11523,-11460,-11418,-11398,-11401,-11428,-11482,-11566,-11680,-11825,-11999,-12198,-12415,-12644,-12877,-13105,-13317,-13504,-13653,-13757,-13808,-13804,-13749,-13651, },
|
||||
/* LAT: -70 */ { -14099,-13780,-13461,-13138,-12806,-12462,-12108,-11751,-11408,-11101,-10849,-10666,-10554,-10502,-10488,-10490,-10496,-10504,-10527,-10582,-10691,-10866,-11113,-11429,-11802,-12221,-12669,-13134,-13600,-14052,-14469,-14813,-14999,-14944,-14713,-14414,-14099, },
|
||||
/* LAT: -60 */ { -13514,-13160,-12822,-12489,-12146,-11773,-11359,-10904,-10437,-10008, -9680, -9506, -9505, -9643, -9846,-10037,-10159,-10199,-10183,-10167,-10215,-10375,-10667,-11078,-11578,-12136,-12722,-13319,-13907,-14469,-14966,-15255,-15075,-14689,-14282,-13888,-13514, },
|
||||
/* LAT: -50 */ { -12494,-12151,-11820,-11497,-11174,-10827,-10429, -9958, -9429, -8909, -8522, -8400, -8605, -9068, -9631,-10139,-10493,-10650,-10614,-10458,-10316,-10325,-10551,-10971,-11516,-12110,-12696,-13234,-13679,-13976,-14083,-14010,-13806,-13522,-13193,-12845,-12494, },
|
||||
/* LAT: -40 */ { -11239,-10890,-10541,-10196, -9856, -9518, -9158, -8734, -8214, -7650, -7228, -7194, -7661, -8488, -9408,-10234,-10887,-11315,-11445,-11269,-10923,-10655,-10655,-10942,-11408,-11913,-12357,-12676,-12833,-12838,-12748,-12612,-12434,-12202,-11915,-11587,-11239, },
|
||||
/* LAT: -30 */ { -9602, -9221, -8840, -8449, -8057, -7682, -7327, -6938, -6426, -5816, -5369, -5463, -6245, -7453, -8702, -9793,-10701,-11404,-11792,-11771,-11391,-10883,-10556,-10563,-10819,-11140,-11394,-11503,-11439,-11263,-11091,-10959,-10815,-10610,-10328, -9982, -9602, },
|
||||
/* LAT: -20 */ { -7372, -6928, -6507, -6078, -5634, -5205, -4816, -4406, -3842, -3158, -2718, -2995, -4122, -5743, -7368, -8729, -9786,-10552,-10979,-11002,-10629,-10011, -9456, -9218, -9271, -9434, -9573, -9587, -9413, -9141, -8951, -8869, -8770, -8565, -8248, -7834, -7372, },
|
||||
/* LAT: -10 */ { -4417, -3875, -3417, -2978, -2521, -2071, -1660, -1210, -588, 112, 464, 18, -1330, -3258, -5229, -6824, -7906, -8527, -8782, -8710, -8291, -7600, -6937, -6597, -6561, -6654, -6770, -6791, -6601, -6306, -6157, -6175, -6143, -5930, -5547, -5016, -4417, },
|
||||
/* LAT: 0 */ { -910, -279, 192, 596, 1015, 1431, 1819, 2256, 2834, 3406, 3598, 3086, 1772, -150, -2190, -3825, -4815, -5230, -5280, -5102, -4653, -3929, -3224, -2858, -2799, -2867, -2990, -3062, -2932, -2698, -2650, -2804, -2878, -2696, -2272, -1638, -910, },
|
||||
/* LAT: 10 */ { 2558, 3191, 3630, 3973, 4328, 4695, 5044, 5425, 5870, 6235, 6262, 5761, 4666, 3091, 1402, 40, -749, -983, -883, -642, -224, 421, 1054, 1388, 1451, 1410, 1311, 1220, 1262, 1363, 1281, 1003, 801, 868, 1221, 1827, 2558, },
|
||||
/* LAT: 20 */ { 5414, 5947, 6329, 6626, 6940, 7283, 7623, 7966, 8294, 8489, 8396, 7925, 7081, 5981, 4858, 3957, 3439, 3331, 3487, 3734, 4069, 4539, 4999, 5253, 5311, 5297, 5251, 5193, 5179, 5158, 4979, 4639, 4334, 4241, 4413, 4839, 5414, },
|
||||
/* LAT: 30 */ { 7568, 7943, 8262, 8545, 8854, 9201, 9557, 9895, 10168, 10277, 10128, 9702, 9070, 8358, 7699, 7193, 6908, 6872, 7019, 7233, 7483, 7784, 8073, 8247, 8305, 8321, 8325, 8315, 8291, 8206, 7980, 7623, 7263, 7042, 7026, 7222, 7568, },
|
||||
/* LAT: 40 */ { 9266, 9487, 9743, 10029, 10355, 10715, 11081, 11418, 11668, 11747, 11594, 11233, 10759, 10287, 9893, 9613, 9467, 9467, 9581, 9744, 9921, 10107, 10280, 10405, 10483, 10546, 10602, 10635, 10617, 10504, 10260, 9907, 9538, 9253, 9110, 9122, 9266, },
|
||||
/* LAT: 50 */ { 10802, 10923, 11124, 11393, 11715, 12068, 12421, 12736, 12956, 13014, 12873, 12576, 12212, 11868, 11594, 11410, 11319, 11318, 11387, 11491, 11606, 11723, 11840, 11956, 12075, 12199, 12313, 12385, 12375, 12248, 12000, 11671, 11330, 11045, 10856, 10776, 10802, },
|
||||
/* LAT: 60 */ { 12319, 12391, 12540, 12757, 13026, 13326, 13627, 13892, 14067, 14095, 13960, 13711, 13424, 13153, 12934, 12779, 12689, 12660, 12677, 12725, 12794, 12880, 12987, 13120, 13280, 13456, 13621, 13729, 13733, 13611, 13385, 13106, 12828, 12591, 12421, 12329, 12319, },
|
||||
/* LAT: 70 */ { 13758, 13799, 13892, 14033, 14211, 14413, 14621, 14801, 14906, 14888, 14753, 14554, 14337, 14134, 13961, 13827, 13733, 13679, 13661, 13674, 13717, 13790, 13894, 14031, 14198, 14386, 14570, 14709, 14754, 14680, 14518, 14320, 14126, 13961, 13840, 13771, 13758, },
|
||||
/* LAT: 80 */ { 14994, 15006, 15042, 15100, 15176, 15259, 15337, 15383, 15368, 15292, 15182, 15060, 14938, 14824, 14725, 14643, 14582, 14541, 14523, 14527, 14554, 14603, 14675, 14768, 14880, 15007, 15143, 15275, 15383, 15426, 15385, 15297, 15201, 15116, 15050, 15009, 14994, },
|
||||
/* LAT: 90 */ { 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15397, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, 15398, },
|
||||
};
|
||||
|
||||
// Magnetic strength data in milli-Gauss * 10
|
||||
// Model: WMM-2020,
|
||||
// Version: 0.5.1.11,
|
||||
// Date: 2023.074,
|
||||
// Date: 2023.2246,
|
||||
static constexpr const int16_t strength_table[19][37] {
|
||||
// LONGITUDE: -180, -170, -160, -150, -140, -130, -120, -110, -100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180,
|
||||
/* LAT: -90 */ { 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, 5448, },
|
||||
/* LAT: -80 */ { 6055, 5991, 5912, 5820, 5716, 5605, 5486, 5365, 5242, 5122, 5008, 4903, 4809, 4730, 4667, 4622, 4598, 4596, 4618, 4664, 4735, 4829, 4944, 5076, 5220, 5370, 5519, 5663, 5794, 5907, 6000, 6069, 6113, 6132, 6127, 6101, 6055, },
|
||||
/* LAT: -70 */ { 6299, 6166, 6015, 5850, 5671, 5478, 5273, 5058, 4839, 4624, 4422, 4240, 4082, 3951, 3847, 3771, 3724, 3712, 3741, 3817, 3946, 4126, 4355, 4624, 4919, 5226, 5530, 5814, 6063, 6267, 6418, 6513, 6554, 6547, 6496, 6412, 6299, },
|
||||
/* LAT: -60 */ { 6185, 5992, 5790, 5581, 5361, 5127, 4870, 4592, 4299, 4010, 3743, 3516, 3337, 3203, 3104, 3031, 2980, 2960, 2987, 3078, 3247, 3499, 3827, 4214, 4636, 5071, 5492, 5876, 6200, 6449, 6612, 6690, 6691, 6627, 6513, 6362, 6185, },
|
||||
/* LAT: -50 */ { 5842, 5612, 5379, 5148, 4915, 4670, 4399, 4096, 3767, 3436, 3134, 2895, 2734, 2643, 2595, 2560, 2526, 2499, 2505, 2578, 2752, 3044, 3441, 3914, 4421, 4927, 5402, 5820, 6159, 6400, 6537, 6578, 6535, 6424, 6261, 6063, 5842, },
|
||||
/* LAT: -40 */ { 5392, 5146, 4900, 4660, 4426, 4188, 3933, 3649, 3335, 3009, 2711, 2489, 2373, 2347, 2366, 2387, 2391, 2378, 2365, 2394, 2526, 2804, 3224, 3739, 4286, 4810, 5276, 5664, 5955, 6143, 6230, 6233, 6163, 6031, 5850, 5631, 5392, },
|
||||
/* LAT: -30 */ { 4878, 4636, 4397, 4162, 3936, 3717, 3498, 3266, 3010, 2735, 2477, 2296, 2227, 2252, 2319, 2390, 2454, 2504, 2524, 2536, 2605, 2807, 3171, 3661, 4193, 4690, 5107, 5422, 5625, 5724, 5750, 5723, 5644, 5511, 5331, 5114, 4878, },
|
||||
/* LAT: -20 */ { 4321, 4107, 3898, 3693, 3497, 3314, 3146, 2982, 2804, 2606, 2415, 2282, 2242, 2286, 2376, 2486, 2614, 2741, 2828, 2863, 2889, 2987, 3229, 3615, 4066, 4493, 4840, 5073, 5178, 5185, 5155, 5108, 5026, 4898, 4731, 4534, 4321, },
|
||||
/* LAT: -10 */ { 3790, 3629, 3475, 3329, 3193, 3073, 2969, 2877, 2779, 2664, 2542, 2443, 2399, 2424, 2512, 2641, 2796, 2954, 3077, 3138, 3152, 3180, 3305, 3559, 3886, 4208, 4472, 4633, 4668, 4615, 4547, 4484, 4396, 4271, 4122, 3958, 3790, },
|
||||
/* LAT: 0 */ { 3412, 3319, 3234, 3161, 3106, 3068, 3041, 3022, 2997, 2948, 2870, 2775, 2696, 2666, 2709, 2812, 2945, 3080, 3194, 3269, 3299, 3322, 3398, 3556, 3766, 3980, 4159, 4264, 4270, 4202, 4114, 4021, 3910, 3779, 3644, 3520, 3412, },
|
||||
/* LAT: 10 */ { 3283, 3251, 3230, 3227, 3251, 3298, 3353, 3406, 3440, 3430, 3361, 3247, 3120, 3027, 3002, 3044, 3125, 3223, 3323, 3408, 3472, 3534, 3623, 3742, 3878, 4017, 4136, 4206, 4208, 4146, 4036, 3892, 3731, 3571, 3436, 3339, 3283, },
|
||||
/* LAT: 20 */ { 3399, 3402, 3427, 3481, 3572, 3693, 3821, 3938, 4018, 4030, 3957, 3815, 3649, 3510, 3435, 3424, 3460, 3533, 3630, 3727, 3818, 3917, 4028, 4140, 4249, 4361, 4464, 4529, 4539, 4480, 4343, 4140, 3913, 3703, 3540, 3439, 3399, },
|
||||
/* LAT: 30 */ { 3722, 3728, 3782, 3881, 4023, 4194, 4369, 4525, 4633, 4659, 4586, 4431, 4243, 4080, 3975, 3930, 3934, 3986, 4073, 4172, 4270, 4376, 4492, 4610, 4730, 4857, 4978, 5065, 5090, 5032, 4875, 4635, 4361, 4106, 3907, 3778, 3722, },
|
||||
/* LAT: 40 */ { 4222, 4219, 4283, 4406, 4572, 4759, 4942, 5098, 5203, 5229, 5161, 5013, 4827, 4654, 4526, 4452, 4426, 4449, 4510, 4590, 4677, 4774, 4889, 5023, 5174, 5336, 5488, 5598, 5636, 5581, 5425, 5187, 4913, 4653, 4443, 4297, 4222, },
|
||||
/* LAT: 50 */ { 4832, 4823, 4878, 4987, 5132, 5291, 5441, 5562, 5636, 5646, 5583, 5456, 5294, 5131, 4995, 4898, 4844, 4833, 4858, 4908, 4978, 5069, 5188, 5339, 5514, 5699, 5865, 5982, 6025, 5980, 5849, 5653, 5429, 5214, 5034, 4904, 4832, },
|
||||
/* LAT: 60 */ { 5392, 5378, 5405, 5467, 5552, 5646, 5733, 5800, 5834, 5826, 5772, 5679, 5559, 5431, 5312, 5216, 5150, 5117, 5115, 5143, 5200, 5287, 5405, 5552, 5719, 5887, 6034, 6137, 6180, 6158, 6075, 5949, 5804, 5661, 5539, 5447, 5392, },
|
||||
/* LAT: 70 */ { 5726, 5705, 5701, 5712, 5734, 5760, 5784, 5799, 5799, 5781, 5742, 5685, 5616, 5540, 5466, 5403, 5355, 5327, 5323, 5343, 5388, 5458, 5549, 5658, 5775, 5889, 5988, 6060, 6099, 6103, 6074, 6021, 5954, 5883, 5818, 5764, 5726, },
|
||||
/* LAT: 80 */ { 5790, 5772, 5757, 5745, 5734, 5725, 5715, 5703, 5689, 5671, 5649, 5624, 5597, 5571, 5546, 5526, 5513, 5508, 5513, 5528, 5554, 5589, 5632, 5680, 5729, 5777, 5820, 5854, 5878, 5891, 5893, 5886, 5872, 5853, 5831, 5810, 5790, },
|
||||
/* LAT: -90 */ { 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, 5447, },
|
||||
/* LAT: -80 */ { 6054, 5990, 5911, 5818, 5715, 5603, 5485, 5363, 5241, 5121, 5007, 4902, 4808, 4729, 4666, 4621, 4597, 4595, 4617, 4663, 4734, 4828, 4943, 5075, 5219, 5369, 5519, 5662, 5793, 5907, 5999, 6068, 6112, 6131, 6127, 6100, 6054, },
|
||||
/* LAT: -70 */ { 6298, 6165, 6014, 5848, 5669, 5477, 5272, 5057, 4838, 4623, 4420, 4238, 4081, 3950, 3846, 3770, 3723, 3711, 3740, 3817, 3945, 4126, 4355, 4623, 4919, 5226, 5530, 5814, 6064, 6267, 6418, 6513, 6554, 6546, 6496, 6411, 6298, },
|
||||
/* LAT: -60 */ { 6184, 5991, 5789, 5579, 5360, 5125, 4868, 4590, 4298, 4008, 3742, 3515, 3336, 3202, 3103, 3030, 2979, 2959, 2986, 3077, 3247, 3499, 3827, 4214, 4637, 5071, 5493, 5876, 6201, 6449, 6612, 6690, 6691, 6627, 6513, 6361, 6184, },
|
||||
/* LAT: -50 */ { 5842, 5611, 5378, 5147, 4914, 4669, 4398, 4095, 3766, 3434, 3133, 2894, 2733, 2643, 2594, 2559, 2525, 2498, 2504, 2577, 2752, 3044, 3442, 3915, 4422, 4928, 5403, 5821, 6159, 6400, 6538, 6578, 6535, 6424, 6261, 6062, 5842, },
|
||||
/* LAT: -40 */ { 5392, 5145, 4900, 4659, 4424, 4187, 3932, 3648, 3334, 3008, 2710, 2488, 2372, 2347, 2366, 2386, 2390, 2377, 2364, 2393, 2526, 2804, 3225, 3741, 4288, 4811, 5277, 5664, 5956, 6143, 6231, 6233, 6163, 6031, 5850, 5631, 5392, },
|
||||
/* LAT: -30 */ { 4877, 4636, 4396, 4161, 3935, 3716, 3497, 3265, 3009, 2734, 2476, 2295, 2226, 2252, 2318, 2389, 2454, 2503, 2523, 2535, 2604, 2807, 3172, 3663, 4195, 4691, 5108, 5423, 5625, 5724, 5751, 5723, 5644, 5511, 5331, 5114, 4877, },
|
||||
/* LAT: -20 */ { 4320, 4107, 3898, 3693, 3496, 3314, 3145, 2981, 2803, 2605, 2414, 2281, 2241, 2286, 2376, 2486, 2614, 2741, 2827, 2862, 2888, 2987, 3230, 3617, 4068, 4494, 4841, 5074, 5178, 5185, 5155, 5108, 5026, 4898, 4731, 4534, 4320, },
|
||||
/* LAT: -10 */ { 3790, 3628, 3475, 3328, 3192, 3072, 2969, 2876, 2778, 2663, 2541, 2442, 2398, 2424, 2512, 2641, 2797, 2954, 3076, 3137, 3151, 3180, 3306, 3560, 3887, 4209, 4473, 4634, 4668, 4615, 4548, 4484, 4396, 4271, 4122, 3958, 3790, },
|
||||
/* LAT: 0 */ { 3412, 3318, 3234, 3161, 3105, 3067, 3041, 3021, 2996, 2947, 2868, 2774, 2695, 2666, 2709, 2813, 2945, 3080, 3194, 3268, 3299, 3321, 3398, 3557, 3767, 3981, 4160, 4265, 4270, 4202, 4114, 4022, 3910, 3779, 3645, 3520, 3412, },
|
||||
/* LAT: 10 */ { 3282, 3251, 3230, 3226, 3250, 3297, 3352, 3405, 3439, 3429, 3359, 3245, 3119, 3026, 3001, 3044, 3125, 3224, 3324, 3408, 3472, 3535, 3624, 3743, 3879, 4018, 4137, 4207, 4209, 4146, 4036, 3893, 3731, 3572, 3436, 3339, 3282, },
|
||||
/* LAT: 20 */ { 3399, 3401, 3427, 3480, 3572, 3692, 3820, 3937, 4017, 4029, 3955, 3814, 3648, 3509, 3435, 3424, 3460, 3533, 3630, 3728, 3818, 3917, 4029, 4141, 4250, 4362, 4465, 4531, 4540, 4481, 4343, 4141, 3913, 3703, 3540, 3439, 3399, },
|
||||
/* LAT: 30 */ { 3722, 3728, 3782, 3880, 4022, 4193, 4368, 4524, 4631, 4658, 4585, 4430, 4242, 4079, 3975, 3930, 3934, 3986, 4074, 4172, 4270, 4377, 4493, 4611, 4731, 4859, 4980, 5066, 5091, 5033, 4876, 4636, 4361, 4107, 3907, 3778, 3722, },
|
||||
/* LAT: 40 */ { 4222, 4219, 4282, 4405, 4571, 4758, 4941, 5097, 5201, 5227, 5159, 5012, 4826, 4653, 4526, 4452, 4427, 4450, 4511, 4591, 4678, 4775, 4891, 5024, 5175, 5338, 5489, 5599, 5637, 5582, 5425, 5187, 4913, 4654, 4443, 4297, 4222, },
|
||||
/* LAT: 50 */ { 4832, 4823, 4877, 4985, 5131, 5290, 5439, 5561, 5635, 5644, 5582, 5456, 5294, 5131, 4995, 4898, 4844, 4833, 4858, 4909, 4979, 5070, 5189, 5340, 5515, 5700, 5866, 5983, 6026, 5981, 5850, 5654, 5430, 5214, 5035, 4904, 4832, },
|
||||
/* LAT: 60 */ { 5392, 5378, 5404, 5466, 5551, 5645, 5732, 5799, 5833, 5825, 5771, 5678, 5558, 5430, 5312, 5217, 5151, 5117, 5116, 5144, 5201, 5287, 5406, 5553, 5720, 5888, 6035, 6138, 6181, 6158, 6075, 5949, 5804, 5662, 5539, 5447, 5392, },
|
||||
/* LAT: 70 */ { 5726, 5705, 5701, 5712, 5733, 5759, 5783, 5798, 5798, 5780, 5742, 5685, 5616, 5540, 5467, 5403, 5355, 5328, 5324, 5344, 5389, 5458, 5550, 5659, 5776, 5890, 5989, 6061, 6100, 6103, 6074, 6021, 5954, 5884, 5818, 5764, 5726, },
|
||||
/* LAT: 80 */ { 5790, 5772, 5757, 5744, 5734, 5725, 5715, 5703, 5689, 5671, 5649, 5624, 5598, 5571, 5546, 5526, 5513, 5508, 5513, 5529, 5554, 5590, 5632, 5680, 5730, 5778, 5820, 5855, 5879, 5892, 5894, 5887, 5872, 5853, 5832, 5810, 5790, },
|
||||
/* LAT: 90 */ { 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, 5683, },
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -54,7 +54,7 @@ AirspeedValidator::update_airspeed_validator(const airspeed_validator_update_dat
|
||||
update_CAS_scale_applied();
|
||||
update_CAS_TAS(input_data.air_pressure_pa, input_data.air_temperature_celsius);
|
||||
update_wind_estimator(input_data.timestamp, input_data.airspeed_true_raw, input_data.lpos_valid,
|
||||
input_data.ground_velocity, input_data.lpos_evh, input_data.lpos_evv, input_data.att_q);
|
||||
input_data.ground_velocity, input_data.lpos_evh, input_data.lpos_evv, input_data.q_att);
|
||||
update_in_fixed_wing_flight(input_data.in_fixed_wing_flight);
|
||||
check_airspeed_data_stuck(input_data.timestamp);
|
||||
check_load_factor(input_data.accel_z);
|
||||
@@ -72,20 +72,18 @@ AirspeedValidator::reset_airspeed_to_invalid(const uint64_t timestamp)
|
||||
|
||||
void
|
||||
AirspeedValidator::update_wind_estimator(const uint64_t time_now_usec, float airspeed_true_raw, bool lpos_valid,
|
||||
const matrix::Vector3f &vI, float lpos_evh, float lpos_evv, const float att_q[4])
|
||||
const matrix::Vector3f &vI, float lpos_evh, float lpos_evv, const Quatf &q_att)
|
||||
{
|
||||
_wind_estimator.update(time_now_usec);
|
||||
|
||||
if (lpos_valid && _in_fixed_wing_flight) {
|
||||
|
||||
Quatf q(att_q);
|
||||
|
||||
// airspeed fusion (with raw TAS)
|
||||
const float hor_vel_variance = lpos_evh * lpos_evh;
|
||||
_wind_estimator.fuse_airspeed(time_now_usec, airspeed_true_raw, vI, hor_vel_variance, q);
|
||||
_wind_estimator.fuse_airspeed(time_now_usec, airspeed_true_raw, vI, hor_vel_variance, q_att);
|
||||
|
||||
// sideslip fusion
|
||||
_wind_estimator.fuse_beta(time_now_usec, vI, hor_vel_variance, q);
|
||||
_wind_estimator.fuse_beta(time_now_usec, vI, hor_vel_variance, q_att);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ struct airspeed_validator_update_data {
|
||||
bool lpos_valid;
|
||||
float lpos_evh;
|
||||
float lpos_evv;
|
||||
float att_q[4];
|
||||
matrix::Quatf q_att;
|
||||
float air_pressure_pa;
|
||||
float air_temperature_celsius;
|
||||
float accel_z;
|
||||
@@ -179,7 +179,7 @@ private:
|
||||
|
||||
void update_wind_estimator(const uint64_t timestamp, float airspeed_true_raw, bool lpos_valid,
|
||||
const matrix::Vector3f &vI,
|
||||
float lpos_evh, float lpos_evv, const float att_q[4]);
|
||||
float lpos_evh, float lpos_evv, const Quatf &q_att);
|
||||
void update_CAS_scale_validated(bool lpos_valid, const matrix::Vector3f &vI, float airspeed_true_raw);
|
||||
void update_CAS_scale_applied();
|
||||
void update_CAS_TAS(float air_pressure_pa, float air_temperature_celsius);
|
||||
|
||||
@@ -128,7 +128,6 @@ private:
|
||||
estimator_status_s _estimator_status {};
|
||||
vehicle_acceleration_s _accel {};
|
||||
vehicle_air_data_s _vehicle_air_data {};
|
||||
vehicle_attitude_s _vehicle_attitude {};
|
||||
vehicle_land_detected_s _vehicle_land_detected {};
|
||||
vehicle_local_position_s _vehicle_local_position {};
|
||||
vehicle_status_s _vehicle_status {};
|
||||
@@ -142,6 +141,7 @@ private:
|
||||
int32_t _prev_number_of_airspeed_sensors{0}; /**< number of airspeed sensors in previous loop (to detect a new added sensor)*/
|
||||
AirspeedValidator _airspeed_validator[MAX_NUM_AIRSPEED_SENSORS] {}; /**< airspeedValidator instances (one for each sensor) */
|
||||
|
||||
matrix::Quatf _q_att;
|
||||
hrt_abstime _time_now_usec{0};
|
||||
int _valid_airspeed_index{-2}; /**< index of currently chosen (valid) airspeed sensor */
|
||||
int _prev_airspeed_index{-2}; /**< previously chosen airspeed sensor index */
|
||||
@@ -350,10 +350,7 @@ AirspeedModule::Run()
|
||||
input_data.lpos_valid = _vehicle_local_position_valid;
|
||||
input_data.lpos_evh = _vehicle_local_position.evh;
|
||||
input_data.lpos_evv = _vehicle_local_position.evv;
|
||||
input_data.att_q[0] = _vehicle_attitude.q[0];
|
||||
input_data.att_q[1] = _vehicle_attitude.q[1];
|
||||
input_data.att_q[2] = _vehicle_attitude.q[2];
|
||||
input_data.att_q[3] = _vehicle_attitude.q[3];
|
||||
input_data.q_att = _q_att;
|
||||
input_data.air_pressure_pa = _vehicle_air_data.baro_pressure_pa;
|
||||
input_data.accel_z = _accel.xyz[2];
|
||||
input_data.vel_test_ratio = _estimator_status.vel_test_ratio;
|
||||
@@ -498,13 +495,25 @@ void AirspeedModule::poll_topics()
|
||||
_estimator_status_sub.update(&_estimator_status);
|
||||
_vehicle_acceleration_sub.update(&_accel);
|
||||
_vehicle_air_data_sub.update(&_vehicle_air_data);
|
||||
_vehicle_attitude_sub.update(&_vehicle_attitude);
|
||||
_vehicle_land_detected_sub.update(&_vehicle_land_detected);
|
||||
_vehicle_status_sub.update(&_vehicle_status);
|
||||
_vtol_vehicle_status_sub.update(&_vtol_vehicle_status);
|
||||
_vehicle_local_position_sub.update(&_vehicle_local_position);
|
||||
_position_setpoint_sub.update(&_position_setpoint);
|
||||
|
||||
if (_vehicle_attitude_sub.updated()) {
|
||||
vehicle_attitude_s vehicle_attitude;
|
||||
_vehicle_attitude_sub.update(&vehicle_attitude);
|
||||
|
||||
if (_vehicle_status.is_vtol_tailsitter && _vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING) {
|
||||
|
||||
// if the vehicle is a tailsitter we have to rotate the attitude by 90° to get to the airspeed frame
|
||||
_q_att = Quatf(vehicle_attitude.q) * Quatf(matrix::Eulerf(0.f, M_PI_2_F, 0.f));
|
||||
|
||||
} else {
|
||||
_q_att = Quatf(vehicle_attitude.q);
|
||||
}
|
||||
}
|
||||
|
||||
_vehicle_local_position_valid = (_time_now_usec - _vehicle_local_position.timestamp < 1_s)
|
||||
&& (_vehicle_local_position.timestamp > 0)
|
||||
@@ -521,11 +530,9 @@ void AirspeedModule::update_wind_estimator_sideslip()
|
||||
&& _vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING
|
||||
&& !_vehicle_land_detected.landed) {
|
||||
Vector3f vI(_vehicle_local_position.vx, _vehicle_local_position.vy, _vehicle_local_position.vz);
|
||||
Quatf q(_vehicle_attitude.q);
|
||||
|
||||
const float hor_vel_variance = _vehicle_local_position.evh * _vehicle_local_position.evh;
|
||||
|
||||
_wind_estimator_sideslip.fuse_beta(_time_now_usec, vI, hor_vel_variance, q);
|
||||
_wind_estimator_sideslip.fuse_beta(_time_now_usec, vI, hor_vel_variance, _q_att);
|
||||
}
|
||||
|
||||
_wind_estimate_sideslip.timestamp = _time_now_usec;
|
||||
|
||||
@@ -171,7 +171,7 @@ bool FailureDetector::update(const vehicle_status_s &vehicle_status, const vehic
|
||||
failure_detector_status_u status_prev = _status;
|
||||
|
||||
if (vehicle_control_mode.flag_control_attitude_enabled) {
|
||||
updateAttitudeStatus();
|
||||
updateAttitudeStatus(vehicle_status);
|
||||
|
||||
if (_param_fd_ext_ats_en.get()) {
|
||||
updateExternalAtsStatus();
|
||||
@@ -206,15 +206,31 @@ bool FailureDetector::update(const vehicle_status_s &vehicle_status, const vehic
|
||||
return _status.value != status_prev.value;
|
||||
}
|
||||
|
||||
void FailureDetector::updateAttitudeStatus()
|
||||
void FailureDetector::updateAttitudeStatus(const vehicle_status_s &vehicle_status)
|
||||
{
|
||||
vehicle_attitude_s attitude;
|
||||
|
||||
if (_vehicle_attitude_sub.update(&attitude)) {
|
||||
|
||||
const matrix::Eulerf euler(matrix::Quatf(attitude.q));
|
||||
const float roll(euler.phi());
|
||||
const float pitch(euler.theta());
|
||||
float roll(euler.phi());
|
||||
float pitch(euler.theta());
|
||||
|
||||
// special handling for tailsitter
|
||||
if (vehicle_status.is_vtol_tailsitter) {
|
||||
if (vehicle_status.in_transition_mode) {
|
||||
// disable attitude check during tailsitter transition
|
||||
roll = 0.f;
|
||||
pitch = 0.f;
|
||||
|
||||
} else if (vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING) {
|
||||
// in FW flight rotate the attitude by 90° around pitch (level FW flight = 0° pitch)
|
||||
const matrix::Eulerf euler_rotated = matrix::Eulerf(matrix::Quatf(attitude.q) * matrix::Quatf(matrix::Eulerf(0.f,
|
||||
M_PI_2_F, 0.f)));
|
||||
roll = euler_rotated.phi();
|
||||
pitch = euler_rotated.theta();
|
||||
}
|
||||
}
|
||||
|
||||
const float max_roll_deg = _param_fd_fail_r.get();
|
||||
const float max_pitch_deg = _param_fd_fail_p.get();
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
uint16_t getMotorFailures() const { return _motor_failure_esc_timed_out_mask | _motor_failure_esc_under_current_mask; }
|
||||
|
||||
private:
|
||||
void updateAttitudeStatus();
|
||||
void updateAttitudeStatus(const vehicle_status_s &vehicle_status);
|
||||
void updateExternalAtsStatus();
|
||||
void updateEscsStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status);
|
||||
void updateMotorStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status);
|
||||
|
||||
+3
-1
@@ -61,6 +61,7 @@ ActuatorEffectivenessHelicopter::ActuatorEffectivenessHelicopter(ModuleParams *p
|
||||
}
|
||||
|
||||
_param_handles.yaw_collective_pitch_scale = param_find("CA_HELI_YAW_CP_S");
|
||||
_param_handles.yaw_collective_pitch_offset = param_find("CA_HELI_YAW_CP_O");
|
||||
_param_handles.yaw_throttle_scale = param_find("CA_HELI_YAW_TH_S");
|
||||
_param_handles.yaw_ccw = param_find("CA_HELI_YAW_CCW");
|
||||
_param_handles.spoolup_time = param_find("COM_SPOOLUP_TIME");
|
||||
@@ -95,6 +96,7 @@ void ActuatorEffectivenessHelicopter::updateParams()
|
||||
}
|
||||
|
||||
param_get(_param_handles.yaw_collective_pitch_scale, &_geometry.yaw_collective_pitch_scale);
|
||||
param_get(_param_handles.yaw_collective_pitch_offset, &_geometry.yaw_collective_pitch_offset);
|
||||
param_get(_param_handles.yaw_throttle_scale, &_geometry.yaw_throttle_scale);
|
||||
param_get(_param_handles.spoolup_time, &_geometry.spoolup_time);
|
||||
int32_t yaw_ccw = 0;
|
||||
@@ -142,7 +144,7 @@ void ActuatorEffectivenessHelicopter::updateSetpoint(const matrix::Vector<float,
|
||||
actuator_sp(0) = mainMotorEnaged() ? throttle : NAN;
|
||||
|
||||
actuator_sp(1) = control_sp(ControlAxis::YAW) * _geometry.yaw_sign
|
||||
+ fabsf(collective_pitch) * _geometry.yaw_collective_pitch_scale
|
||||
+ fabsf(collective_pitch - _geometry.yaw_collective_pitch_offset) * _geometry.yaw_collective_pitch_scale
|
||||
+ throttle * _geometry.yaw_throttle_scale;
|
||||
|
||||
// Saturation check for yaw
|
||||
|
||||
+2
@@ -60,6 +60,7 @@ public:
|
||||
float throttle_curve[NUM_CURVE_POINTS];
|
||||
float pitch_curve[NUM_CURVE_POINTS];
|
||||
float yaw_collective_pitch_scale;
|
||||
float yaw_collective_pitch_offset;
|
||||
float yaw_throttle_scale;
|
||||
float yaw_sign;
|
||||
float spoolup_time;
|
||||
@@ -109,6 +110,7 @@ private:
|
||||
param_t throttle_curve[NUM_CURVE_POINTS];
|
||||
param_t pitch_curve[NUM_CURVE_POINTS];
|
||||
param_t yaw_collective_pitch_scale;
|
||||
param_t yaw_collective_pitch_offset;
|
||||
param_t yaw_throttle_scale;
|
||||
param_t yaw_ccw;
|
||||
param_t spoolup_time;
|
||||
|
||||
@@ -476,7 +476,24 @@ parameters:
|
||||
This allows to add a proportional factor of the collective pitch command to the yaw command.
|
||||
A negative value is needed when positive thrust of the tail rotor rotates the vehicle opposite to the main rotor turn direction.
|
||||
|
||||
tail_output += CA_HELI_YAW_CP_S * collective_pitch
|
||||
tail_output += CA_HELI_YAW_CP_S * abs(collective_pitch - CA_HELI_YAW_CP_O)
|
||||
type: float
|
||||
decimal: 3
|
||||
increment: 0.1
|
||||
min: -2
|
||||
max: 2
|
||||
default: 0.0
|
||||
CA_HELI_YAW_CP_O:
|
||||
description:
|
||||
short: Offset for yaw compensation based on collective pitch
|
||||
long: |
|
||||
This allows to specify which collective pitch command results in the least amount of rotor drag.
|
||||
This is used to increase the accuracy of the yaw drag torque compensation based on collective pitch
|
||||
by aligning the lowest rotor drag with zero compensation.
|
||||
For symmetric profile blades this is the command that results in exactly 0° collective blade angle.
|
||||
For lift profile blades this is typically a command resulting in slightly negative collective blade angle.
|
||||
|
||||
tail_output += CA_HELI_YAW_CP_S * abs(collective_pitch - CA_HELI_YAW_CP_O)
|
||||
type: float
|
||||
decimal: 3
|
||||
increment: 0.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2015-2020 PX4 Development Team. All rights reserved.
|
||||
# Copyright (c) 2015-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
|
||||
@@ -66,6 +66,78 @@ add_subdirectory(Utility)
|
||||
# add_custom_target(ekf2_symforce_generate DEPENDS ${EKF_GENERATED_SRC_FILES})
|
||||
# endif()
|
||||
|
||||
set(EKF_SRCS)
|
||||
list(APPEND EKF_SRCS
|
||||
EKF/baro_height_control.cpp
|
||||
EKF/bias_estimator.cpp
|
||||
EKF/control.cpp
|
||||
EKF/covariance.cpp
|
||||
EKF/ekf.cpp
|
||||
EKF/ekf_helper.cpp
|
||||
EKF/EKFGSF_yaw.cpp
|
||||
EKF/estimator_interface.cpp
|
||||
EKF/fake_height_control.cpp
|
||||
EKF/fake_pos_control.cpp
|
||||
EKF/gnss_height_control.cpp
|
||||
EKF/gps_checks.cpp
|
||||
EKF/gps_control.cpp
|
||||
EKF/gravity_fusion.cpp
|
||||
EKF/height_control.cpp
|
||||
EKF/imu_down_sampler.cpp
|
||||
EKF/mag_control.cpp
|
||||
EKF/mag_fusion.cpp
|
||||
EKF/output_predictor.cpp
|
||||
EKF/vel_pos_fusion.cpp
|
||||
EKF/zero_innovation_heading_update.cpp
|
||||
EKF/zero_velocity_update.cpp
|
||||
)
|
||||
|
||||
if(CONFIG_EKF2_AIRSPEED)
|
||||
list(APPEND EKF_SRCS EKF/airspeed_fusion.cpp)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_AUXVEL)
|
||||
list(APPEND EKF_SRCS EKF/auxvel_fusion.cpp)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_DRAG_FUSION)
|
||||
list(APPEND EKF_SRCS EKF/drag_fusion.cpp)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
list(APPEND EKF_SRCS
|
||||
EKF/ev_control.cpp
|
||||
EKF/ev_height_control.cpp
|
||||
EKF/ev_pos_control.cpp
|
||||
EKF/ev_vel_control.cpp
|
||||
EKF/ev_yaw_control.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_GNSS_YAW)
|
||||
list(APPEND EKF_SRCS EKF/gps_yaw_fusion.cpp)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
list(APPEND EKF_SRCS
|
||||
EKF/optical_flow_control.cpp
|
||||
EKF/optflow_fusion.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_RANGE_FINDER)
|
||||
list(APPEND EKF_SRCS
|
||||
EKF/range_finder_consistency_check.cpp
|
||||
EKF/range_height_control.cpp
|
||||
EKF/sensor_range_finder.cpp
|
||||
EKF/terrain_estimator.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_SIDESLIP)
|
||||
list(APPEND EKF_SRCS EKF/sideslip_fusion.cpp)
|
||||
endif()
|
||||
|
||||
px4_add_module(
|
||||
MODULE modules__ekf2
|
||||
MAIN ekf2
|
||||
@@ -81,44 +153,7 @@ px4_add_module(
|
||||
STACK_MAX
|
||||
3600
|
||||
SRCS
|
||||
EKF/airspeed_fusion.cpp
|
||||
EKF/auxvel_fusion.cpp
|
||||
EKF/baro_height_control.cpp
|
||||
EKF/bias_estimator.cpp
|
||||
EKF/control.cpp
|
||||
EKF/covariance.cpp
|
||||
EKF/drag_fusion.cpp
|
||||
EKF/ekf.cpp
|
||||
EKF/ekf_helper.cpp
|
||||
EKF/EKFGSF_yaw.cpp
|
||||
EKF/estimator_interface.cpp
|
||||
EKF/ev_control.cpp
|
||||
EKF/ev_height_control.cpp
|
||||
EKF/ev_pos_control.cpp
|
||||
EKF/ev_vel_control.cpp
|
||||
EKF/ev_yaw_control.cpp
|
||||
EKF/fake_height_control.cpp
|
||||
EKF/fake_pos_control.cpp
|
||||
EKF/gnss_height_control.cpp
|
||||
EKF/gps_checks.cpp
|
||||
EKF/gps_control.cpp
|
||||
EKF/gps_yaw_fusion.cpp
|
||||
EKF/gravity_fusion.cpp
|
||||
EKF/height_control.cpp
|
||||
EKF/imu_down_sampler.cpp
|
||||
EKF/mag_control.cpp
|
||||
EKF/mag_fusion.cpp
|
||||
EKF/optical_flow_control.cpp
|
||||
EKF/optflow_fusion.cpp
|
||||
EKF/output_predictor.cpp
|
||||
EKF/range_finder_consistency_check.cpp
|
||||
EKF/range_height_control.cpp
|
||||
EKF/sensor_range_finder.cpp
|
||||
EKF/sideslip_fusion.cpp
|
||||
EKF/terrain_estimator.cpp
|
||||
EKF/vel_pos_fusion.cpp
|
||||
EKF/zero_innovation_heading_update.cpp
|
||||
EKF/zero_velocity_update.cpp
|
||||
${EKF_SRCS}
|
||||
|
||||
EKF2.cpp
|
||||
EKF2.hpp
|
||||
|
||||
@@ -31,47 +31,82 @@
|
||||
#
|
||||
############################################################################
|
||||
|
||||
add_library(ecl_EKF
|
||||
airspeed_fusion.cpp
|
||||
auxvel_fusion.cpp
|
||||
set(EKF_SRCS)
|
||||
list(APPEND EKF_SRCS
|
||||
baro_height_control.cpp
|
||||
bias_estimator.cpp
|
||||
control.cpp
|
||||
covariance.cpp
|
||||
drag_fusion.cpp
|
||||
ekf.cpp
|
||||
ekf_helper.cpp
|
||||
EKFGSF_yaw.cpp
|
||||
estimator_interface.cpp
|
||||
ev_control.cpp
|
||||
ev_height_control.cpp
|
||||
ev_pos_control.cpp
|
||||
ev_vel_control.cpp
|
||||
ev_yaw_control.cpp
|
||||
fake_height_control.cpp
|
||||
fake_pos_control.cpp
|
||||
gnss_height_control.cpp
|
||||
gps_checks.cpp
|
||||
gps_control.cpp
|
||||
gps_yaw_fusion.cpp
|
||||
gravity_fusion.cpp
|
||||
height_control.cpp
|
||||
imu_down_sampler.cpp
|
||||
mag_control.cpp
|
||||
mag_fusion.cpp
|
||||
optical_flow_control.cpp
|
||||
optflow_fusion.cpp
|
||||
output_predictor.cpp
|
||||
range_finder_consistency_check.cpp
|
||||
range_height_control.cpp
|
||||
sensor_range_finder.cpp
|
||||
sideslip_fusion.cpp
|
||||
terrain_estimator.cpp
|
||||
vel_pos_fusion.cpp
|
||||
zero_innovation_heading_update.cpp
|
||||
zero_velocity_update.cpp
|
||||
)
|
||||
|
||||
if(CONFIG_EKF2_AIRSPEED)
|
||||
list(APPEND EKF_SRCS airspeed_fusion.cpp)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_AUXVEL)
|
||||
list(APPEND EKF_SRCS auxvel_fusion.cpp)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_DRAG_FUSION)
|
||||
list(APPEND EKF_SRCS drag_fusion.cpp)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
list(APPEND EKF_SRCS
|
||||
ev_control.cpp
|
||||
ev_height_control.cpp
|
||||
ev_pos_control.cpp
|
||||
ev_vel_control.cpp
|
||||
ev_yaw_control.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_GNSS_YAW)
|
||||
list(APPEND EKF_SRCS gps_yaw_fusion.cpp)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
list(APPEND EKF_SRCS
|
||||
optical_flow_control.cpp
|
||||
optflow_fusion.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_RANGE_FINDER)
|
||||
list(APPEND EKF_SRCS
|
||||
range_finder_consistency_check.cpp
|
||||
range_height_control.cpp
|
||||
sensor_range_finder.cpp
|
||||
terrain_estimator.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EKF2_SIDESLIP)
|
||||
list(APPEND EKF_SRCS sideslip_fusion.cpp)
|
||||
endif()
|
||||
|
||||
add_library(ecl_EKF
|
||||
${EKF_SRCS}
|
||||
)
|
||||
|
||||
add_dependencies(ecl_EKF prebuild_targets)
|
||||
target_link_libraries(ecl_EKF PRIVATE geo world_magnetic_model)
|
||||
target_compile_options(ecl_EKF PRIVATE -fno-associative-math)
|
||||
|
||||
@@ -222,21 +222,6 @@ void Ekf::stopAirspeedFusion()
|
||||
}
|
||||
}
|
||||
|
||||
float Ekf::getTrueAirspeed() const
|
||||
{
|
||||
return (_state.vel - Vector3f(_state.wind_vel(0), _state.wind_vel(1), 0.f)).norm();
|
||||
}
|
||||
|
||||
void Ekf::resetWind()
|
||||
{
|
||||
if (_control_status.flags.fuse_aspd && isRecent(_airspeed_sample_delayed.time_us, 1e6)) {
|
||||
resetWindUsingAirspeed(_airspeed_sample_delayed);
|
||||
|
||||
} else {
|
||||
resetWindToZero();
|
||||
}
|
||||
}
|
||||
|
||||
void Ekf::resetWindUsingAirspeed(const airspeedSample &airspeed_sample)
|
||||
{
|
||||
const float euler_yaw = getEulerYaw(_R_to_earth);
|
||||
@@ -282,14 +267,3 @@ void Ekf::resetWindCovarianceUsingAirspeed(const airspeedSample &airspeed_sample
|
||||
P(22, 22) += P(4, 4);
|
||||
P(23, 23) += P(5, 5);
|
||||
}
|
||||
|
||||
void Ekf::resetWindToZero()
|
||||
{
|
||||
ECL_INFO("reset wind to zero");
|
||||
|
||||
// If we don't have an airspeed measurement, then assume the wind is zero
|
||||
_state.wind_vel.setZero();
|
||||
|
||||
// start with a small initial uncertainty to improve the initial estimate
|
||||
P.uncorrelateCovarianceSetVariance<2>(22, _params.initial_wind_uncertainty);
|
||||
}
|
||||
|
||||
@@ -108,10 +108,12 @@ enum MagFuseType : uint8_t {
|
||||
NONE = 5 ///< Do not use magnetometer under any circumstance. Other sources of yaw may be used if selected via the EKF2_AID_MASK parameter.
|
||||
};
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
enum TerrainFusionMask : uint8_t {
|
||||
TerrainFuseRangeFinder = (1 << 0),
|
||||
TerrainFuseOpticalFlow = (1 << 1)
|
||||
};
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
enum HeightSensor : uint8_t {
|
||||
BARO = 0,
|
||||
@@ -238,6 +240,7 @@ struct flowSample {
|
||||
uint8_t quality{}; ///< quality indicator between 0 and 255
|
||||
};
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
struct extVisionSample {
|
||||
uint64_t time_us{}; ///< timestamp of the measurement (uSec)
|
||||
Vector3f pos{}; ///< XYZ position in external vision's local reference frame (m) - Z must be aligned with down axis
|
||||
@@ -251,17 +254,22 @@ struct extVisionSample {
|
||||
uint8_t reset_counter{};
|
||||
int8_t quality{}; ///< quality indicator between 0 and 100
|
||||
};
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
struct dragSample {
|
||||
uint64_t time_us{}; ///< timestamp of the measurement (uSec)
|
||||
Vector2f accelXY{}; ///< measured specific force along the X and Y body axes (m/sec**2)
|
||||
};
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
struct auxVelSample {
|
||||
uint64_t time_us{}; ///< timestamp of the measurement (uSec)
|
||||
Vector2f vel{}; ///< measured NE velocity relative to the local origin (m/sec)
|
||||
Vector2f velVar{}; ///< estimated error variance of the NE velocity (m/sec)**2
|
||||
};
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
struct systemFlagUpdate {
|
||||
uint64_t time_us{};
|
||||
@@ -294,10 +302,6 @@ struct parameters {
|
||||
int32_t position_sensor_ref{static_cast<int32_t>(PositionSensor::GNSS)};
|
||||
int32_t baro_ctrl{1};
|
||||
int32_t gnss_ctrl{GnssCtrl::HPOS | GnssCtrl::VEL};
|
||||
int32_t rng_ctrl{RngCtrl::CONDITIONAL};
|
||||
int32_t ev_ctrl{0};
|
||||
int32_t terrain_fusion_mode{TerrainFusionMask::TerrainFuseRangeFinder |
|
||||
TerrainFusionMask::TerrainFuseOpticalFlow}; ///< aiding source(s) selection bitmask for the terrain estimator
|
||||
|
||||
int32_t sensor_interval_max_ms{10}; ///< maximum time of arrival difference between non IMU sensor updates. Sets the size of the observation buffers. (mSec)
|
||||
|
||||
@@ -305,11 +309,6 @@ struct parameters {
|
||||
float mag_delay_ms{0.0f}; ///< magnetometer measurement delay relative to the IMU (mSec)
|
||||
float baro_delay_ms{0.0f}; ///< barometer height measurement delay relative to the IMU (mSec)
|
||||
float gps_delay_ms{110.0f}; ///< GPS measurement delay relative to the IMU (mSec)
|
||||
float airspeed_delay_ms{100.0f}; ///< airspeed measurement delay relative to the IMU (mSec)
|
||||
float flow_delay_ms{5.0f}; ///< optical flow measurement delay relative to the IMU (mSec) - this is to the middle of the optical flow integration interval
|
||||
float range_delay_ms{5.0f}; ///< range finder measurement delay relative to the IMU (mSec)
|
||||
float ev_delay_ms{175.0f}; ///< off-board vision measurement delay relative to the IMU (mSec)
|
||||
float auxvel_delay_ms{5.0f}; ///< auxiliary velocity measurement delay relative to the IMU (mSec)
|
||||
|
||||
// input noise
|
||||
float gyro_noise{1.5e-2f}; ///< IMU angular rate noise used for covariance prediction (rad/sec)
|
||||
@@ -323,10 +322,6 @@ struct parameters {
|
||||
float wind_vel_nsd{1.0e-2f}; ///< process noise spectral density for wind velocity prediction (m/sec**2/sqrt(Hz))
|
||||
const float wind_vel_nsd_scaler{0.5f}; ///< scaling of wind process noise with vertical velocity
|
||||
|
||||
float terrain_p_noise{5.0f}; ///< process noise for terrain offset (m/sec)
|
||||
float terrain_gradient{0.5f}; ///< gradient of terrain used to estimate process noise due to changing position (m/m)
|
||||
const float terrain_timeout{10.f}; ///< maximum time for invalid bottom distance measurements before resetting terrain estimate (s)
|
||||
|
||||
// initialization errors
|
||||
float switch_on_gyro_bias{0.1f}; ///< 1-sigma gyro bias uncertainty at switch on (rad/sec)
|
||||
float switch_on_accel_bias{0.2f}; ///< 1-sigma accelerometer bias uncertainty at switch on (m/sec**2)
|
||||
@@ -357,21 +352,35 @@ struct parameters {
|
||||
float mag_acc_gate{0.5f}; ///< when in auto select mode, heading fusion will be used when manoeuvre accel is lower than this (m/sec**2)
|
||||
float mag_yaw_rate_gate{0.20f}; ///< yaw rate threshold used by mode select logic (rad/sec)
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
// GNSS heading fusion
|
||||
float gps_heading_noise{0.1f}; ///< measurement noise standard deviation used for GNSS heading fusion (rad)
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
// airspeed fusion
|
||||
float airspeed_delay_ms{100.0f}; ///< airspeed measurement delay relative to the IMU (mSec)
|
||||
float tas_innov_gate{5.0f}; ///< True Airspeed innovation consistency gate size (STD)
|
||||
float eas_noise{1.4f}; ///< EAS measurement noise standard deviation used for airspeed fusion (m/s)
|
||||
float arsp_thr{2.0f}; ///< Airspeed fusion threshold. A value of zero will deactivate airspeed fusion
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_SIDESLIP)
|
||||
// synthetic sideslip fusion
|
||||
int32_t beta_fusion_enabled{0};
|
||||
float beta_innov_gate{5.0f}; ///< synthetic sideslip innovation consistency gate size in standard deviation (STD)
|
||||
float beta_noise{0.3f}; ///< synthetic sideslip noise (rad)
|
||||
const float beta_avg_ft_us{150000.0f}; ///< The average time between synthetic sideslip measurements (uSec)
|
||||
#endif // CONFIG_EKF2_SIDESLIP
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
// range finder fusion
|
||||
int32_t rng_ctrl{RngCtrl::CONDITIONAL};
|
||||
|
||||
int32_t terrain_fusion_mode{TerrainFusionMask::TerrainFuseRangeFinder |
|
||||
TerrainFusionMask::TerrainFuseOpticalFlow}; ///< aiding source(s) selection bitmask for the terrain estimator
|
||||
|
||||
float range_delay_ms{5.0f}; ///< range finder measurement delay relative to the IMU (mSec)
|
||||
float range_noise{0.1f}; ///< observation noise for range finder measurements (m)
|
||||
float range_innov_gate{5.0f}; ///< range finder fusion innovation consistency gate size (STD)
|
||||
float rng_hgt_bias_nsd{0.13f}; ///< process noise for range height bias estimation (m/s/sqrt(Hz))
|
||||
@@ -386,7 +395,19 @@ struct parameters {
|
||||
float range_cos_max_tilt{0.7071f}; ///< cosine of the maximum tilt angle from the vertical that permits use of range finder and flow data
|
||||
float range_kin_consistency_gate{1.0f}; ///< gate size used by the range finder kinematic consistency check
|
||||
|
||||
Vector3f rng_pos_body{}; ///< xyz position of range sensor in body frame (m)
|
||||
|
||||
float terrain_p_noise{5.0f}; ///< process noise for terrain offset (m/sec)
|
||||
float terrain_gradient{0.5f}; ///< gradient of terrain used to estimate process noise due to changing position (m/m)
|
||||
const float terrain_timeout{10.f}; ///< maximum time for invalid bottom distance measurements before resetting terrain estimate (s)
|
||||
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
// vision position fusion
|
||||
int32_t ev_ctrl{0};
|
||||
float ev_delay_ms{175.0f}; ///< off-board vision measurement delay relative to the IMU (mSec)
|
||||
|
||||
float ev_vel_noise{0.1f}; ///< minimum allowed observation noise for EV velocity fusion (m/sec)
|
||||
float ev_pos_noise{0.1f}; ///< minimum allowed observation noise for EV position fusion (m)
|
||||
float ev_att_noise{0.1f}; ///< minimum allowed observation noise for EV attitude fusion (rad/sec)
|
||||
@@ -395,15 +416,24 @@ struct parameters {
|
||||
float ev_pos_innov_gate{5.0f}; ///< vision position fusion innovation consistency gate size (STD)
|
||||
float ev_hgt_bias_nsd{0.13f}; ///< process noise for vision height bias estimation (m/s/sqrt(Hz))
|
||||
|
||||
Vector3f ev_pos_body{}; ///< xyz position of VI-sensor focal point in body frame (m)
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
// gravity fusion
|
||||
float gravity_noise{1.0f}; ///< accelerometer measurement gaussian noise (m/s**2)
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
float flow_delay_ms{5.0f}; ///< optical flow measurement delay relative to the IMU (mSec) - this is to the middle of the optical flow integration interval
|
||||
|
||||
// optical flow fusion
|
||||
float flow_noise{0.15f}; ///< observation noise for optical flow LOS rate measurements (rad/sec)
|
||||
float flow_noise_qual_min{0.5f}; ///< observation noise for optical flow LOS rate measurements when flow sensor quality is at the minimum useable (rad/sec)
|
||||
int32_t flow_qual_min{1}; ///< minimum acceptable quality integer from the flow sensor
|
||||
float flow_innov_gate{3.0f}; ///< optical flow fusion innovation consistency gate size (STD)
|
||||
|
||||
Vector3f flow_pos_body{}; ///< xyz position of range sensor focal point in body frame (m)
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
// these parameters control the strictness of GPS quality checks used to determine if the GPS is
|
||||
// good enough to set a local origin and commence aiding
|
||||
int32_t gps_check_mask{21}; ///< bitmask used to control which GPS quality checks are used
|
||||
@@ -418,9 +448,6 @@ struct parameters {
|
||||
// XYZ offset of sensors in body axes (m)
|
||||
Vector3f imu_pos_body{}; ///< xyz position of IMU in body frame (m)
|
||||
Vector3f gps_pos_body{}; ///< xyz position of the GPS antenna in body frame (m)
|
||||
Vector3f rng_pos_body{}; ///< xyz position of range sensor in body frame (m)
|
||||
Vector3f flow_pos_body{}; ///< xyz position of range sensor focal point in body frame (m)
|
||||
Vector3f ev_pos_body{}; ///< xyz position of VI-sensor focal point in body frame (m)
|
||||
|
||||
// accel bias learning control
|
||||
float acc_bias_lim{0.4f}; ///< maximum accel bias magnitude (m/sec**2)
|
||||
@@ -436,6 +463,7 @@ struct parameters {
|
||||
|
||||
int32_t valid_timeout_max{5'000'000}; ///< amount of time spent inertial dead reckoning before the estimator reports the state estimates as invalid (uSec)
|
||||
|
||||
#if defined(CONFIG_EKF2_BARO_COMPENSATION)
|
||||
// static barometer pressure position error coefficient along body axes
|
||||
float static_pressure_coef_xp{0.0f}; // (-)
|
||||
float static_pressure_coef_xn{0.0f}; // (-)
|
||||
@@ -445,21 +473,27 @@ struct parameters {
|
||||
|
||||
// upper limit on airspeed used for correction (m/s**2)
|
||||
float max_correction_airspeed {20.0f};
|
||||
#endif // CONFIG_EKF2_BARO_COMPENSATION
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
// multi-rotor drag specific force fusion
|
||||
float drag_noise{2.5f}; ///< observation noise variance for drag specific force measurements (m/sec**2)**2
|
||||
float bcoef_x{100.0f}; ///< bluff body drag ballistic coefficient for the X-axis (kg/m**2)
|
||||
float bcoef_y{100.0f}; ///< bluff body drag ballistic coefficient for the Y-axis (kg/m**2)
|
||||
float mcoef{0.1f}; ///< rotor momentum drag coefficient for the X and Y axes (1/s)
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
// control of accel error detection and mitigation (IMU clipping)
|
||||
const float vert_innov_test_lim{3.0f}; ///< Number of standard deviations of vertical vel/pos innovations allowed before triggering a vertical acceleration failure
|
||||
const float vert_innov_test_min{1.0f}; ///< Minimum number of standard deviations of vertical vel/pos innovations required to trigger a vertical acceleration failure
|
||||
const int bad_acc_reset_delay_us{500000}; ///< Continuous time that the vertical position and velocity innovation test must fail before the states are reset (uSec)
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
// auxiliary velocity fusion
|
||||
float auxvel_delay_ms{5.0f}; ///< auxiliary velocity measurement delay relative to the IMU (mSec)
|
||||
const float auxvel_noise{0.5f}; ///< minimum observation noise, uses reported noise if greater (m/s)
|
||||
const float auxvel_gate{5.0f}; ///< velocity fusion innovation consistency gate size (STD)
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
// compute synthetic magnetomter Z value if possible
|
||||
int32_t synthesize_mag_z{0};
|
||||
@@ -593,6 +627,7 @@ union ekf_solution_status_u {
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
union terrain_fusion_status_u {
|
||||
struct {
|
||||
bool range_finder : 1; ///< 0 - true if we are fusing range finder data
|
||||
@@ -600,6 +635,7 @@ union terrain_fusion_status_u {
|
||||
} flags;
|
||||
uint8_t value;
|
||||
};
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
// define structure used to communicate information events
|
||||
union information_event_status_u {
|
||||
|
||||
@@ -104,19 +104,37 @@ void Ekf::controlFusionModes(const imuSample &imu_delayed)
|
||||
|
||||
// control use of observations for aiding
|
||||
controlMagFusion();
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
controlOpticalFlowFusion(imu_delayed);
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
controlGpsFusion(imu_delayed);
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
controlAirDataFusion(imu_delayed);
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_SIDESLIP)
|
||||
controlBetaFusion(imu_delayed);
|
||||
#endif // CONFIG_EKF2_SIDESLIP
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
controlDragFusion();
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
controlHeightFusion(imu_delayed);
|
||||
controlGravityFusion(imu_delayed);
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
// Additional data odometry data from an external estimator can be fused.
|
||||
controlExternalVisionFusion();
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
// Additional horizontal velocity data from an auxiliary sensor can be fused
|
||||
controlAuxVelFusion();
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
controlZeroInnovationHeadingUpdate();
|
||||
|
||||
|
||||
@@ -69,16 +69,17 @@ void Ekf::initialiseCovariance()
|
||||
// position
|
||||
P(7,7) = sq(fmaxf(_params.gps_pos_noise, 0.01f));
|
||||
P(8,8) = P(7,7);
|
||||
P(9,9) = sq(fmaxf(_params.baro_noise, 0.01f));
|
||||
|
||||
if (_control_status.flags.gps_hgt) {
|
||||
P(9,9) = sq(fmaxf(1.5f * _params.gps_pos_noise, 0.01f));
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
if (_control_status.flags.rng_hgt) {
|
||||
P(9,9) = sq(fmaxf(_params.range_noise, 0.01f));
|
||||
|
||||
} else if (_control_status.flags.gps_hgt) {
|
||||
P(9,9) = sq(fmaxf(1.5f * _params.gps_pos_noise, 0.01f));
|
||||
|
||||
} else {
|
||||
P(9,9) = sq(fmaxf(_params.baro_noise, 0.01f));
|
||||
}
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
// gyro bias
|
||||
_prev_delta_ang_bias_var(0) = P(10,10) = sq(_params.switch_on_gyro_bias * dt);
|
||||
@@ -444,14 +445,27 @@ void Ekf::fixCovarianceErrors(bool force_symmetry)
|
||||
if (fabsf(down_dvel_bias) > dVel_bias_lim) {
|
||||
|
||||
bool bad_vz_gps = _control_status.flags.gps && (down_dvel_bias * _aid_src_gnss_vel.innovation[2] < 0.0f);
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
bool bad_vz_ev = _control_status.flags.ev_vel && (down_dvel_bias * _aid_src_ev_vel.innovation[2] < 0.0f);
|
||||
#else
|
||||
bool bad_vz_ev = false;
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
if (bad_vz_gps || bad_vz_ev) {
|
||||
bool bad_z_baro = _control_status.flags.baro_hgt && (down_dvel_bias * _aid_src_baro_hgt.innovation < 0.0f);
|
||||
bool bad_z_gps = _control_status.flags.gps_hgt && (down_dvel_bias * _aid_src_gnss_hgt.innovation < 0.0f);
|
||||
bool bad_z_rng = _control_status.flags.rng_hgt && (down_dvel_bias * _aid_src_rng_hgt.innovation < 0.0f);
|
||||
bool bad_z_ev = _control_status.flags.ev_hgt && (down_dvel_bias * _aid_src_ev_hgt.innovation < 0.0f);
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
bool bad_z_rng = _control_status.flags.rng_hgt && (down_dvel_bias * _aid_src_rng_hgt.innovation < 0.0f);
|
||||
#else
|
||||
bool bad_z_rng = false;
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
bool bad_z_ev = _control_status.flags.ev_hgt && (down_dvel_bias * _aid_src_ev_hgt.innovation < 0.0f);
|
||||
#else
|
||||
bool bad_z_ev = false;
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
if (bad_z_baro || bad_z_gps || bad_z_rng || bad_z_ev) {
|
||||
bad_acc_bias = true;
|
||||
|
||||
@@ -63,9 +63,11 @@ void Ekf::reset()
|
||||
_state.wind_vel.setZero();
|
||||
_state.quat_nominal.setIdentity();
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
_range_sensor.setPitchOffset(_params.rng_sens_pitch);
|
||||
_range_sensor.setCosMaxTilt(_params.range_cos_max_tilt);
|
||||
_range_sensor.setQualityHysteresis(_params.range_valid_quality_s);
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
_control_status.value = 0;
|
||||
_control_status_prev.value = 0;
|
||||
@@ -94,17 +96,13 @@ void Ekf::reset()
|
||||
_time_last_hor_vel_fuse = 0;
|
||||
_time_last_ver_vel_fuse = 0;
|
||||
_time_last_heading_fuse = 0;
|
||||
|
||||
_time_last_flow_terrain_fuse = 0;
|
||||
_time_last_zero_velocity_fuse = 0;
|
||||
_time_last_healthy_rng_data = 0;
|
||||
|
||||
_last_known_pos.setZero();
|
||||
|
||||
_time_acc_bias_check = 0;
|
||||
|
||||
_gps_checks_passed = false;
|
||||
|
||||
_gps_alt_ref = NAN;
|
||||
|
||||
_baro_counter = 0;
|
||||
@@ -115,30 +113,46 @@ void Ekf::reset()
|
||||
_clip_counter = 0;
|
||||
|
||||
resetEstimatorAidStatus(_aid_src_baro_hgt);
|
||||
resetEstimatorAidStatus(_aid_src_rng_hgt);
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
resetEstimatorAidStatus(_aid_src_airspeed);
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
#if defined(CONFIG_EKF2_SIDESLIP)
|
||||
resetEstimatorAidStatus(_aid_src_sideslip);
|
||||
#endif // CONFIG_EKF2_SIDESLIP
|
||||
|
||||
resetEstimatorAidStatus(_aid_src_fake_pos);
|
||||
resetEstimatorAidStatus(_aid_src_fake_hgt);
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
resetEstimatorAidStatus(_aid_src_ev_hgt);
|
||||
resetEstimatorAidStatus(_aid_src_ev_pos);
|
||||
resetEstimatorAidStatus(_aid_src_ev_vel);
|
||||
resetEstimatorAidStatus(_aid_src_ev_yaw);
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
resetEstimatorAidStatus(_aid_src_gnss_hgt);
|
||||
resetEstimatorAidStatus(_aid_src_gnss_pos);
|
||||
resetEstimatorAidStatus(_aid_src_gnss_vel);
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
resetEstimatorAidStatus(_aid_src_gnss_yaw);
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
resetEstimatorAidStatus(_aid_src_mag_heading);
|
||||
resetEstimatorAidStatus(_aid_src_mag);
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
resetEstimatorAidStatus(_aid_src_aux_vel);
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
resetEstimatorAidStatus(_aid_src_optical_flow);
|
||||
resetEstimatorAidStatus(_aid_src_terrain_optical_flow);
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
resetEstimatorAidStatus(_aid_src_rng_hgt);
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
}
|
||||
|
||||
bool Ekf::update()
|
||||
@@ -166,8 +180,10 @@ bool Ekf::update()
|
||||
// control fusion of observation data
|
||||
controlFusionModes(imu_sample_delayed);
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
// run a separate filter for terrain estimation
|
||||
runTerrainEstimator(imu_sample_delayed);
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
_output_predictor.correctOutputStates(imu_sample_delayed.time_us, getGyroBias(), getAccelBias(),
|
||||
_state.quat_nominal, _state.vel, _state.pos);
|
||||
@@ -205,8 +221,10 @@ bool Ekf::initialiseFilter()
|
||||
// initialise the state covariance matrix now we have starting values for all the states
|
||||
initialiseCovariance();
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
// Initialise the terrain estimator
|
||||
initHagl();
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
// reset the output predictor state history to match the EKF initial values
|
||||
_output_predictor.alignOutputFilter(_state.quat_nominal, _state.vel, _state.pos);
|
||||
|
||||
+249
-154
@@ -64,7 +64,6 @@ public:
|
||||
typedef matrix::Vector<float, _k_num_states> Vector24f;
|
||||
typedef matrix::SquareMatrix<float, _k_num_states> SquareMatrix24f;
|
||||
typedef matrix::SquareMatrix<float, 2> Matrix2f;
|
||||
typedef matrix::Vector<float, 4> Vector4f;
|
||||
template<int ... Idxs>
|
||||
|
||||
using SparseVector24f = matrix::SparseVectorf<24, Idxs...>;
|
||||
@@ -86,21 +85,50 @@ public:
|
||||
void getGpsVelPosInnovVar(float hvel[2], float &vvel, float hpos[2], float &vpos) const;
|
||||
void getGpsVelPosInnovRatio(float &hvel, float &vvel, float &hpos, float &vpos) const;
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
void getEvVelPosInnov(float hvel[2], float &vvel, float hpos[2], float &vpos) const;
|
||||
void getEvVelPosInnovVar(float hvel[2], float &vvel, float hpos[2], float &vpos) const;
|
||||
void getEvVelPosInnovRatio(float &hvel, float &vvel, float &hpos, float &vpos) const;
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
void getBaroHgtInnov(float &baro_hgt_innov) const { baro_hgt_innov = _aid_src_baro_hgt.innovation; }
|
||||
void getBaroHgtInnovVar(float &baro_hgt_innov_var) const { baro_hgt_innov_var = _aid_src_baro_hgt.innovation_variance; }
|
||||
void getBaroHgtInnovRatio(float &baro_hgt_innov_ratio) const { baro_hgt_innov_ratio = _aid_src_baro_hgt.test_ratio; }
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
// range height
|
||||
const BiasEstimator::status &getRngHgtBiasEstimatorStatus() const { return _rng_hgt_b_est.getStatus(); }
|
||||
const auto &aid_src_rng_hgt() const { return _aid_src_rng_hgt; }
|
||||
|
||||
void getRngHgtInnov(float &rng_hgt_innov) const { rng_hgt_innov = _aid_src_rng_hgt.innovation; }
|
||||
void getRngHgtInnovVar(float &rng_hgt_innov_var) const { rng_hgt_innov_var = _aid_src_rng_hgt.innovation_variance; }
|
||||
void getRngHgtInnovRatio(float &rng_hgt_innov_ratio) const { rng_hgt_innov_ratio = _aid_src_rng_hgt.test_ratio; }
|
||||
|
||||
void getAuxVelInnov(float aux_vel_innov[2]) const;
|
||||
void getAuxVelInnovVar(float aux_vel_innov[2]) const;
|
||||
void getAuxVelInnovRatio(float &aux_vel_innov_ratio) const { aux_vel_innov_ratio = math::max(_aid_src_aux_vel.test_ratio[0], _aid_src_aux_vel.test_ratio[1]); }
|
||||
void getHaglInnov(float &hagl_innov) const { hagl_innov = _hagl_innov; }
|
||||
void getHaglInnovVar(float &hagl_innov_var) const { hagl_innov_var = _hagl_innov_var; }
|
||||
void getHaglInnovRatio(float &hagl_innov_ratio) const { hagl_innov_ratio = _hagl_test_ratio; }
|
||||
|
||||
void getHaglRateInnov(float &hagl_rate_innov) const { hagl_rate_innov = _rng_consistency_check.getInnov(); }
|
||||
void getHaglRateInnovVar(float &hagl_rate_innov_var) const { hagl_rate_innov_var = _rng_consistency_check.getInnovVar(); }
|
||||
void getHaglRateInnovRatio(float &hagl_rate_innov_ratio) const { hagl_rate_innov_ratio = _rng_consistency_check.getSignedTestRatioLpf(); }
|
||||
|
||||
// terrain estimate
|
||||
bool isTerrainEstimateValid() const;
|
||||
|
||||
uint8_t getTerrainEstimateSensorBitfield() const { return _hagl_sensor_status.value; }
|
||||
|
||||
// get the estimated terrain vertical position relative to the NED origin
|
||||
float getTerrainVertPos() const { return _terrain_vpos; };
|
||||
|
||||
// get the number of times the vertical terrain position has been reset
|
||||
uint8_t getTerrainVertPosResetCounter() const { return _terrain_vpos_reset_counter; };
|
||||
|
||||
// get the terrain variance
|
||||
float get_terrain_var() const { return _terrain_var; }
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
const auto &aid_src_optical_flow() const { return _aid_src_optical_flow; }
|
||||
|
||||
void getFlowInnov(float flow_innov[2]) const;
|
||||
void getFlowInnovVar(float flow_innov_var[2]) const;
|
||||
@@ -119,77 +147,117 @@ public:
|
||||
void getTerrainFlowInnovVar(float flow_innov_var[2]) const;
|
||||
void getTerrainFlowInnovRatio(float &flow_innov_ratio) const { flow_innov_ratio = math::max(_aid_src_terrain_optical_flow.test_ratio[0], _aid_src_terrain_optical_flow.test_ratio[1]); }
|
||||
|
||||
const auto &aid_src_terrain_optical_flow() const { return _aid_src_terrain_optical_flow; }
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
void getAuxVelInnov(float aux_vel_innov[2]) const;
|
||||
void getAuxVelInnovVar(float aux_vel_innov[2]) const;
|
||||
void getAuxVelInnovRatio(float &aux_vel_innov_ratio) const { aux_vel_innov_ratio = math::max(_aid_src_aux_vel.test_ratio[0], _aid_src_aux_vel.test_ratio[1]); }
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
void getHeadingInnov(float &heading_innov) const
|
||||
{
|
||||
if (_control_status.flags.mag_hdg) {
|
||||
heading_innov = _aid_src_mag_heading.innovation;
|
||||
|
||||
} else if (_control_status.flags.mag_3D) {
|
||||
heading_innov = Vector3f(_aid_src_mag.innovation).max();
|
||||
|
||||
} else if (_control_status.flags.gps_yaw) {
|
||||
heading_innov = _aid_src_gnss_yaw.innovation;
|
||||
|
||||
} else if (_control_status.flags.ev_yaw) {
|
||||
heading_innov = _aid_src_ev_yaw.innovation;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_control_status.flags.mag_3D) {
|
||||
heading_innov = Vector3f(_aid_src_mag.innovation).max();
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
if (_control_status.flags.gps_yaw) {
|
||||
heading_innov = _aid_src_gnss_yaw.innovation;
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_yaw) {
|
||||
heading_innov = _aid_src_ev_yaw.innovation;
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
}
|
||||
|
||||
void getHeadingInnovVar(float &heading_innov_var) const
|
||||
{
|
||||
if (_control_status.flags.mag_hdg) {
|
||||
heading_innov_var = _aid_src_mag_heading.innovation_variance;
|
||||
|
||||
} else if (_control_status.flags.mag_3D) {
|
||||
heading_innov_var = Vector3f(_aid_src_mag.innovation_variance).max();
|
||||
|
||||
} else if (_control_status.flags.gps_yaw) {
|
||||
heading_innov_var = _aid_src_gnss_yaw.innovation_variance;
|
||||
|
||||
} else if (_control_status.flags.ev_yaw) {
|
||||
heading_innov_var = _aid_src_ev_yaw.innovation_variance;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_control_status.flags.mag_3D) {
|
||||
heading_innov_var = Vector3f(_aid_src_mag.innovation_variance).max();
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
if (_control_status.flags.gps_yaw) {
|
||||
heading_innov_var = _aid_src_gnss_yaw.innovation_variance;
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_yaw) {
|
||||
heading_innov_var = _aid_src_ev_yaw.innovation_variance;
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
}
|
||||
|
||||
void getHeadingInnovRatio(float &heading_innov_ratio) const
|
||||
{
|
||||
if (_control_status.flags.mag_hdg) {
|
||||
heading_innov_ratio = _aid_src_mag_heading.test_ratio;
|
||||
|
||||
} else if (_control_status.flags.mag_3D) {
|
||||
heading_innov_ratio = Vector3f(_aid_src_mag.test_ratio).max();
|
||||
|
||||
} else if (_control_status.flags.gps_yaw) {
|
||||
heading_innov_ratio = _aid_src_gnss_yaw.test_ratio;
|
||||
|
||||
} else if (_control_status.flags.ev_yaw) {
|
||||
heading_innov_ratio = _aid_src_ev_yaw.test_ratio;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_control_status.flags.mag_3D) {
|
||||
heading_innov_ratio = Vector3f(_aid_src_mag.test_ratio).max();
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
if (_control_status.flags.gps_yaw) {
|
||||
heading_innov_ratio = _aid_src_gnss_yaw.test_ratio;
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_yaw) {
|
||||
heading_innov_ratio = _aid_src_ev_yaw.test_ratio;
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
}
|
||||
|
||||
void getMagInnov(float mag_innov[3]) const { memcpy(mag_innov, _aid_src_mag.innovation, sizeof(_aid_src_mag.innovation)); }
|
||||
void getMagInnovVar(float mag_innov_var[3]) const { memcpy(mag_innov_var, _aid_src_mag.innovation_variance, sizeof(_aid_src_mag.innovation_variance)); }
|
||||
void getMagInnovRatio(float &mag_innov_ratio) const { mag_innov_ratio = Vector3f(_aid_src_mag.test_ratio).max(); }
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
void getDragInnov(float drag_innov[2]) const { _drag_innov.copyTo(drag_innov); }
|
||||
void getDragInnovVar(float drag_innov_var[2]) const { _drag_innov_var.copyTo(drag_innov_var); }
|
||||
void getDragInnovRatio(float drag_innov_ratio[2]) const { _drag_test_ratio.copyTo(drag_innov_ratio); }
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
void getAirspeedInnov(float &airspeed_innov) const { airspeed_innov = _aid_src_airspeed.innovation; }
|
||||
void getAirspeedInnovVar(float &airspeed_innov_var) const { airspeed_innov_var = _aid_src_airspeed.innovation_variance; }
|
||||
void getAirspeedInnovRatio(float &airspeed_innov_ratio) const { airspeed_innov_ratio = _aid_src_airspeed.test_ratio; }
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_SIDESLIP)
|
||||
void getBetaInnov(float &beta_innov) const { beta_innov = _aid_src_sideslip.innovation; }
|
||||
void getBetaInnovVar(float &beta_innov_var) const { beta_innov_var = _aid_src_sideslip.innovation_variance; }
|
||||
void getBetaInnovRatio(float &beta_innov_ratio) const { beta_innov_ratio = _aid_src_sideslip.test_ratio; }
|
||||
|
||||
void getHaglInnov(float &hagl_innov) const { hagl_innov = _hagl_innov; }
|
||||
void getHaglInnovVar(float &hagl_innov_var) const { hagl_innov_var = _hagl_innov_var; }
|
||||
void getHaglInnovRatio(float &hagl_innov_ratio) const { hagl_innov_ratio = _hagl_test_ratio; }
|
||||
|
||||
void getHaglRateInnov(float &hagl_rate_innov) const { hagl_rate_innov = _rng_consistency_check.getInnov(); }
|
||||
void getHaglRateInnovVar(float &hagl_rate_innov_var) const { hagl_rate_innov_var = _rng_consistency_check.getInnovVar(); }
|
||||
void getHaglRateInnovRatio(float &hagl_rate_innov_ratio) const { hagl_rate_innov_ratio = _rng_consistency_check.getSignedTestRatioLpf(); }
|
||||
#endif // CONFIG_EKF2_SIDESLIP
|
||||
|
||||
void getGravityInnov(float grav_innov[3]) const { memcpy(grav_innov, _aid_src_gravity.innovation, sizeof(_aid_src_gravity.innovation)); }
|
||||
void getGravityInnovVar(float grav_innov_var[3]) const { memcpy(grav_innov_var, _aid_src_gravity.innovation_variance, sizeof(_aid_src_gravity.innovation_variance)); }
|
||||
@@ -204,9 +272,6 @@ public:
|
||||
// get the wind velocity var
|
||||
Vector2f getWindVelocityVariance() const { return P.slice<2, 2>(22, 22).diag(); }
|
||||
|
||||
// get the true airspeed in m/s
|
||||
float getTrueAirspeed() const;
|
||||
|
||||
// get the full covariance matrix
|
||||
const matrix::SquareMatrix<float, 24> &covariances() const { return P; }
|
||||
|
||||
@@ -287,8 +352,6 @@ public:
|
||||
return !_vertical_velocity_deadreckon_time_exceeded && !_control_status.flags.fake_hgt;
|
||||
}
|
||||
|
||||
bool isTerrainEstimateValid() const;
|
||||
|
||||
bool isYawFinalAlignComplete() const
|
||||
{
|
||||
const bool is_using_mag = (_control_status.flags.mag_3D || _control_status.flags.mag_hdg);
|
||||
@@ -299,17 +362,6 @@ public:
|
||||
&& (is_mag_alignment_in_flight_complete || !is_using_mag);
|
||||
}
|
||||
|
||||
uint8_t getTerrainEstimateSensorBitfield() const { return _hagl_sensor_status.value; }
|
||||
|
||||
// get the estimated terrain vertical position relative to the NED origin
|
||||
float getTerrainVertPos() const { return _terrain_vpos; };
|
||||
|
||||
// get the number of times the vertical terrain position has been reset
|
||||
uint8_t getTerrainVertPosResetCounter() const { return _terrain_vpos_reset_counter; };
|
||||
|
||||
// get the terrain variance
|
||||
float get_terrain_var() const { return _terrain_var; }
|
||||
|
||||
// gyro bias (states 10, 11, 12)
|
||||
Vector3f getGyroBias() const { return _state.delta_ang_bias / _dt_ekf_avg; } // get the gyroscope bias in rad/s
|
||||
Vector3f getGyroBiasVariance() const { return Vector3f{P(10, 10), P(11, 11), P(12, 12)} / sq(_dt_ekf_avg); } // get the gyroscope bias variance in rad/s
|
||||
@@ -410,39 +462,49 @@ public:
|
||||
uint8_t getHeightSensorRef() const { return _height_sensor_ref; }
|
||||
const BiasEstimator::status &getBaroBiasEstimatorStatus() const { return _baro_b_est.getStatus(); }
|
||||
const BiasEstimator::status &getGpsHgtBiasEstimatorStatus() const { return _gps_hgt_b_est.getStatus(); }
|
||||
const BiasEstimator::status &getRngHgtBiasEstimatorStatus() const { return _rng_hgt_b_est.getStatus(); }
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
const BiasEstimator::status &getEvHgtBiasEstimatorStatus() const { return _ev_hgt_b_est.getStatus(); }
|
||||
|
||||
const BiasEstimator::status &getEvPosBiasEstimatorStatus(int i) const { return _ev_pos_b_est.getStatus(i); }
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
const auto &aid_src_airspeed() const { return _aid_src_airspeed; }
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_SIDESLIP)
|
||||
const auto &aid_src_sideslip() const { return _aid_src_sideslip; }
|
||||
#endif // CONFIG_EKF2_SIDESLIP
|
||||
|
||||
const auto &aid_src_baro_hgt() const { return _aid_src_baro_hgt; }
|
||||
const auto &aid_src_rng_hgt() const { return _aid_src_rng_hgt; }
|
||||
|
||||
const auto &aid_src_fake_hgt() const { return _aid_src_fake_hgt; }
|
||||
const auto &aid_src_fake_pos() const { return _aid_src_fake_pos; }
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
const auto &aid_src_ev_hgt() const { return _aid_src_ev_hgt; }
|
||||
const auto &aid_src_ev_pos() const { return _aid_src_ev_pos; }
|
||||
const auto &aid_src_ev_vel() const { return _aid_src_ev_vel; }
|
||||
const auto &aid_src_ev_yaw() const { return _aid_src_ev_yaw; }
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
const auto &aid_src_gnss_hgt() const { return _aid_src_gnss_hgt; }
|
||||
const auto &aid_src_gnss_pos() const { return _aid_src_gnss_pos; }
|
||||
const auto &aid_src_gnss_vel() const { return _aid_src_gnss_vel; }
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
const auto &aid_src_gnss_yaw() const { return _aid_src_gnss_yaw; }
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
const auto &aid_src_mag_heading() const { return _aid_src_mag_heading; }
|
||||
const auto &aid_src_mag() const { return _aid_src_mag; }
|
||||
|
||||
const auto &aid_src_gravity() const { return _aid_src_gravity; }
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
const auto &aid_src_aux_vel() const { return _aid_src_aux_vel; }
|
||||
|
||||
const auto &aid_src_optical_flow() const { return _aid_src_optical_flow; }
|
||||
const auto &aid_src_terrain_optical_flow() const { return _aid_src_terrain_optical_flow; }
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
private:
|
||||
|
||||
@@ -483,13 +545,8 @@ private:
|
||||
|
||||
bool _filter_initialised{false}; ///< true when the EKF sttes and covariances been initialised
|
||||
|
||||
float _ev_yaw_pred_prev{}; ///< previous value of yaw state used by odometry fusion (m)
|
||||
bool _inhibit_ev_yaw_use{false}; ///< true when the vision yaw data should not be used (e.g.: NE fusion requires true North)
|
||||
|
||||
// booleans true when fresh sensor data is available at the fusion time horizon
|
||||
bool _gps_data_ready{false}; ///< true when new GPS data has fallen behind the fusion time horizon and is available to be fused
|
||||
bool _flow_data_ready{false}; ///< true when the leading edge of the optical flow integration period has fallen behind the fusion time horizon
|
||||
bool _flow_for_terrain_data_ready{false}; /// same flag as "_flow_data_ready" but used for separate terrain estimator
|
||||
|
||||
uint64_t _time_last_horizontal_aiding{0}; ///< amount of time we have been doing inertial only deadreckoning (uSec)
|
||||
uint64_t _time_last_v_pos_aiding{0};
|
||||
@@ -500,15 +557,7 @@ private:
|
||||
uint64_t _time_last_hor_vel_fuse{0}; ///< time the last fusion of horizontal velocity measurements was performed (uSec)
|
||||
uint64_t _time_last_ver_vel_fuse{0}; ///< time the last fusion of verticalvelocity measurements was performed (uSec)
|
||||
uint64_t _time_last_heading_fuse{0};
|
||||
|
||||
uint64_t _time_last_flow_terrain_fuse{0}; ///< time the last fusion of optical flow measurements for terrain estimation were performed (uSec)
|
||||
uint64_t _time_last_zero_velocity_fuse{0}; ///< last time of zero velocity update (uSec)
|
||||
uint64_t _time_last_healthy_rng_data{0};
|
||||
uint8_t _nb_gps_yaw_reset_available{0}; ///< remaining number of resets allowed before switching to another aiding source
|
||||
|
||||
uint8_t _nb_ev_pos_reset_available{0};
|
||||
uint8_t _nb_ev_vel_reset_available{0};
|
||||
uint8_t _nb_ev_yaw_reset_available{0};
|
||||
|
||||
Vector3f _last_known_pos{}; ///< last known local position vector (m)
|
||||
|
||||
@@ -537,11 +586,35 @@ private:
|
||||
Vector3f _delta_angle_bias_var_accum{}; ///< kahan summation algorithm accumulator for delta angle bias variance
|
||||
Vector3f _delta_vel_bias_var_accum{}; ///< kahan summation algorithm accumulator for delta velocity bias variance
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
Vector2f _drag_innov{}; ///< multirotor drag measurement innovation (m/sec**2)
|
||||
Vector2f _drag_innov_var{}; ///< multirotor drag measurement innovation variance ((m/sec**2)**2)
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
estimator_aid_source1d_s _aid_src_rng_hgt{};
|
||||
|
||||
HeightBiasEstimator _rng_hgt_b_est{HeightSensor::RANGE, _height_sensor_ref};
|
||||
|
||||
float _hagl_innov{0.0f}; ///< innovation of the last height above terrain measurement (m)
|
||||
float _hagl_innov_var{0.0f}; ///< innovation variance for the last height above terrain measurement (m**2)
|
||||
float _hagl_test_ratio{}; // height above terrain measurement innovation consistency check ratio
|
||||
|
||||
uint64_t _time_last_healthy_rng_data{0};
|
||||
|
||||
// Terrain height state estimation
|
||||
float _terrain_vpos{0.0f}; ///< estimated vertical position of the terrain underneath the vehicle in local NED frame (m)
|
||||
float _terrain_var{1e4f}; ///< variance of terrain position estimate (m**2)
|
||||
uint8_t _terrain_vpos_reset_counter{0}; ///< number of times _terrain_vpos has been reset
|
||||
uint64_t _time_last_hagl_fuse{0}; ///< last system time that a range sample was fused by the terrain estimator
|
||||
terrain_fusion_status_u _hagl_sensor_status{}; ///< Struct indicating type of sensor used to estimate height above ground
|
||||
|
||||
float _last_on_ground_posD{0.0f}; ///< last vertical position when the in_air status was false (m)
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
estimator_aid_source2d_s _aid_src_optical_flow{};
|
||||
estimator_aid_source2d_s _aid_src_terrain_optical_flow{};
|
||||
|
||||
// optical flow processing
|
||||
Vector3f _flow_gyro_bias{}; ///< bias errors in optical flow sensor rate gyro outputs (rad/sec)
|
||||
@@ -554,33 +627,52 @@ private:
|
||||
uint64_t _time_good_motion_us{0}; ///< last system time that on-ground motion was within limits (uSec)
|
||||
Vector2f _flow_compensated_XY_rad{}; ///< measured delta angle of the image about the X and Y body axes after removal of body rotation (rad), RH rotation is positive
|
||||
|
||||
bool _flow_data_ready{false}; ///< true when the leading edge of the optical flow integration period has fallen behind the fusion time horizon
|
||||
uint64_t _time_last_flow_terrain_fuse{0}; ///< time the last fusion of optical flow measurements for terrain estimation were performed (uSec)
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
estimator_aid_source1d_s _aid_src_baro_hgt{};
|
||||
estimator_aid_source1d_s _aid_src_rng_hgt{};
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
estimator_aid_source1d_s _aid_src_airspeed{};
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
#if defined(CONFIG_EKF2_SIDESLIP)
|
||||
estimator_aid_source1d_s _aid_src_sideslip{};
|
||||
#endif // CONFIG_EKF2_SIDESLIP
|
||||
|
||||
estimator_aid_source2d_s _aid_src_fake_pos{};
|
||||
estimator_aid_source1d_s _aid_src_fake_hgt{};
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
estimator_aid_source1d_s _aid_src_ev_hgt{};
|
||||
estimator_aid_source2d_s _aid_src_ev_pos{};
|
||||
estimator_aid_source3d_s _aid_src_ev_vel{};
|
||||
estimator_aid_source1d_s _aid_src_ev_yaw{};
|
||||
|
||||
float _ev_yaw_pred_prev{}; ///< previous value of yaw state used by odometry fusion (m)
|
||||
|
||||
uint8_t _nb_ev_pos_reset_available{0};
|
||||
uint8_t _nb_ev_vel_reset_available{0};
|
||||
uint8_t _nb_ev_yaw_reset_available{0};
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
bool _inhibit_ev_yaw_use{false}; ///< true when the vision yaw data should not be used (e.g.: NE fusion requires true North)
|
||||
|
||||
estimator_aid_source1d_s _aid_src_gnss_hgt{};
|
||||
estimator_aid_source2d_s _aid_src_gnss_pos{};
|
||||
estimator_aid_source3d_s _aid_src_gnss_vel{};
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
estimator_aid_source1d_s _aid_src_gnss_yaw{};
|
||||
uint8_t _nb_gps_yaw_reset_available{0}; ///< remaining number of resets allowed before switching to another aiding source
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
estimator_aid_source1d_s _aid_src_mag_heading{};
|
||||
estimator_aid_source3d_s _aid_src_mag{};
|
||||
|
||||
estimator_aid_source3d_s _aid_src_gravity{};
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
estimator_aid_source2d_s _aid_src_aux_vel{};
|
||||
|
||||
estimator_aid_source2d_s _aid_src_optical_flow{};
|
||||
estimator_aid_source2d_s _aid_src_terrain_optical_flow{};
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
// variables used for the GPS quality checks
|
||||
Vector3f _gps_pos_deriv_filt{}; ///< GPS NED position derivative (m/sec)
|
||||
@@ -608,7 +700,6 @@ private:
|
||||
AlphaFilter<float> _baro_lpf{0.1f}; ///< filtered barometric height measurement (m)
|
||||
|
||||
// Variables used to control activation of post takeoff functionality
|
||||
float _last_on_ground_posD{0.0f}; ///< last vertical position when the in_air status was false (m)
|
||||
uint64_t _flt_mag_align_start_time{0}; ///< time that inflight magnetic field alignment started (uSec)
|
||||
uint64_t _time_last_mov_3d_mag_suitable{0}; ///< last system time that sufficient movement to use 3-axis magnetometer fusion was detected (uSec)
|
||||
Vector3f _saved_mag_bf_variance {}; ///< magnetic field state variances that have been saved for use at the next initialisation (Gauss**2)
|
||||
@@ -626,13 +717,6 @@ private:
|
||||
Vector3f _prev_delta_ang_bias_var{}; ///< saved delta angle XYZ bias variances (rad/sec)
|
||||
Vector3f _prev_dvel_bias_var{}; ///< saved delta velocity XYZ bias variances (m/sec)**2
|
||||
|
||||
// Terrain height state estimation
|
||||
float _terrain_vpos{0.0f}; ///< estimated vertical position of the terrain underneath the vehicle in local NED frame (m)
|
||||
float _terrain_var{1e4f}; ///< variance of terrain position estimate (m**2)
|
||||
uint8_t _terrain_vpos_reset_counter{0}; ///< number of times _terrain_vpos has been reset
|
||||
uint64_t _time_last_hagl_fuse{0}; ///< last system time that a range sample was fused by the terrain estimator
|
||||
terrain_fusion_status_u _hagl_sensor_status{}; ///< Struct indicating type of sensor used to estimate height above ground
|
||||
|
||||
// height sensor status
|
||||
bool _baro_hgt_faulty{false}; ///< true if baro data have been declared faulty TODO: move to fault flags
|
||||
bool _gps_intermittent{true}; ///< true if data into the buffer is intermittent
|
||||
@@ -664,6 +748,9 @@ private:
|
||||
bool fuseYaw(float innovation, float variance, estimator_aid_source1d_s &aid_src_status, const Vector24f &H_YAW);
|
||||
void computeYawInnovVarAndH(float variance, float &innovation_variance, Vector24f &H_YAW) const;
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
void controlGpsYawFusion(const gpsSample &gps_sample, bool gps_checks_passing, bool gps_checks_failing);
|
||||
|
||||
// fuse the yaw angle obtained from a dual antenna GPS unit
|
||||
void fuseGpsYaw();
|
||||
|
||||
@@ -671,6 +758,13 @@ private:
|
||||
// return true if the reset was successful
|
||||
bool resetYawToGps(const float gnss_yaw);
|
||||
|
||||
void updateGpsYaw(const gpsSample &gps_sample);
|
||||
|
||||
void startGpsYawFusion(const gpsSample &gps_sample);
|
||||
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
void stopGpsYawFusion();
|
||||
|
||||
// fuse magnetometer declination measurement
|
||||
// argument passed in is the declination uncertainty in radians
|
||||
bool fuseDeclination(float decl_sigma);
|
||||
@@ -678,15 +772,38 @@ private:
|
||||
// apply sensible limits to the declination and length of the NE mag field states estimates
|
||||
void limitDeclination();
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
// control fusion of air data observations
|
||||
void controlAirDataFusion(const imuSample &imu_delayed);
|
||||
|
||||
void updateAirspeed(const airspeedSample &airspeed_sample, estimator_aid_source1d_s &aid_src) const;
|
||||
void fuseAirspeed(const airspeedSample &airspeed_sample, estimator_aid_source1d_s &aid_src);
|
||||
|
||||
void stopAirspeedFusion();
|
||||
|
||||
// Reset the wind states using the current airspeed measurement, ground relative nav velocity, yaw angle and assumption of zero sideslip
|
||||
void resetWindUsingAirspeed(const airspeedSample &airspeed_sample);
|
||||
|
||||
// perform a limited reset of the wind state covariances
|
||||
void resetWindCovarianceUsingAirspeed(const airspeedSample &airspeed_sample);
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_SIDESLIP)
|
||||
// control fusion of synthetic sideslip observations
|
||||
void controlBetaFusion(const imuSample &imu_delayed);
|
||||
|
||||
// fuse synthetic zero sideslip measurement
|
||||
void updateSideslip(estimator_aid_source1d_s &_aid_src_sideslip) const;
|
||||
void fuseSideslip(estimator_aid_source1d_s &_aid_src_sideslip);
|
||||
#endif // CONFIG_EKF2_SIDESLIP
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
// control fusion of multi-rotor drag specific force observations
|
||||
void controlDragFusion();
|
||||
|
||||
// fuse body frame drag specific forces for multi-rotor wind estimation
|
||||
void fuseDrag(const dragSample &drag_sample);
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
// fuse single velocity and position measurement
|
||||
bool fuseVelPosHeight(const float innov, const float innov_var, const int obs_index);
|
||||
@@ -710,12 +827,6 @@ private:
|
||||
|
||||
void resetVerticalVelocityToZero();
|
||||
|
||||
// fuse optical flow line of sight rate measurements
|
||||
void updateOptFlow(estimator_aid_source2d_s &aid_src);
|
||||
void fuseOptFlow();
|
||||
float predictFlowRange();
|
||||
Vector2f predictFlowVelBody();
|
||||
|
||||
// horizontal and vertical position aid source
|
||||
void updateHorizontalPositionAidSrcStatus(const uint64_t &time_us, const Vector2f &obs, const Vector2f &obs_var, const float innov_gate, estimator_aid_source2d_s &aid_src) const;
|
||||
void updateVerticalPositionAidSrcStatus(const uint64_t &time_us, const float obs, const float obs_var, const float innov_gate, estimator_aid_source1d_s &aid_src) const;
|
||||
@@ -732,18 +843,19 @@ private:
|
||||
void fuseVelocity(estimator_aid_source2d_s &vel_aid_src);
|
||||
void fuseVelocity(estimator_aid_source3d_s &vel_aid_src);
|
||||
|
||||
void updateGpsYaw(const gpsSample &gps_sample);
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
// range height
|
||||
void controlRangeHeightFusion();
|
||||
bool isConditionalRangeAidSuitable();
|
||||
void stopRngHgtFusion();
|
||||
|
||||
// calculate optical flow body angular rate compensation
|
||||
// returns false if bias corrected body rate data is unavailable
|
||||
bool calcOptFlowBodyRateComp();
|
||||
|
||||
// initialise the terrain vertical position estimator
|
||||
// terrain vertical position estimator
|
||||
void initHagl();
|
||||
|
||||
void runTerrainEstimator(const imuSample &imu_delayed);
|
||||
void predictHagl(const imuSample &imu_delayed);
|
||||
|
||||
float getTerrainVPos() const { return isTerrainEstimateValid() ? _terrain_vpos : _last_on_ground_posD; }
|
||||
|
||||
// update the terrain vertical position estimate using a height above ground measurement from the range finder
|
||||
void controlHaglRngFusion();
|
||||
void fuseHaglRng();
|
||||
@@ -753,14 +865,37 @@ private:
|
||||
void stopHaglRngFusion();
|
||||
float getRngVar();
|
||||
|
||||
void controlHaglFakeFusion();
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
// control fusion of optical flow observations
|
||||
void controlOpticalFlowFusion(const imuSample &imu_delayed);
|
||||
void stopFlowFusion();
|
||||
|
||||
void updateOnGroundMotionForOpticalFlowChecks();
|
||||
void resetOnGroundMotionForOpticalFlowChecks();
|
||||
|
||||
// calculate the measurement variance for the optical flow sensor
|
||||
float calcOptFlowMeasVar(const flowSample &flow_sample);
|
||||
|
||||
// calculate optical flow body angular rate compensation
|
||||
// returns false if bias corrected body rate data is unavailable
|
||||
bool calcOptFlowBodyRateComp();
|
||||
|
||||
// fuse optical flow line of sight rate measurements
|
||||
void updateOptFlow(estimator_aid_source2d_s &aid_src);
|
||||
void fuseOptFlow();
|
||||
float predictFlowRange();
|
||||
Vector2f predictFlowVelBody();
|
||||
|
||||
// update the terrain vertical position estimate using an optical flow measurement
|
||||
void controlHaglFlowFusion();
|
||||
void startHaglFlowFusion();
|
||||
void resetHaglFlow();
|
||||
void stopHaglFlowFusion();
|
||||
void fuseFlowForTerrain(estimator_aid_source2d_s &flow);
|
||||
|
||||
void controlHaglFakeFusion();
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
// reset the heading and magnetic field states using the declination and magnetometer measurements
|
||||
// return true if successful
|
||||
@@ -862,36 +997,30 @@ private:
|
||||
// Control the filter fusion modes
|
||||
void controlFusionModes(const imuSample &imu_delayed);
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
// control fusion of external vision observations
|
||||
void controlExternalVisionFusion();
|
||||
|
||||
void controlEvHeightFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source1d_s &aid_src);
|
||||
|
||||
void controlEvPosFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source2d_s &aid_src);
|
||||
void startEvPosFusion(const Vector2f &measurement, const Vector2f &measurement_var, estimator_aid_source2d_s &aid_src);
|
||||
void updateEvPosFusion(const Vector2f &measurement, const Vector2f &measurement_var, bool quality_sufficient, bool reset, estimator_aid_source2d_s &aid_src);
|
||||
void stopEvPosFusion();
|
||||
|
||||
void controlEvVelFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source3d_s &aid_src);
|
||||
void controlEvYawFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source1d_s &aid_src);
|
||||
|
||||
// control fusion of optical flow observations
|
||||
void controlOpticalFlowFusion(const imuSample &imu_delayed);
|
||||
void updateOnGroundMotionForOpticalFlowChecks();
|
||||
void resetOnGroundMotionForOpticalFlowChecks();
|
||||
void startEvPosFusion(const Vector2f &measurement, const Vector2f &measurement_var, estimator_aid_source2d_s &aid_src);
|
||||
void updateEvPosFusion(const Vector2f &measurement, const Vector2f &measurement_var, bool quality_sufficient, bool reset, estimator_aid_source2d_s &aid_src);
|
||||
void stopEvPosFusion();
|
||||
void stopEvHgtFusion();
|
||||
void stopEvVelFusion();
|
||||
void stopEvYawFusion();
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
// control fusion of GPS observations
|
||||
void controlGpsFusion(const imuSample &imu_delayed);
|
||||
bool shouldResetGpsFusion() const;
|
||||
bool isYawFailure() const;
|
||||
|
||||
void controlGpsYawFusion(const gpsSample &gps_sample, bool gps_checks_passing, bool gps_checks_failing);
|
||||
|
||||
// control fusion of magnetometer observations
|
||||
void controlMagFusion();
|
||||
|
||||
float getTerrainVPos() const { return isTerrainEstimateValid() ? _terrain_vpos : _last_on_ground_posD; }
|
||||
|
||||
bool magReset();
|
||||
bool haglYawResetReq();
|
||||
|
||||
@@ -908,15 +1037,6 @@ private:
|
||||
void runMagAndMagDeclFusions(const Vector3f &mag);
|
||||
void run3DMagAndDeclFusions(const Vector3f &mag);
|
||||
|
||||
// control fusion of air data observations
|
||||
void controlAirDataFusion(const imuSample &imu_delayed);
|
||||
|
||||
// control fusion of synthetic sideslip observations
|
||||
void controlBetaFusion(const imuSample &imu_delayed);
|
||||
|
||||
// control fusion of multi-rotor drag specific force observations
|
||||
void controlDragFusion();
|
||||
|
||||
// control fusion of fake position observations to constrain drift
|
||||
void controlFakePosFusion();
|
||||
|
||||
@@ -929,8 +1049,11 @@ private:
|
||||
|
||||
void controlZeroInnovationHeadingUpdate();
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
// control fusion of auxiliary velocity observations
|
||||
void controlAuxVelFusion();
|
||||
void stopAuxVelFusion();
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
void checkVerticalAccelerationHealth(const imuSample &imu_delayed);
|
||||
Likelihood estimateInertialNavFallingLikelihood() const;
|
||||
@@ -940,9 +1063,6 @@ private:
|
||||
void checkHeightSensorRefFallback();
|
||||
void controlBaroHeightFusion();
|
||||
void controlGnssHeightFusion(const gpsSample &gps_sample);
|
||||
void controlRangeHeightFusion();
|
||||
|
||||
bool isConditionalRangeAidSuitable();
|
||||
|
||||
void stopMagFusion();
|
||||
void stopMag3DFusion();
|
||||
@@ -952,17 +1072,12 @@ private:
|
||||
|
||||
void stopBaroHgtFusion();
|
||||
void stopGpsHgtFusion();
|
||||
void stopRngHgtFusion();
|
||||
void stopEvHgtFusion();
|
||||
|
||||
void updateGroundEffect();
|
||||
|
||||
// gravity fusion: heuristically enable / disable gravity fusion
|
||||
void controlGravityFusion(const imuSample &imu_delayed);
|
||||
|
||||
// calculate the measurement variance for the optical flow sensor
|
||||
float calcOptFlowMeasVar(const flowSample &flow_sample);
|
||||
|
||||
// initialise the quaternion covariances using rotation vector variances
|
||||
// do not call before quaternion states are initialised
|
||||
void initialiseQuatCovariances(Vector3f &rot_vec_var);
|
||||
@@ -976,18 +1091,8 @@ private:
|
||||
|
||||
// perform a reset of the wind states and related covariances
|
||||
void resetWind();
|
||||
|
||||
// Reset the wind states using the current airspeed measurement, ground relative nav velocity, yaw angle and assumption of zero sideslip
|
||||
void resetWindUsingAirspeed(const airspeedSample &airspeed_sample);
|
||||
|
||||
// perform a limited reset of the wind state covariances
|
||||
void resetWindCovarianceUsingAirspeed(const airspeedSample &airspeed_sample);
|
||||
|
||||
void resetWindToZero();
|
||||
|
||||
// check that the range finder data is continuous
|
||||
void updateRangeDataContinuity();
|
||||
|
||||
// Increase the yaw error variance of the quaternions
|
||||
// Argument is additional yaw variance in rad**2
|
||||
void increaseQuatYawErrVariance(float yaw_variance);
|
||||
@@ -1022,22 +1127,10 @@ private:
|
||||
return (sensor_timestamp != 0) && (sensor_timestamp + acceptance_interval > _time_latest_us);
|
||||
}
|
||||
|
||||
void stopAirspeedFusion();
|
||||
|
||||
void stopGpsFusion();
|
||||
void stopGpsPosFusion();
|
||||
void stopGpsVelFusion();
|
||||
|
||||
void startGpsYawFusion(const gpsSample &gps_sample);
|
||||
void stopGpsYawFusion();
|
||||
|
||||
void stopEvVelFusion();
|
||||
void stopEvYawFusion();
|
||||
|
||||
void stopAuxVelFusion();
|
||||
|
||||
void stopFlowFusion();
|
||||
|
||||
void resetFakePosFusion();
|
||||
void stopFakePosFusion();
|
||||
|
||||
@@ -1058,9 +1151,11 @@ private:
|
||||
|
||||
HeightBiasEstimator _baro_b_est{HeightSensor::BARO, _height_sensor_ref};
|
||||
HeightBiasEstimator _gps_hgt_b_est{HeightSensor::GNSS, _height_sensor_ref};
|
||||
HeightBiasEstimator _rng_hgt_b_est{HeightSensor::RANGE, _height_sensor_ref};
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
HeightBiasEstimator _ev_hgt_b_est{HeightSensor::EV, _height_sensor_ref};
|
||||
PositionBiasEstimator _ev_pos_b_est{static_cast<uint8_t>(PositionSensor::EV), _position_sensor_ref};
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
// Resets the main Nav EKf yaw to the estimator from the EKF-GSF yaw estimator
|
||||
// Resets the horizontal velocity and position to the default navigation sensor
|
||||
|
||||
@@ -150,7 +150,9 @@ void Ekf::resetHorizontalPositionTo(const Vector2f &new_horz_pos, const Vector2f
|
||||
|
||||
_state_reset_status.reset_count.posNE++;
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
_ev_pos_b_est.setBias(_ev_pos_b_est.getBias() - _state_reset_status.posNE_change);
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
//_gps_pos_b_est.setBias(_gps_pos_b_est.getBias() + _state_reset_status.posNE_change);
|
||||
|
||||
// Reset the timout timer
|
||||
@@ -196,9 +198,13 @@ void Ekf::resetVerticalPositionTo(const float new_vert_pos, float new_vert_pos_v
|
||||
_state_reset_status.reset_count.posD++;
|
||||
|
||||
_baro_b_est.setBias(_baro_b_est.getBias() + delta_z);
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
_ev_hgt_b_est.setBias(_ev_hgt_b_est.getBias() - delta_z);
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
_gps_hgt_b_est.setBias(_gps_hgt_b_est.getBias() + delta_z);
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
_rng_hgt_b_est.setBias(_rng_hgt_b_est.getBias() + delta_z);
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
// Reset the timout timer
|
||||
_time_last_hgt_fuse = _time_delayed_us;
|
||||
@@ -231,6 +237,7 @@ void Ekf::constrainStates()
|
||||
|
||||
float Ekf::compensateBaroForDynamicPressure(const float baro_alt_uncompensated) const
|
||||
{
|
||||
#if defined(CONFIG_EKF2_BARO_COMPENSATION)
|
||||
if (_control_status.flags.wind && local_position_is_valid()) {
|
||||
// calculate static pressure error = Pmeas - Ptruth
|
||||
// model position error sensitivity as a body fixed ellipse with a different scale in the positive and
|
||||
@@ -258,6 +265,7 @@ float Ekf::compensateBaroForDynamicPressure(const float baro_alt_uncompensated)
|
||||
// correct baro measurement using pressure error estimate and assuming sea level gravity
|
||||
return baro_alt_uncompensated + pstatic_err / (_air_density * CONSTANTS_ONE_G);
|
||||
}
|
||||
#endif // CONFIG_EKF2_BARO_COMPENSATION
|
||||
|
||||
// otherwise return the uncorrected baro measurement
|
||||
return baro_alt_uncompensated;
|
||||
@@ -302,6 +310,7 @@ void Ekf::getGpsVelPosInnovRatio(float &hvel, float &vvel, float &hpos, float &v
|
||||
vpos = _aid_src_gnss_hgt.test_ratio;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
void Ekf::getEvVelPosInnov(float hvel[2], float &vvel, float hpos[2], float &vpos) const
|
||||
{
|
||||
hvel[0] = _aid_src_ev_vel.innovation[0];
|
||||
@@ -332,7 +341,9 @@ void Ekf::getEvVelPosInnovRatio(float &hvel, float &vvel, float &hpos, float &vp
|
||||
hpos = fmaxf(_aid_src_ev_pos.test_ratio[0], _aid_src_ev_pos.test_ratio[1]);
|
||||
vpos = _aid_src_ev_hgt.test_ratio;
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
void Ekf::getAuxVelInnov(float aux_vel_innov[2]) const
|
||||
{
|
||||
aux_vel_innov[0] = _aid_src_aux_vel.innovation[0];
|
||||
@@ -344,7 +355,9 @@ void Ekf::getAuxVelInnovVar(float aux_vel_innov_var[2]) const
|
||||
aux_vel_innov_var[0] = _aid_src_aux_vel.innovation_variance[0];
|
||||
aux_vel_innov_var[1] = _aid_src_aux_vel.innovation_variance[1];
|
||||
}
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
void Ekf::getFlowInnov(float flow_innov[2]) const
|
||||
{
|
||||
flow_innov[0] = _aid_src_optical_flow.innovation[0];
|
||||
@@ -368,6 +381,7 @@ void Ekf::getTerrainFlowInnovVar(float flow_innov_var[2]) const
|
||||
flow_innov_var[0] = _aid_src_terrain_optical_flow.innovation_variance[0];
|
||||
flow_innov_var[1] = _aid_src_terrain_optical_flow.innovation_variance[1];
|
||||
}
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
// get the state vector at the delayed time horizon
|
||||
matrix::Vector<float, 24> Ekf::getStateAtFusionHorizonAsVector() const
|
||||
@@ -462,9 +476,11 @@ void Ekf::get_ekf_gpos_accuracy(float *ekf_eph, float *ekf_epv) const
|
||||
hpos_err = math::max(hpos_err, Vector2f(_aid_src_gnss_pos.innovation).norm());
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_pos) {
|
||||
hpos_err = math::max(hpos_err, Vector2f(_aid_src_ev_pos.innovation).norm());
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
}
|
||||
|
||||
*ekf_eph = hpos_err;
|
||||
@@ -485,9 +501,11 @@ void Ekf::get_ekf_lpos_accuracy(float *ekf_eph, float *ekf_epv) const
|
||||
hpos_err = math::max(hpos_err, Vector2f(_aid_src_gnss_pos.innovation).norm());
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_pos) {
|
||||
hpos_err = math::max(hpos_err, Vector2f(_aid_src_ev_pos.innovation).norm());
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
}
|
||||
|
||||
*ekf_eph = hpos_err;
|
||||
@@ -505,21 +523,26 @@ void Ekf::get_ekf_vel_accuracy(float *ekf_evh, float *ekf_evv) const
|
||||
if (_horizontal_deadreckon_time_exceeded) {
|
||||
float vel_err_conservative = 0.0f;
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
if (_control_status.flags.opt_flow) {
|
||||
float gndclearance = math::max(_params.rng_gnd_clearance, 0.1f);
|
||||
vel_err_conservative = math::max((_terrain_vpos - _state.pos(2)), gndclearance) * Vector2f(_aid_src_optical_flow.innovation).norm();
|
||||
}
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
if (_control_status.flags.gps) {
|
||||
vel_err_conservative = math::max(vel_err_conservative, Vector2f(_aid_src_gnss_pos.innovation).norm());
|
||||
}
|
||||
|
||||
} else if (_control_status.flags.ev_pos) {
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_pos) {
|
||||
vel_err_conservative = math::max(vel_err_conservative, Vector2f(_aid_src_ev_pos.innovation).norm());
|
||||
}
|
||||
|
||||
if (_control_status.flags.ev_vel) {
|
||||
vel_err_conservative = math::max(vel_err_conservative, Vector2f(_aid_src_ev_vel.innovation).norm());
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
hvel_err = math::max(hvel_err, vel_err_conservative);
|
||||
}
|
||||
@@ -543,6 +566,7 @@ void Ekf::get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, fl
|
||||
*hagl_min = NAN;
|
||||
*hagl_max = NAN;
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
// Calculate range finder limits
|
||||
const float rangefinder_hagl_min = _range_sensor.getValidMinVal();
|
||||
|
||||
@@ -551,15 +575,18 @@ void Ekf::get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, fl
|
||||
|
||||
// TODO : calculate visual odometry limits
|
||||
const bool relying_on_rangefinder = isOnlyActiveSourceOfVerticalPositionAiding(_control_status.flags.rng_hgt);
|
||||
const bool relying_on_optical_flow = isOnlyActiveSourceOfHorizontalAiding(_control_status.flags.opt_flow);
|
||||
|
||||
// Keep within range sensor limit when using rangefinder as primary height source
|
||||
if (relying_on_rangefinder) {
|
||||
*hagl_min = rangefinder_hagl_min;
|
||||
*hagl_max = rangefinder_hagl_max;
|
||||
}
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
// Keep within flow AND range sensor limits when exclusively using optical flow
|
||||
const bool relying_on_optical_flow = isOnlyActiveSourceOfHorizontalAiding(_control_status.flags.opt_flow);
|
||||
|
||||
if (relying_on_optical_flow) {
|
||||
// Calculate optical flow limits
|
||||
const float flow_hagl_min = fmaxf(rangefinder_hagl_min, _flow_min_distance);
|
||||
@@ -574,6 +601,7 @@ void Ekf::get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, fl
|
||||
*hagl_min = flow_hagl_min;
|
||||
*hagl_max = flow_hagl_max;
|
||||
}
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
}
|
||||
|
||||
void Ekf::resetImuBias()
|
||||
@@ -617,19 +645,28 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
|
||||
status = _innov_check_fail_status.value;
|
||||
|
||||
// return the largest magnetometer innovation test ratio
|
||||
mag = 0.f;
|
||||
|
||||
if (_control_status.flags.mag_hdg) {
|
||||
mag = sqrtf(_aid_src_mag_heading.test_ratio);
|
||||
|
||||
} else if (_control_status.flags.mag_3D) {
|
||||
mag = sqrtf(Vector3f(_aid_src_mag.test_ratio).max());
|
||||
|
||||
} else if (_control_status.flags.gps_yaw) {
|
||||
mag = sqrtf(_aid_src_gnss_yaw.test_ratio);
|
||||
|
||||
} else {
|
||||
mag = NAN;
|
||||
mag = math::max(mag, sqrtf(_aid_src_mag_heading.test_ratio));
|
||||
}
|
||||
|
||||
if (_control_status.flags.mag_3D) {
|
||||
mag = math::max(mag, sqrtf(Vector3f(_aid_src_mag.test_ratio).max()));
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
if (_control_status.flags.gps_yaw) {
|
||||
mag = math::max(mag, sqrtf(_aid_src_gnss_yaw.test_ratio));
|
||||
}
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_yaw) {
|
||||
mag = math::max(mag, sqrtf(_aid_src_ev_yaw.test_ratio));
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
// return the largest velocity and position innovation test ratio
|
||||
vel = NAN;
|
||||
pos = NAN;
|
||||
@@ -642,6 +679,7 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
|
||||
pos = math::max(gps_pos, FLT_MIN);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_vel) {
|
||||
float ev_vel = sqrtf(Vector3f(_aid_src_ev_vel.test_ratio).max());
|
||||
vel = math::max(vel, ev_vel, FLT_MIN);
|
||||
@@ -651,11 +689,14 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
|
||||
float ev_pos = sqrtf(Vector2f(_aid_src_ev_pos.test_ratio).max());
|
||||
pos = math::max(pos, ev_pos, FLT_MIN);
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
if (isOnlyActiveSourceOfHorizontalAiding(_control_status.flags.opt_flow)) {
|
||||
float of_vel = sqrtf(Vector2f(_aid_src_optical_flow.test_ratio).max());
|
||||
vel = math::max(of_vel, FLT_MIN);
|
||||
}
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
// return the combined vertical position innovation test ratio
|
||||
float hgt_sum = 0.f;
|
||||
@@ -671,15 +712,19 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
|
||||
n_hgt_sources++;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
if (_control_status.flags.rng_hgt) {
|
||||
hgt_sum += sqrtf(_aid_src_rng_hgt.test_ratio);
|
||||
n_hgt_sources++;
|
||||
}
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_hgt) {
|
||||
hgt_sum += sqrtf(_aid_src_ev_hgt.test_ratio);
|
||||
n_hgt_sources++;
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
if (n_hgt_sources > 0) {
|
||||
hgt = math::max(hgt_sum / static_cast<float>(n_hgt_sources), FLT_MIN);
|
||||
@@ -688,20 +733,26 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
|
||||
hgt = NAN;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
// return the airspeed fusion innovation test ratio
|
||||
tas = sqrtf(_aid_src_airspeed.test_ratio);
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
// return the terrain height innovation test ratio
|
||||
hagl = sqrtf(_hagl_test_ratio);
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_SIDESLIP)
|
||||
// return the synthetic sideslip innovation test ratio
|
||||
beta = sqrtf(_aid_src_sideslip.test_ratio);
|
||||
#endif // CONFIG_EKF2_SIDESLIP
|
||||
}
|
||||
|
||||
// return a bitmask integer that describes which state estimates are valid
|
||||
void Ekf::get_ekf_soln_status(uint16_t *status) const
|
||||
{
|
||||
ekf_solution_status_u soln_status;
|
||||
ekf_solution_status_u soln_status{};
|
||||
// TODO: Is this accurate enough?
|
||||
soln_status.flags.attitude = _control_status.flags.tilt_align && _control_status.flags.yaw_align && (_fault_status.value == 0);
|
||||
soln_status.flags.velocity_horiz = (isHorizontalAidingActive() || (_control_status.flags.fuse_beta && _control_status.flags.fuse_aspd)) && (_fault_status.value == 0);
|
||||
@@ -709,7 +760,9 @@ void Ekf::get_ekf_soln_status(uint16_t *status) const
|
||||
soln_status.flags.pos_horiz_rel = (_control_status.flags.gps || _control_status.flags.ev_pos || _control_status.flags.opt_flow) && (_fault_status.value == 0);
|
||||
soln_status.flags.pos_horiz_abs = (_control_status.flags.gps || _control_status.flags.ev_pos) && (_fault_status.value == 0);
|
||||
soln_status.flags.pos_vert_abs = soln_status.flags.velocity_vert;
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
soln_status.flags.pos_vert_agl = isTerrainEstimateValid();
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
soln_status.flags.const_pos_mode = !soln_status.flags.velocity_horiz;
|
||||
soln_status.flags.pred_pos_horiz_rel = soln_status.flags.pos_horiz_rel;
|
||||
soln_status.flags.pred_pos_horiz_abs = soln_status.flags.pos_horiz_abs;
|
||||
@@ -768,13 +821,23 @@ void Ekf::updateHorizontalDeadReckoningstatus()
|
||||
&& (isRecent(_time_last_hor_pos_fuse, _params.no_aid_timeout_max)
|
||||
|| isRecent(_time_last_hor_vel_fuse, _params.no_aid_timeout_max));
|
||||
|
||||
const bool optFlowAiding = _control_status.flags.opt_flow && isRecent(_aid_src_optical_flow.time_last_fuse, _params.no_aid_timeout_max);
|
||||
bool optFlowAiding = false;
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
optFlowAiding = _control_status.flags.opt_flow && isRecent(_aid_src_optical_flow.time_last_fuse, _params.no_aid_timeout_max);
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
const bool airDataAiding = _control_status.flags.wind &&
|
||||
bool airDataAiding = false;
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
airDataAiding = _control_status.flags.wind &&
|
||||
isRecent(_aid_src_airspeed.time_last_fuse, _params.no_aid_timeout_max) &&
|
||||
isRecent(_aid_src_sideslip.time_last_fuse, _params.no_aid_timeout_max);
|
||||
|
||||
_control_status.flags.wind_dead_reckoning = !velPosAiding && !optFlowAiding && airDataAiding;
|
||||
#else
|
||||
_control_status.flags.wind_dead_reckoning = false;
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
_control_status.flags.inertial_dead_reckoning = !velPosAiding && !optFlowAiding && !airDataAiding;
|
||||
|
||||
if (!_control_status.flags.inertial_dead_reckoning) {
|
||||
@@ -963,12 +1026,15 @@ void Ekf::initialiseQuatCovariances(Vector3f &rot_vec_var)
|
||||
void Ekf::updateGroundEffect()
|
||||
{
|
||||
if (_control_status.flags.in_air && !_control_status.flags.fixed_wing) {
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
if (isTerrainEstimateValid()) {
|
||||
// automatically set ground effect if terrain is valid
|
||||
float height = _terrain_vpos - _state.pos(2);
|
||||
_control_status.flags.gnd_effect = (height < _params.gnd_effect_max_hgt);
|
||||
|
||||
} else if (_control_status.flags.gnd_effect) {
|
||||
} else
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
if (_control_status.flags.gnd_effect) {
|
||||
// Turn off ground effect compensation if it times out
|
||||
if (isTimedOut(_time_last_gnd_effect_on, GNDEFFECT_TIMEOUT)) {
|
||||
_control_status.flags.gnd_effect = false;
|
||||
@@ -1118,9 +1184,12 @@ bool Ekf::resetYawToEKFGSF()
|
||||
_control_status.flags.gps_yaw_fault = true;
|
||||
_warning_events.flags.emergency_yaw_reset_gps_yaw_stopped = true;
|
||||
|
||||
} else if (_control_status.flags.ev_yaw) {
|
||||
}
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_control_status.flags.ev_yaw) {
|
||||
_inhibit_ev_yaw_use = true;
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1151,3 +1220,26 @@ void Ekf::resetGpsDriftCheckFilters()
|
||||
_gps_vertical_position_drift_rate_m_s = NAN;
|
||||
_gps_filtered_horizontal_velocity_m_s = NAN;
|
||||
}
|
||||
|
||||
void Ekf::resetWind()
|
||||
{
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
if (_control_status.flags.fuse_aspd && isRecent(_airspeed_sample_delayed.time_us, 1e6)) {
|
||||
resetWindUsingAirspeed(_airspeed_sample_delayed);
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
resetWindToZero();
|
||||
}
|
||||
|
||||
void Ekf::resetWindToZero()
|
||||
{
|
||||
ECL_INFO("reset wind to zero");
|
||||
|
||||
// If we don't have an airspeed measurement, then assume the wind is zero
|
||||
_state.wind_vel.setZero();
|
||||
|
||||
// start with a small initial uncertainty to improve the initial estimate
|
||||
P.uncorrelateCovarianceSetVariance<2>(22, _params.initial_wind_uncertainty);
|
||||
}
|
||||
|
||||
@@ -49,12 +49,24 @@ EstimatorInterface::~EstimatorInterface()
|
||||
delete _gps_buffer;
|
||||
delete _mag_buffer;
|
||||
delete _baro_buffer;
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
delete _range_buffer;
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
delete _airspeed_buffer;
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
delete _flow_buffer;
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
delete _ext_vision_buffer;
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
delete _drag_buffer;
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
delete _auxvel_buffer;
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
}
|
||||
|
||||
// Accumulate imu data and store to buffer at desired rate
|
||||
@@ -85,7 +97,9 @@ void EstimatorInterface::setIMUData(const imuSample &imu_sample)
|
||||
_min_obs_interval_us = (imu_sample.time_us - _time_delayed_us) / (_obs_buffer_length - 1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
setDragData(imu_sample);
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
}
|
||||
|
||||
void EstimatorInterface::setMagData(const magSample &mag_sample)
|
||||
@@ -164,7 +178,17 @@ void EstimatorInterface::setGpsData(const gpsMessage &gps)
|
||||
|
||||
gps_sample_new.hgt = (float)gps.alt * 1e-3f;
|
||||
|
||||
gps_sample_new.yaw = gps.yaw;
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
|
||||
if (PX4_ISFINITE(gps.yaw)) {
|
||||
_time_last_gps_yaw_buffer_push = _time_latest_us;
|
||||
gps_sample_new.yaw = gps.yaw;
|
||||
gps_sample_new.yaw_acc = PX4_ISFINITE(gps.yaw_accuracy) ? gps.yaw_accuracy : 0.f;
|
||||
|
||||
} else {
|
||||
gps_sample_new.yaw = NAN;
|
||||
gps_sample_new.yaw_acc = 0.f;
|
||||
}
|
||||
|
||||
if (PX4_ISFINITE(gps.yaw_offset)) {
|
||||
_gps_yaw_offset = gps.yaw_offset;
|
||||
@@ -173,12 +197,7 @@ void EstimatorInterface::setGpsData(const gpsMessage &gps)
|
||||
_gps_yaw_offset = 0.0f;
|
||||
}
|
||||
|
||||
if (PX4_ISFINITE(gps.yaw_accuracy)) {
|
||||
gps_sample_new.yaw_acc = gps.yaw_accuracy;
|
||||
|
||||
} else {
|
||||
gps_sample_new.yaw_acc = 0.f;
|
||||
}
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
// Only calculate the relative position if the WGS-84 location of the origin is set
|
||||
if (collect_gps(gps)) {
|
||||
@@ -192,9 +211,6 @@ void EstimatorInterface::setGpsData(const gpsMessage &gps)
|
||||
_gps_buffer->push(gps_sample_new);
|
||||
_time_last_gps_buffer_push = _time_latest_us;
|
||||
|
||||
if (PX4_ISFINITE(gps.yaw)) {
|
||||
_time_last_gps_yaw_buffer_push = _time_latest_us;
|
||||
}
|
||||
|
||||
} else {
|
||||
ECL_WARN("GPS data too fast %" PRIi64 " < %" PRIu64 " + %d", time_us, _gps_buffer->get_newest().time_us, _min_obs_interval_us);
|
||||
@@ -237,6 +253,7 @@ void EstimatorInterface::setBaroData(const baroSample &baro_sample)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
void EstimatorInterface::setAirspeedData(const airspeedSample &airspeed_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
@@ -271,7 +288,9 @@ void EstimatorInterface::setAirspeedData(const airspeedSample &airspeed_sample)
|
||||
ECL_WARN("airspeed data too fast %" PRIi64 " < %" PRIu64 " + %d", time_us, _airspeed_buffer->get_newest().time_us, _min_obs_interval_us);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
void EstimatorInterface::setRangeData(const rangeSample &range_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
@@ -307,7 +326,9 @@ void EstimatorInterface::setRangeData(const rangeSample &range_sample)
|
||||
ECL_WARN("range data too fast %" PRIi64 " < %" PRIu64 " + %d", time_us, _range_buffer->get_newest().time_us, _min_obs_interval_us);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
void EstimatorInterface::setOpticalFlowData(const flowSample &flow)
|
||||
{
|
||||
if (!_initialised) {
|
||||
@@ -342,8 +363,9 @@ void EstimatorInterface::setOpticalFlowData(const flowSample &flow)
|
||||
ECL_WARN("optical flow data too fast %" PRIi64 " < %" PRIu64 " + %d", time_us, _flow_buffer->get_newest().time_us, _min_obs_interval_us);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
// set attitude and position data derived from an external vision system
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
void EstimatorInterface::setExtVisionData(const extVisionSample &evdata)
|
||||
{
|
||||
if (!_initialised) {
|
||||
@@ -380,7 +402,9 @@ void EstimatorInterface::setExtVisionData(const extVisionSample &evdata)
|
||||
ECL_WARN("EV data too fast %" PRIi64 " < %" PRIu64 " + %d", time_us, _ext_vision_buffer->get_newest().time_us, _min_obs_interval_us);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
void EstimatorInterface::setAuxVelData(const auxVelSample &auxvel_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
@@ -415,6 +439,7 @@ void EstimatorInterface::setAuxVelData(const auxVelSample &auxvel_sample)
|
||||
ECL_WARN("aux velocity data too fast %" PRIi64 " < %" PRIu64 " + %d", time_us, _auxvel_buffer->get_newest().time_us, _min_obs_interval_us);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
void EstimatorInterface::setSystemFlagData(const systemFlagUpdate &system_flags)
|
||||
{
|
||||
@@ -452,6 +477,7 @@ void EstimatorInterface::setSystemFlagData(const systemFlagUpdate &system_flags)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
void EstimatorInterface::setDragData(const imuSample &imu)
|
||||
{
|
||||
// down-sample the drag specific force data by accumulating and calculating the mean when
|
||||
@@ -502,45 +528,59 @@ void EstimatorInterface::setDragData(const imuSample &imu)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
bool EstimatorInterface::initialise_interface(uint64_t timestamp)
|
||||
{
|
||||
// find the maximum time delay the buffers are required to handle
|
||||
|
||||
// it's reasonable to assume that aux velocity device has low delay. TODO: check the delay only if the aux device is used
|
||||
float max_time_delay_ms = math::max((float)_params.sensor_interval_max_ms, _params.auxvel_delay_ms);
|
||||
float max_time_delay_ms = _params.sensor_interval_max_ms;
|
||||
|
||||
// aux vel
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
max_time_delay_ms = math::max(_params.auxvel_delay_ms, max_time_delay_ms);
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
// using baro
|
||||
if (_params.baro_ctrl > 0) {
|
||||
max_time_delay_ms = math::max(_params.baro_delay_ms, max_time_delay_ms);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
// using airspeed
|
||||
if (_params.arsp_thr > FLT_EPSILON) {
|
||||
max_time_delay_ms = math::max(_params.airspeed_delay_ms, max_time_delay_ms);
|
||||
}
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
// mag mode
|
||||
if (_params.mag_fusion_type != MagFuseType::NONE) {
|
||||
max_time_delay_ms = math::max(_params.mag_delay_ms, max_time_delay_ms);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
// using range finder
|
||||
if ((_params.rng_ctrl != RngCtrl::DISABLED)) {
|
||||
max_time_delay_ms = math::max(_params.range_delay_ms, max_time_delay_ms);
|
||||
}
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
if (_params.gnss_ctrl > 0) {
|
||||
max_time_delay_ms = math::max(_params.gps_delay_ms, max_time_delay_ms);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
if (_params.fusion_mode & SensorFusionMask::USE_OPT_FLOW) {
|
||||
max_time_delay_ms = math::max(_params.flow_delay_ms, max_time_delay_ms);
|
||||
}
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_params.ev_ctrl > 0) {
|
||||
max_time_delay_ms = math::max(_params.ev_delay_ms, max_time_delay_ms);
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
const float filter_update_period_ms = _params.filter_update_interval_us / 1000.f;
|
||||
|
||||
@@ -666,25 +706,35 @@ void EstimatorInterface::print_status()
|
||||
printf("baro buffer: %d/%d (%d Bytes)\n", _baro_buffer->entries(), _baro_buffer->get_length(), _baro_buffer->get_total_size());
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
if (_range_buffer) {
|
||||
printf("range buffer: %d/%d (%d Bytes)\n", _range_buffer->entries(), _range_buffer->get_length(), _range_buffer->get_total_size());
|
||||
}
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
if (_airspeed_buffer) {
|
||||
printf("airspeed buffer: %d/%d (%d Bytes)\n", _airspeed_buffer->entries(), _airspeed_buffer->get_length(), _airspeed_buffer->get_total_size());
|
||||
}
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
if (_flow_buffer) {
|
||||
printf("flow buffer: %d/%d (%d Bytes)\n", _flow_buffer->entries(), _flow_buffer->get_length(), _flow_buffer->get_total_size());
|
||||
}
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
if (_ext_vision_buffer) {
|
||||
printf("vision buffer: %d/%d (%d Bytes)\n", _ext_vision_buffer->entries(), _ext_vision_buffer->get_length(), _ext_vision_buffer->get_total_size());
|
||||
}
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
if (_drag_buffer) {
|
||||
printf("drag buffer: %d/%d (%d Bytes)\n", _drag_buffer->entries(), _drag_buffer->get_length(), _drag_buffer->get_total_size());
|
||||
}
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
_output_predictor.print_status();
|
||||
}
|
||||
|
||||
@@ -64,11 +64,14 @@
|
||||
#include "common.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "imu_down_sampler.hpp"
|
||||
#include "range_finder_consistency_check.hpp"
|
||||
#include "sensor_range_finder.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "output_predictor.h"
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
# include "range_finder_consistency_check.hpp"
|
||||
# include "sensor_range_finder.hpp"
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#include <lib/geo/geo.h>
|
||||
#include <matrix/math.hpp>
|
||||
#include <mathlib/mathlib.h>
|
||||
@@ -90,17 +93,43 @@ public:
|
||||
|
||||
void setBaroData(const baroSample &baro_sample);
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
void setAirspeedData(const airspeedSample &airspeed_sample);
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
void setRangeData(const rangeSample &range_sample);
|
||||
|
||||
// set sensor limitations reported by the rangefinder
|
||||
void set_rangefinder_limits(float min_distance, float max_distance)
|
||||
{
|
||||
_range_sensor.setLimits(min_distance, max_distance);
|
||||
}
|
||||
|
||||
const rangeSample &get_rng_sample_delayed() { return *(_range_sensor.getSampleAddress()); }
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
// if optical flow sensor gyro delta angles are not available, set gyro_xyz vector fields to NaN and the EKF will use its internal delta angle data instead
|
||||
void setOpticalFlowData(const flowSample &flow);
|
||||
|
||||
// set sensor limitations reported by the optical flow sensor
|
||||
void set_optical_flow_limits(float max_flow_rate, float min_distance, float max_distance)
|
||||
{
|
||||
_flow_max_rate = max_flow_rate;
|
||||
_flow_min_distance = min_distance;
|
||||
_flow_max_distance = max_distance;
|
||||
}
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
// set external vision position and attitude data
|
||||
void setExtVisionData(const extVisionSample &evdata);
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
void setAuxVelData(const auxVelSample &auxvel_sample);
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
void setSystemFlagData(const systemFlagUpdate &system_flags);
|
||||
|
||||
@@ -147,20 +176,6 @@ public:
|
||||
// set air density used by the multi-rotor specific drag force fusion
|
||||
void set_air_density(float air_density) { _air_density = air_density; }
|
||||
|
||||
// set sensor limitations reported by the rangefinder
|
||||
void set_rangefinder_limits(float min_distance, float max_distance)
|
||||
{
|
||||
_range_sensor.setLimits(min_distance, max_distance);
|
||||
}
|
||||
|
||||
// set sensor limitations reported by the optical flow sensor
|
||||
void set_optical_flow_limits(float max_flow_rate, float min_distance, float max_distance)
|
||||
{
|
||||
_flow_max_rate = max_flow_rate;
|
||||
_flow_min_distance = min_distance;
|
||||
_flow_max_distance = max_distance;
|
||||
}
|
||||
|
||||
// the flags considered are opt_flow, gps, ev_vel and ev_pos
|
||||
bool isOnlyActiveSourceOfHorizontalAiding(bool aiding_flag) const;
|
||||
|
||||
@@ -242,7 +257,6 @@ public:
|
||||
const uint64_t &time_delayed_us() const { return _time_delayed_us; }
|
||||
|
||||
const gpsSample &get_gps_sample_delayed() const { return _gps_sample_delayed; }
|
||||
const rangeSample &get_rng_sample_delayed() { return *(_range_sensor.getSampleAddress()); }
|
||||
|
||||
const bool &global_origin_valid() const { return _NED_origin_initialised; }
|
||||
const MapProjection &global_origin() const { return _pos_ref; }
|
||||
@@ -290,20 +304,36 @@ protected:
|
||||
|
||||
// measurement samples capturing measurements on the delayed time horizon
|
||||
gpsSample _gps_sample_delayed{};
|
||||
sensor::SensorRangeFinder _range_sensor{};
|
||||
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
airspeedSample _airspeed_sample_delayed{};
|
||||
flowSample _flow_sample_delayed{};
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
extVisionSample _ev_sample_prev{};
|
||||
dragSample _drag_down_sampled{}; // down sampled drag specific force data (filter prediction rate -> observation rate)
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
RingBuffer<rangeSample> *_range_buffer{nullptr};
|
||||
uint64_t _time_last_range_buffer_push{0};
|
||||
|
||||
sensor::SensorRangeFinder _range_sensor{};
|
||||
RangeFinderConsistencyCheck _rng_consistency_check;
|
||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||
|
||||
float _air_density{CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C}; // air density (kg/m**3)
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
RingBuffer<flowSample> *_flow_buffer{nullptr};
|
||||
|
||||
flowSample _flow_sample_delayed{};
|
||||
|
||||
// Sensor limitations
|
||||
float _flow_max_rate{1.0f}; ///< maximum angular flow rate that the optical flow sensor can measure (rad/s)
|
||||
float _flow_min_distance{0.0f}; ///< minimum distance that the optical flow sensor can operate at (m)
|
||||
float _flow_max_distance{10.f}; ///< maximum distance that the optical flow sensor can operate at (m)
|
||||
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||
|
||||
float _air_density{CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C}; // air density (kg/m**3)
|
||||
|
||||
bool _imu_updated{false}; // true if the ekf should update (completed downsampling process)
|
||||
bool _initialised{false}; // true if the ekf interface instance (data buffering) is initialized
|
||||
@@ -314,13 +344,19 @@ protected:
|
||||
MapProjection _pos_ref{}; // Contains WGS-84 position latitude and longitude of the EKF origin
|
||||
MapProjection _gps_pos_prev{}; // Contains WGS-84 position latitude and longitude of the previous GPS message
|
||||
float _gps_alt_prev{0.0f}; // height from the previous GPS message (m)
|
||||
#if defined(CONFIG_EKF2_GNSS_YAW)
|
||||
float _gps_yaw_offset{0.0f}; // Yaw offset angle for dual GPS antennas used for yaw estimation (radians).
|
||||
|
||||
// innovation consistency check monitoring ratios
|
||||
AlphaFilter<float> _gnss_yaw_signed_test_ratio_lpf{0.1f}; // average signed test ratio used to detect a bias in the state
|
||||
uint64_t _time_last_gps_yaw_buffer_push{0};
|
||||
#endif // CONFIG_EKF2_GNSS_YAW
|
||||
|
||||
float _hagl_test_ratio{}; // height above terrain measurement innovation consistency check ratio
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
RingBuffer<dragSample> *_drag_buffer{nullptr};
|
||||
dragSample _drag_down_sampled{}; // down sampled drag specific force data (filter prediction rate -> observation rate)
|
||||
Vector2f _drag_test_ratio{}; // drag innovation consistency check ratio
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
innovation_fault_status_u _innov_check_fail_status{};
|
||||
|
||||
bool _horizontal_deadreckon_time_exceeded{true};
|
||||
@@ -341,20 +377,23 @@ protected:
|
||||
RingBuffer<gpsSample> *_gps_buffer{nullptr};
|
||||
RingBuffer<magSample> *_mag_buffer{nullptr};
|
||||
RingBuffer<baroSample> *_baro_buffer{nullptr};
|
||||
RingBuffer<rangeSample> *_range_buffer{nullptr};
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
RingBuffer<airspeedSample> *_airspeed_buffer{nullptr};
|
||||
RingBuffer<flowSample> *_flow_buffer{nullptr};
|
||||
#endif // CONFIG_EKF2_AIRSPEED
|
||||
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
RingBuffer<extVisionSample> *_ext_vision_buffer{nullptr};
|
||||
RingBuffer<dragSample> *_drag_buffer{nullptr};
|
||||
uint64_t _time_last_ext_vision_buffer_push{0};
|
||||
#endif // CONFIG_EKF2_EXTERNAL_VISION
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
RingBuffer<auxVelSample> *_auxvel_buffer{nullptr};
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
RingBuffer<systemFlagUpdate> *_system_flag_buffer{nullptr};
|
||||
|
||||
uint64_t _time_last_gps_buffer_push{0};
|
||||
uint64_t _time_last_gps_yaw_buffer_push{0};
|
||||
uint64_t _time_last_mag_buffer_push{0};
|
||||
uint64_t _time_last_baro_buffer_push{0};
|
||||
uint64_t _time_last_range_buffer_push{0};
|
||||
uint64_t _time_last_ext_vision_buffer_push{0};
|
||||
|
||||
uint64_t _time_last_gnd_effect_on{0};
|
||||
|
||||
@@ -380,16 +419,18 @@ protected:
|
||||
|
||||
private:
|
||||
|
||||
inline void setDragData(const imuSample &imu);
|
||||
#if defined(CONFIG_EKF2_DRAG_FUSION)
|
||||
void setDragData(const imuSample &imu);
|
||||
|
||||
// Used by the multi-rotor specific drag force fusion
|
||||
uint8_t _drag_sample_count{0}; // number of drag specific force samples assumulated at the filter prediction rate
|
||||
float _drag_sample_time_dt{0.0f}; // time integral across all samples used to form _drag_down_sampled (sec)
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
void printBufferAllocationFailed(const char *buffer_name);
|
||||
|
||||
ImuDownSampler _imu_down_sampler{_params.filter_update_interval_us};
|
||||
|
||||
unsigned _min_obs_interval_us{0}; // minimum time interval between observations that will guarantee data is not lost (usec)
|
||||
|
||||
// Used by the multi-rotor specific drag force fusion
|
||||
uint8_t _drag_sample_count{0}; // number of drag specific force samples assumulated at the filter prediction rate
|
||||
float _drag_sample_time_dt{0.0f}; // time integral across all samples used to form _drag_down_sampled (sec)
|
||||
};
|
||||
#endif // !EKF_ESTIMATOR_INTERFACE_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user