Skip to content

Fix bytewise parameter write acknowledgements#14662

Open
ikalnytskyi wants to merge 1 commit into
mavlink:masterfrom
ikalnytskyi:bug/param-ack
Open

Fix bytewise parameter write acknowledgements#14662
ikalnytskyi wants to merge 1 commit into
mavlink:masterfrom
ikalnytskyi:bug/param-ack

Conversation

@ikalnytskyi

Copy link
Copy Markdown
Contributor

Description

When QGC writes a parameter, it waits for the vehicle to echo the new value in PARAM_VALUE. The acknowledgement is accepted only when both the value and the QVariant type match QGC's stored Fact value.

For 8- & 16-bit parameters, FactMetaData stores the value in a QVariant: Qt Int (32-bit) for signed values and 32-bit Qt UInt (32-bit) for unsigned values. This preserves the parameter's signedness in QGC's internal representation.

The _mavlinkParamUnionToVariant method passed uint8_t and uint16_t directly to QVariant. C++ selected QVariant's int constructor, so an unsigned PARAM_VALUE was decoded as signed Qt Int. The type check then rejected the otherwise valid acknowledgement and the write timed out. Decode narrow values into QGC's canonical Int or UInt representations.

The bug affects only UINT8 and UINT16 parameters; the other supported types coincidentally work. It flew below the radar because ArduPilot uses float-based parameter encoding, while PX4 does not expose UINT8 or UINT16 parameters for which the problem exhibits itself.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)
  • CI/Build changes
  • Other

Testing

  • Tested locally
  • Added/updated unit tests
  • Tested with simulator (SITL)
  • Tested with hardware

Platforms Tested

  • Linux
  • Windows
  • macOS
  • Android
  • iOS

Flight Stacks Tested

  • PX4
  • ArduPilot
  • Generic

Screenshots

Checklist

  • I have read the Contribution Guidelines
  • I have read the Code of Conduct
  • My code follows the project's coding standards
  • I have added tests that prove my fix/feature works
  • New and existing unit tests pass locally

Related Issues


By submitting this pull request, I confirm that my contribution is made under the terms of the project's dual license (Apache 2.0 and GPL v3).

Copilot AI review requested due to automatic review settings July 20, 2026 21:39
@ikalnytskyi
ikalnytskyi requested a review from HTRamsey as a code owner July 20, 2026 21:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes parameter write acknowledgements for bytewise MAVLink parameter types by decoding MAV_PARAM_TYPE_UINT8/UINT16 (and similarly INT8/INT16) into QGC’s canonical 32-bit QVariant integer representations, preventing valid PARAM_VALUE echoes from being rejected due to mismatched QVariant types.

Changes:

  • Fix _mavlinkParamUnionToVariant to cast narrow integer types to qint32/quint32 before wrapping in QVariant.
  • Add unit tests covering successful writes of UINT8 and UINT16 parameters.
  • Extend MockLink to load a minimal generic parameter set containing UINT8/UINT16 test parameters.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/FactSystem/ParameterManagerTest.h Adds new unit test slots and extends the helper signature to parameterize param name and autopilot type.
test/FactSystem/ParameterManagerTest.cc Implements UINT8/UINT16 write tests and updates the helper to support generic autopilot + integer step sizing.
src/FactSystem/ParameterManager.cc Fixes UINT8/UINT16 (and INT8/INT16) decoding to consistent 32-bit QVariant integer types.
src/Comms/MockLink/MockLink.cc Loads a new generic parameter file when MAV_AUTOPILOT_GENERIC is used.
src/Comms/MockLink/GenericMockLink.params Adds test parameters TEST_UINT8 and TEST_UINT16 with MAVLink types for coverage.
src/Comms/MockLink/CMakeLists.txt Registers GenericMockLink.params as a Qt resource for the mock link.

return true;
case MAV_PARAM_TYPE_UINT8:
outValue = QVariant(paramUnion.param_uint8);
outValue = QVariant(static_cast<quint32>(paramUnion.param_uint8));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

n.b. Without this cast, QVariant ends up storing an int, not a uint, while the fact system we compare this value to stores a uint. Due to the mismatch, QGC rejects write acknowledgement, retries and eventually shows the write failure.

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 31.69%. Comparing base (f29efd3) to head (941ac1c).
⚠️ Report is 162 commits behind head on master.

Files with missing lines Patch % Lines
src/Comms/MockLink/MockLink.cc 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #14662      +/-   ##
==========================================
+ Coverage   25.47%   31.69%   +6.21%     
==========================================
  Files         769      785      +16     
  Lines       65912    67046    +1134     
  Branches    30495    31042     +547     
==========================================
+ Hits        16788    21247    +4459     
+ Misses      37285    31399    -5886     
- Partials    11839    14400    +2561     
Flag Coverage Δ
unittests 31.69% <83.33%> (+6.21%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/FactSystem/ParameterManager.cc 41.36% <100.00%> (+4.56%) ⬆️
src/Comms/MockLink/MockLink.cc 57.13% <50.00%> (+6.25%) ⬆️

... and 455 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 52e1ce8...941ac1c. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

⚠️ Build results unavailable — artifact download from one or more platform workflows failed (likely artifact retention expiry or transient API error). The combined report cannot be generated for this run.

See the Build Results workflow run for details.

Copilot AI review requested due to automatic review settings July 21, 2026 08:59
When QGC writes a parameter, it waits for the vehicle to echo the new
value in PARAM_VALUE. The acknowledgement is accepted only when both the
value and the QVariant type match QGC's stored Fact value.

For 8- & 16-bit parameters, FactMetaData stores the value in a QVariant:
Qt Int (32-bit) for signed values and 32-bit Qt UInt (32-bit) for
unsigned values. This preserves the parameter's signedness in QGC's
internal representation.

The `_mavlinkParamUnionToVariant` method passed `uint8_t` and `uint16_t`
directly to QVariant. C++ selected QVariant's `int` constructor, so an
unsigned PARAM_VALUE was decoded as signed Qt Int. The type check then
rejected the otherwise valid acknowledgement and the write timed out.
Decode narrow values into QGC's canonical Int or UInt representations.

The bug affects only UINT8 and UINT16 parameters; the other supported
types coincidentally work. It flew below the radar because ArduPilot
uses float-based parameter encoding, while PX4 does not expose UINT8 or
UINT16 parameters for which the problem exhibits itself.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comment thread test/FactSystem/ParameterManagerTest.cc
Copilot AI review requested due to automatic review settings July 21, 2026 09:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comment on lines 397 to 404
} else {
paramFile.setFileName(":/FirmwarePlugin/APM/Copter.OfflineEditing.params");
}
} else if (_firmwareType == MAV_AUTOPILOT_GENERIC) {
paramFile.setFileName(":/MockLink/GenericMockLink.params");
} else {
paramFile.setFileName(":/MockLink/PX4MockLink.params");
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm... but there shouldn't be any expected parameters set for the Generic autopilot, should there?

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.

2 participants