Repository navigation
Conversation
The header declared motor[0..7], while the I and P frames write getMotorCount() values, up to MAX_SUPPORTED_MOTORS (12). With 9 to 12 motors and motor logging on, every frame carried more values than the header described, and no frame of the log decoded. The header now declares motor[8..11] behind four more conditions. The condition cache was a uint64_t already full on dual-gyro targets, so it becomes an array of 32-bit words sized for every condition. The MSP enum reference gets the new values (that enum's section only).
With mag_learn ON, the compass keeps one raw reading per field direction during each flight (12 headings x 6 equal-area elevation bands), refits the offsets with the sphere fit the ground calibration already uses and saves magzero at disarm when the flight turned through at least 270 degrees and the fit agrees with the stored calibration: radius spread within 5%, radius within 30% of what maggain implies, no axis moving more than 30% of the radius. maggain is kept. The fit runs on samples scaled by maggain, so axes of different sensitivity weigh alike, and a ridge toward the stored offset keeps a direction the flight never swept (the vertical in level flight, the normal of a circle flown at one bank) where it was. A calibration started while armed, or mag_learn switched off, drops what the flight had collected. The save waits out the 5 s in which INAV accepts an emergency rearm after a disarm, so a rearm finds the same calibration and no flash write, and then for the aircraft to be still; if it still moves a minute after the disarm, nothing is saved. EMERGENCY_INFLIGHT_REARM_TIME_WINDOW_MS moves to fc_core.h for that. The estimate is refitted about once a second in flight and logged in the blackbox slow frame (magBias, magBiasFlags, magBiasSectors, magBiasSpread; header mag_learn and mag_zero) under its own field group, MAG_LEARN (on by default in a new configuration, logged only while mag_learn is ON), and MSP2_INAV_MAG_LEARN reports it for the Configurator. Built on iNavFlight#12127 for the wider condition cache and on the slow-frame conditions. USE_MAG_LEARN on USE_MAG targets with more than 512 KB of flash. The setting is appended to compassConfig_t with a zero default, so the PG version stays: on ARM (short enums) the struct had no tail padding and grows from 24 to 26 bytes; on SITL the new byte lands in former tail padding, which the reset template writes as zero.
A Gaussian sum of five 3-state EKFs (velocity north and east, yaw), each started from a different yaw, as in Paul Riseborough's EKF-GSF yaw estimator. Each model is handed the horizontal acceleration and the yaw rate instead of running its own attitude filter, so roll and pitch can come from INAV's AHRS. Core only, with unit tests on simulated flights.
Every AHRS update adds the horizontal acceleration and the yaw rate, both from rMat's roll and pitch only, so the compass never reaches the estimate. A 50 Hz task steps the filter on 20 ms windows held back by the GPS delay and fuses each GPS velocity at the time it was taken, with a 3D fix, 6 satellites and 5 m accuracy, and not while the aircraft rotates faster than 90 deg/s. It learns from INAV's first flight detection to its landing detection, since isFlightDetected alone drops whenever the throttle is under cruise or hover. The estimate counts as usable once it has seen 25 m/s of velocity change and its sigma has stayed under 15 deg for 3 s. Blackbox group GSF: yaw, sigma, velocity change seen, filtered NIS of the leading model, flags. Targets with more than 512 KB of flash.
…sf_yaw) The GPS delay starts at one receiver interval plus 20 ms (120 ms at 10 Hz, 220 ms at 5 Hz, ArduPilot's u-blox lags) and is then measured in flight: for each delay from 0 to 300 ms, how well the 400 ms velocity change of the IMU matches the GPS one after the best rotation, the rotation standing for the unknown heading. A measurement is kept once its least-squares sigma is under 25 ms. Manoeuvres count per second and only past 1 m/s, so vibration and tilt errors do not add up in straight flight. A filtered NIS over 6 flags the estimate inconsistent and not usable; 10 s of it start it over and give the compass its trust back. The yaw rate fed to the models is the rate of the nose's heading (the Euler yaw rate from roll and pitch), not the rate about the vertical: a roll about the nose at pitch leaves the heading alone. With ahrs_gsf_yaw on (off by default), a usable estimate replaces the GPS course as the AHRS's GPS heading, the compass is left out after it has stayed 25 deg or 3 sigma off it for 3 s (back after 10 s within half that, and whenever disarmed), and a heading 45 deg off with no compass to hold it is reset to it, at most twice a flight; the navigation heading target moves with the reset so the aircraft does not turn. The compass still reaches the estimate through the tilt, since the GPS inertia compensation uses the full orientation. Timers are 64-bit, so a flight past 35 min keeps its state. The IMU accumulation runs only while the task does. A tailsitter transition restarts the estimator. Blackbox: gsfGpsDelay, gsfMagErr, more flags, header ahrs_gsf_yaw; the log is where the estimator is read, there is no MSP message. imuConfig_t grows by the appended zero-default field without a version bump (pgLoad copies the stored bytes over the defaults): the PG size database says 18 bytes at version 2.
|
ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing |
PR Summary by QodoAdd compass-independent GSF heading for airplanes
AI Description
Diagram
High-Level Assessment
Files changed (32)
|
Code Review by Qodo
1.
|
|
RAM / Flash usage vs. base commit
See RAM/flash optimization guide for techniques to reduce usage. |
|
Test firmware build ready — commit Download firmware for PR #12159 251 targets built. Find your board's
|
With correlated north and east errors the 5 sigma clip judged spikes along the correlation as ordinary and clipped ordinary updates across it. A unit test fuses a 6.7 sigma innovation of opposite signs.
… the compass - Usable needs a GPS velocity in the last second: without one the heading is the gyro's alone. - The compass is left out only while the estimate is usable, so a lost GPS gives it back at once. - The pending GPS sample is fused with the delay it was stamped and stepped to with; a new delay applies from the next one, and a sample the filter is already well past (the delay grew) is dropped. - gsfYawInit() zeroes the state at boot from imuInit(): AT32's startup clears .bss but not .fastram_bss.
|
Expected: the GSF heading estimator, about 11.2-11.4 KB of flash where it is built, and its state, about 2.3 KB in FASTRAM (CCM on F405, DTCM on F7 and H7). MATEKF722 builds without the estimator (+120 B there). The +32 B of ITCM is not GSF code: on KAKUTEF7, which shows the same +32 B, the only function that grows in ITCM is gyroFilter() (+36 B, one more instruction), where LTO addresses the gyro's variables from different base registers once the new static data has moved them. |
|
The flash and the fast RAM are the GSF heading ( |
|
Flight data from four flights on 2026-10-17 and 18 on a fixed wing (1.2 m T-28, TBS Lucid H7 Wing, u-blox GPS at
Never inconsistent, no heading reset. The compass field followed the motor current: |
Builds on #12142 (mag_learn), so this branch contains it and the diff shows both until #12142 is merged: the blackbox group and the settings sit after mag_learn's. The change of its own is the last three commits.
An airplane's heading comes from the compass, and with a bad compass (interference, a wrong
align_mag, an old calibration) INAV has nothing that tells it so: the GPS course helps only in straight flight without wind. This adds a heading that doesn't use the compass at all, the Gaussian sum filter of Paul Riseborough's EKF-GSF yaw estimator (ArduPilotEKFGSF_yaw, PX4yaw_estimator), and lets the AHRS use it if asked.How it works:
imuUpdateAttitude()and each GPS sample fused when the filter reaches its time.GSF, off by default:gsfYaw,gsfYawStd,gsfExcitation,gsfNis,gsfFlags,gsfGpsDelay,gsfMagErr(compass heading minus the estimate).With
ahrs_gsf_yaw = ON(default OFF) the AHRS uses it:ahrs_gps_yaw_weightalready sets;Off, the estimator still runs and the blackbox logs it, so a flight shows what it would have done.
USE_GSF_YAWis on with GPS on targets with more than 512 KB of flash.Size against #12142:
On KAKUTEF7 and KAKUTEF7HDV the ITCM grows by 104 B, to 16336 of 16384: none of it is new code.
nmshows the same FAST_CODE functions a little longer (gyroFilter +36, pidController +20, dTermProcess +16, mixTable +16, applyRateDynamics +8, pidApplyMulticopterRateController +8), because LTO addresses the globals differently once the program grows; moving the new globals out of FASTRAM, or into one struct, didn't change it.imuConfig_tgrows from 16 to 18 bytes withgsf_yawappended at offset 16, after the end of the stored record, with a zero default, so the PG version stays and a stored config keeps its values;pg_struct_sizes.reference.dbis updated so thatvalidate-pg-for-release.shagrees.Tested:
ahrs_gsf_yaw = ON, the compass left out, one reset, then the AHRS within 4 degrees for the rest of the flight.ahrs_gps_yaw_weight = 0(AHRS at +178 until a reset to +10 at 98 s, then within 7 degrees; the delay measured at 118-146 ms, the X-Plane plugin's accelerometer itself being about 170 ms late).Configurator: iNavFlight/inav-configurator#2844. Blackbox Explorer: iNavFlight/blackbox-log-viewer#127.