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.
…mag_yaw_trim With the GSF heading known each sample is the earth field turned into the body plus the offset, linear in both, and only weighted running means are kept. Samples count while the heading is usable, weighed by how sure it is; the fit needs a half turn, more heading sectors than unknowns, so a heading error that differs between the legs leaves a residual. Its residual tells a compass that does not follow the attitude (orientation, scale, soft iron), the fitted field's direction one turned about the vertical. No attitude fit on tailsitters, whose body axes turn at each transition. The sphere fit still decides as before. The attitude fit confirms a step beyond the 30% limit when the two agree on the horizontal offsets, refines a smaller one, and alone moves every axis at most 10% of the field a flight; the vertical never moves more than that. Fits that disagree are a tilt the alignment does not know, and nothing is saved. A change under 1% is not written. mag_yaw_trim turns the reading about the airplane's vertical after the alignment, which can only be set to what was measured by hand. While the attitude fit decides, the angle between the field it found and magnetic north becomes a change to the trim: up to 5 degrees a flight, nothing under 1, within the setting's range; beyond 15 degrees, or with no room left, the compass is reported as turned instead. It lives with magLearn under USE_MAG_LEARN, appended with a zero default; a compass calibration or a detected orientation sets it back to 0. The fitted field and the trim go to the blackbox (magBiasField, magBiasYawTrim, the mag_yaw_trim header line) and are appended to MSP2_INAV_MAG_LEARN (msp_messages.json 2.2.0, README regenerated).
|
ⓘ 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 QodoLearn compass offsets and yaw trim using a GPS-derived heading
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 #12160 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.
The delta of an earlier attitude fit stayed in magBias[] and MSP2_INAV_MAG_LEARN next to the failure flags.
|
Most of the deltas are #12159 (the GSF heading, +8.2 KB on MATEKF405) and #12142 (mag_learn), which this PR builds on. Its own share against #12159 is +3.0 to +3.3 KB of flash and +120 to +144 B of RAM, MATEKF405 at 80.34 % (table in the description). MATEKF722 builds neither the GSF heading nor this fit (512 KB of flash). |
|
Flight data from the four flights listed on #12142 and #12159 (fixed wing, The attitude fit ran in every flight once the GSF heading was usable. On this compass, whose field followed the motor
With MISFIT (the samples did not follow the attitude) it fell back to the sphere fit, which stopped at NOT_SPHERE. Where |
Builds on #12159 (GSF heading) and #12142 (mag_learn): the change of its own is the last commit.
#12142 fits the compass offsets to a sphere: it needs about 270 degrees of turning, can't tell a compass turned about the vertical, and refuses large steps (over 30 % of the field) because a sphere fit can be wrong in ways it can't see. With the heading of #12159 the readings can also be fitted against the attitude, which sees those.
The attitude fit:
MISFIT: wrong orientation, scale or soft iron); the field's direction within 15 degrees of the declination the AHRS applies (otherwiseDECLINATION_OFF: a compass turned about the vertical, which the residual doesn't show in flat turns); |B| within 30 % of 1024.How it decides, with the sphere fit of #12142 as the other candidate, compared in body axes:
FITS_DISAGREEand save nothing; the sphere fit alone works as in compass: learn the offsets in flight (mag_learn) #12142;CONFIRMEDand writes nothing, so a good calibration is not rewritten flight after flight.mag_yaw_trim(new, -300..300 decidegrees, default 0) turns the compass reading about the airplane's vertical afteralign_mag, positive clockwise: the alignment between a compass and the board can't be measured by hand better than a few degrees. Withmag_learnON the attitude fit refines it: the angle between the fitted field and magnetic north, at most 5 degrees a flight, nothing under 1 degree, never past the setting's range; over 15 degrees, or with no room left in the range, it is reported asDECLINATION_OFFinstead of trimmed. A pending trim is enough for a save. A compass calibration, or an orientation the calibration detects, sets it back to 0; after changingalign_magby hand it should be set to 0 too.Blackbox:
magBiasField(the fitted field),magBiasYawTrim, themag_yaw_trimheader line, and the flagsATTITUDE_FIT(2),MISFIT(3),DECLINATION_OFF(12),FITS_DISAGREE(13),CONFIRMED(14) inmagBiasFlags;magBiasSpreadis the misfit of the fit that decided, 0 when none did.MSP2_INAV_MAG_LEARNgets the field and the trim appended (20 bytes), so a configurator that reads the old 12 bytes still works;msp_messages.json2.2.0 and the README regenerated from it. The version inmsp_messages.jsonconflicts with #12156 and #12141, which raise it too: whichever is merged second takes the next one.Size against #12159:
USE_MAG_LEARNon 512 KB, and the trim lives with itcompassConfig_tgetsmagYawTrim(int16), inside the same#ifdef USE_MAG_LEARNasmagLearn, with a zero default: on targets withUSE_MAG_LEARNit sits at offset 26, the end of #12142's record (26 bytes on the PG reference target), never in its padding, so the PG version stays and the reference size is 28; on the others nothing changes.Tested:
CONFIRMED, nothing written; trim wrong by 8 degrees: -3 after one flight, -1.3 after two (the SITL's fake GPS has an error of its own of 1-3 degrees). These SITL runs were before the 10 % caps, the weights and the half-turn rule.DECLINATION_OFFand the sphere fit decided. Also before the caps, the weights and the half-turn rule.Configurator: iNavFlight/inav-configurator#2845. Blackbox Explorer: iNavFlight/blackbox-log-viewer#128.