Skip to content

AP_Compass: report specific failure reason when fit rejected#32757

Open
christianpetri wants to merge 1 commit into
ArduPilot:masterfrom
christianpetri:compass-cal-early-abort
Open

AP_Compass: report specific failure reason when fit rejected#32757
christianpetri wants to merge 1 commit into
ArduPilot:masterfrom
christianpetri:compass-cal-early-abort

Conversation

@christianpetri
Copy link
Copy Markdown

@christianpetri christianpetri commented Apr 13, 2026

Summary

Extend the CompassCalibrator::Status enum with three new terminal failure values (BAD_OFFSETS=8, BAD_DIAG_SCALING=9, BAD_FITNESS=10) and refactor fit_acceptable() to set the appropriate specific status instead of falling back to the generic FAILED.

Classification & Testing (check all that apply and add your own)

  • Checked by a human programmer
  • Automated test(s) verify changes (e.g. unit test, autotest)
  • Tested manually, description below (e.g. SITL)

Description

Previously fit_acceptable() returned a silent false — the GCS and user had no way to know why calibration was rejected. This PR maps each rejection condition to a specific Status value that is transmitted in the MAG_CAL_REPORT.cal_status field.

New Status enum values (extend MAG_CAL_STATUS MAVLink enum):

Value Name Condition
8 BAD_OFFSETS Any offset component ≥ COMPASS_OFFS_MAX
9 BAD_DIAG_SCALING Diagonal or off-diagonal scaling out of range
10 BAD_FITNESS _fitness > sq(_tolerance)

BAD_RADIUS (7) was already present. All four conditions were previously collapsed into FAILED (5).

Behaviour changes:

  • fit_acceptable() loses const (it now calls set_status()).
  • set_status(FAILED) is guarded against overwriting any of the five specific BAD_* statuses (previously only BAD_ORIENTATION and BAD_RADIUS were protected).
  • update_cal_status(), failed(), is_calibrating(), and send_cal_report() all handle the three new cases identically to BAD_RADIUS.
  • No GCS_SEND_TEXT calls added; flash cost +48 bytes on CubeOrange plane (measured via Tools/scripts/size_compare_branches.py).

Note: The new integer values (8/9/10) are transmitted immediately. GCS will display the raw number until a matching MAG_CAL_STATUS entry is added in the upstream mavlink/mavlink XML and a pymavlink bump lands in ArduPilot. The autotest uses getattr(mavutil.mavlink, 'MAG_CAL_BAD_FITNESS', 10) fallbacks pending that bump.

Related

Testing

Builds clean on SITL and CubeOrange (./waf configure --board CubeOrange && ./waf plane). Flash delta vs master: +48 bytes (measured on CubeOrange plane via official ArduPilot size_compare_branches.py tool).

SITL autotest SITLCompassCalibration passes:

Tools/autotest/autotest.py test.Copter.SITLCompassCalibration

Two new subtests added:

  1. Tight-fit test (COMPASS_CAL_FIT=0.001) — all compasses report MAG_CAL_BAD_FITNESS (10) instead of MAG_CAL_FAILED (5).
  2. Selective-failure test (SIM_MAG1_OFS_X/Y/Z=2000) — compass 0 reports MAG_CAL_BAD_OFFSETS (8); remaining compasses still succeed.

This contribution was AI-assisted (GitHub Copilot).

@christianpetri

This comment was marked as outdated.

@IamPete1
Copy link
Copy Markdown
Member

I think 950 is too low, that is within the range of offsets that we might see in normal operation. I think we might be better off to try and improve the reporting at the end of a calibration attempt rather than guessing at the beginning.

@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from f4e053b to a428227 Compare April 13, 2026 23:03
@christianpetri

This comment was marked as outdated.

@rmackay9
Copy link
Copy Markdown
Contributor

Hi @christianpetri,

Thanks for this. One small thing is we don't accept merge commits so could you rebase on master to remove it?

@christianpetri christianpetri force-pushed the compass-cal-early-abort branch 2 times, most recently from a6d793b to b0f7dc6 Compare April 14, 2026 11:15
Copy link
Copy Markdown
Contributor

@peterbarker peterbarker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create an autotest

  • want other compasses to keep calibrating if one of them gets a long field
  • we have lots of autotests already doing calibration, steal code from there
  • does this make calibration faster with a badly-affected compass?

Generally in favour of this at DevCallEU

What's the flash cost?

@christianpetri

This comment was marked as outdated.

@IamPete1
Copy link
Copy Markdown
Member

Not keen on the short circuit stuff, but I like the improved reporting at the end of the calibration. To get the most out of this we might need some GCS changes, in mission planner you can't see messages on the compass calibration page, you would have to go and look manualy.

@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 560b8e1 to 09774b4 Compare April 19, 2026 20:26
@christianpetri
Copy link
Copy Markdown
Author

christianpetri commented Apr 19, 2026

Dropped the early-abort in pull_sample() as requested. Kept and improved the fit_acceptable() diagnostics: each failure condition (fitness NaN, radius out of range, offsets too large, diagonal/offdiagonal out of range, fitness over tolerance) now emits its own GCS message with the actual values, so all failures are visible in a single calibration attempt rather than just the first hit. Removed const from fit_acceptable() since GCS_SEND_TEXT is a side effect. This is consistent with the pre-existing messages already in calculate_orientation() and fix_radius().

@christianpetri
Copy link
Copy Markdown
Author

christianpetri commented Apr 20, 2026

SITL Test Plan

Manual SITL verification for the Mag(N) bad ... STATUSTEXT capture in the compass calibration dialog.

  • Mission Planner now shows the Mag(N) bad fit diagnostics directly in the compass calibration panel, so the failure reason is visible immediately without leaving the page. image

  • Close-up of the Onboard Mag Calibration box showing a specific rejection reason (offsets over limit) alongside the live calibration progress. image

Related PRs

Setup

sim_vehicle.py -v ArduCopter -f calibration --console --map

Connect Mission Planner via TCP 127.0.0.1:5762, navigate to Initial Setup → Mandatory Hardware → Compass.

Reset between tests

param set COMPASS_CAL_FIT 16
param set SIM_MAG1_OFS_X 0 ; param set SIM_MAG1_OFS_Y 0 ; param set SIM_MAG1_OFS_Z 0
param set SIM_MAG2_OFS_X 0 ; param set SIM_MAG2_OFS_Y 0 ; param set SIM_MAG2_OFS_Z 0
param set SIM_MAG3_OFS_X 0 ; param set SIM_MAG3_OFS_Y 0 ; param set SIM_MAG3_OFS_Z 0
sitl_stop ; sitl_attitude 0 0 0

Tests

# Scenario Setup Action Expected
1 Success baseline (defaults) Start → sitl_magcal → Accept Progress/report lines, no bad lines
2 Bad fit COMPASS_CAL_FIT 0.001 Start → sitl_magcal Mag(N) bad fit: fitness X tolerance Y per compass
3 Bad offset (early abort) SIM_MAG1_OFS_X/Y/Z 2000 Start → sitl_magcal Mag(0) bad fit: ofs (2000,2000,2000)>=1800
4 Cancel/restart (defaults) Start → Cancel mid-run → Start Cancel/restart of calibration via MP — diagnostics state resets cleanly (verified with #3706)

Pass criteria

  • Success path shows no bad lines.
  • Failure path shows Mag(N) bad ... lines, line-separated, latest-per-compass.
  • Restart is clean after Cancel.
  • Non-compass STATUSTEXT still flows to HUD/messages.
  • No UI freeze or crash.

@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 09774b4 to 4fbb08d Compare April 20, 2026 01:01
@christianpetri

This comment was marked as outdated.

@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 4fbb08d to 774fc4c Compare April 20, 2026 01:50
@christianpetri christianpetri changed the title AP_Compass: early abort calibration on extreme magnetic field AP_Compass: report specific failure reason when fit rejected Apr 20, 2026
@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 774fc4c to 88799cf Compare April 20, 2026 22:28
Copy link
Copy Markdown
Member

@IamPete1 IamPete1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this! And Thanks for doing the Mission Planner fix too!

Comment thread libraries/AP_Compass/CompassCalibrator.cpp Outdated
Comment thread libraries/AP_Compass/CompassCalibrator.cpp Outdated
Comment thread libraries/AP_Compass/CompassCalibrator.cpp Outdated
Comment thread libraries/AP_Compass/CompassCalibrator.cpp Outdated
Comment thread libraries/AP_Compass/CompassCalibrator.cpp
@peterbarker
Copy link
Copy Markdown
Contributor

After discussion at DevCall:

  • too many bytes for a setup routine. We can't really afford 450 bytes - we don't have many spare on the small 1MB boards
  • most people don't know what any of these numbers mean
  • thsoe that do know can get the same information out of dataflash logs post-cal-attempt

We think the way forward is to fix the ground control stations to more prominiently display the calibration error code and then to augment the enumeration to include more error codes.

Not to say that this isn't actually a nice UI improvement, it's just we can't jsutify spending the resources on it

@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 2b28b3a to cbfe725 Compare May 6, 2026 01:51
@christianpetri
Copy link
Copy Markdown
Author

christianpetri commented May 6, 2026

Switched to the enum-only approach you described — no GCS_SEND_TEXT, no new strings, +20 bytes on CubeOrange. Three new Status values (BAD_OFFSETS=8, BAD_DIAG=9, BAD_FITNESS=10) are set inside fit_acceptable() and transmitted in MAG_CAL_REPORT.cal_status. GCS will show named labels once the upstream mavlink/mavlink entries land and pymavlink is bumped. Full description in the PR body.

@christianpetri
Copy link
Copy Markdown
Author

Upstream mavlink/mavlink PR opened for the 3 new enum entries: mavlink/mavlink#2478

Once that merges and pymavlink is bumped, the getattr() fallbacks in the autotest can be replaced with direct symbol references.

@christianpetri christianpetri marked this pull request as draft May 6, 2026 05:01
@christianpetri christianpetri force-pushed the compass-cal-early-abort branch 2 times, most recently from 7ace6e0 to f7e0a2e Compare May 11, 2026 20:12
@christianpetri
Copy link
Copy Markdown
Author

Rebased and updated based on review feedback. Latest push includes one follow-up cleanup commit:

  • comment clarifications around retry timing and autoreboot safety rationale
  • removal of two introduced trailing-whitespace lines
  • explicit default initialization for _retry_pending (false)
  • no behavioral change intended from this follow-up commit

Validation on this branch:

  • SITL compass-cal chain manual test: all 4 scenarios pass
  • autotest additions remain in place for:
    • BAD_FITNESS with tight COMPASS_CAL_FIT
    • selective failure where one compass reports BAD_OFFSETS and others continue/succeed
  • local build sanity check passed

Requesting re-review. If anything is still blocking, I can address it quickly.

@christianpetri
Copy link
Copy Markdown
Author

christianpetri commented May 11, 2026

Follow-up question for maintainers on intent:

For the latest cleanup commit, I clarified comments around two behavior points:

  • retry timing visibility (_retry_pending defers transition so BAD_* is observable for one GCS poll cycle)
  • autoreboot safety rationale (do not auto-reboot if any compass ends in BAD_*)

Could you please confirm this is the intended handling?

If preferred, I can adjust to a different policy/wording before merge (for example: keep behavior but simplify wording, or adjust reboot policy expectations).

@christianpetri
Copy link
Copy Markdown
Author

christianpetri commented May 11, 2026

Size re-check on latest branch head using ArduPilot size comparison script:

  • python3 Tools/scripts/size_compare_branches.py --master-branch origin/master --branch compass-cal-early-abort --vehicle plane --board CubeOrange --hide-unchanged
  • Result:

    Board,plane
    CubeOrange,48

So current delta is +48 bytes for CubeOrange plane versus merge-base/origin master.

@christianpetri christianpetri marked this pull request as ready for review May 11, 2026 23:37
@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 553381f to 15aa6c5 Compare May 11, 2026 23:37
christianpetri added a commit to christianpetri/mavlink that referenced this pull request May 11, 2026
Add three new failure reason enum values (8/9/10) to MAG_CAL_STATUS,
and add descriptions to existing entries 6 and 7 for consistency.

Implemented in ArduPilot firmware: ArduPilot/ardupilot#32757
christianpetri added a commit to christianpetri/mavlink that referenced this pull request May 14, 2026
Add three new failure reason enum values (8/9/10) to MAG_CAL_STATUS,
and add descriptions to existing entries 6 and 7 for consistency.

Implemented in ArduPilot firmware: ArduPilot/ardupilot#32757
@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 15aa6c5 to ff38025 Compare May 14, 2026 18:22
hamishwillee pushed a commit to christianpetri/mavlink that referenced this pull request May 21, 2026
Add three new failure reason enum values (8/9/10) to MAG_CAL_STATUS,
and add descriptions to existing entries 6 and 7 for consistency.

Implemented in ArduPilot firmware: ArduPilot/ardupilot#32757
christianpetri added a commit to christianpetri/mavlink that referenced this pull request May 22, 2026
…AL_STATUS

Add three new failure reason enum values (8/9/10) to MAG_CAL_STATUS, and add descriptions to existing entries 6 and 7 for consistency.\n\nImplemented in ArduPilot firmware: ArduPilot/ardupilot#32757
christianpetri added a commit to christianpetri/mavlink that referenced this pull request May 22, 2026
…AL_STATUS

Add three new failure reason enum values (8/9/10) to MAG_CAL_STATUS, and add descriptions to existing entries 6 and 7 for consistency.

Implemented in ArduPilot firmware: ArduPilot/ardupilot#32757
@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 4ce9557 to 399743b Compare May 22, 2026 01:46
christianpetri added a commit to christianpetri/mavlink that referenced this pull request May 28, 2026
…AL_STATUS

Add three new failure reason enum values (8/9/10) to MAG_CAL_STATUS, and add descriptions to existing entries 6 and 7 for consistency.

Implemented in ArduPilot firmware: ArduPilot/ardupilot#32757
@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from 9d73abb to ddea6dc Compare May 28, 2026 12:07
@christianpetri christianpetri force-pushed the compass-cal-early-abort branch from ddea6dc to 15ec2b8 Compare May 28, 2026 12:11
@christianpetri
Copy link
Copy Markdown
Author

Aligned the AP_Compass MAG_CAL failure status naming with mavlink/mavlink#2478 (FAILED_* names), including compatibility fallbacks in autotest until pymavlink catches up.

@christianpetri
Copy link
Copy Markdown
Author

christianpetri commented May 28, 2026

Hi @peterbarker, quick status update on your requested changes:

Could you please re-review and let me know if anything is still blocking from your side?

@rmackay9
Copy link
Copy Markdown
Contributor

Hi @christianpetri,

I've also added this to the weekly dev call so it will be reviewed then if not before, txs!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants