Skip to content

Conversation

@sensei-hacker
Copy link
Member

@sensei-hacker sensei-hacker commented Jan 11, 2026

User description

Summary

Removes double application of RC deadband in multicopter altitude hold climb rate calculation.

Problem

The deadband was being applied twice:

  1. To the stick input () at line 140
  2. To the scaling limit () at line 148

This caused the actual climb rate to not match the configured value in the configurator.

Solution

Remove the second deadband application from . The limit value now uses the raw throttle range for proper scaling, while the deadband remains applied only to the stick input.

Testing

  • SITL build passes
  • Functional testing recommended with SITL runtime

Impact

Fixes user-reported issue where manual climb rate doesn't match configurator setting.

Fixes #10660


PR Type

Bug fix


Description

  • Removes double application of RC deadband in altitude hold climb rate calculation

  • Fixes climb rate not matching configurator settings

  • Applies deadband only to stick input, uses raw throttle range for scaling


Diagram Walkthrough

flowchart LR
  A["RC Throttle Input"] -->|applyDeadbandRescaled| B["rcThrottleAdjustment"]
  B -->|used for scaling| C["rcClimbRate Calculation"]
  D["Max/Min Throttle"] -->|raw range| E["limitValue"]
  E -->|denominator| C
Loading

File Walkthrough

Relevant files
Bug fix
navigation_multicopter.c
Fix double deadband application in climb rate calculation

src/main/navigation/navigation_multicopter.c

  • Removed duplicate applyDeadbandRescaled() call on limitValue
    calculation
  • Changed limitValue to use raw throttle range (difference from
    altHoldThrottleRCZero)
  • Updated comment to clarify deadband is only applied to
    rcThrottleAdjustment
  • Maintains single deadband application to stick input for proper climb
    rate scaling
+4/-3     

Remove double application of RC deadband in multicopter altitude hold
climb rate calculation. Previously, deadband was applied to both the
stick input (rcThrottleAdjustment) and the scaling limit (limitValue),
causing the actual climb rate to not match the configured value.

Now deadband is only applied once to the stick input, and the limit
value uses the raw throttle range for proper scaling.

Fixes iNavFlight#10660
@github-actions
Copy link

Branch Targeting Suggestion

You've targeted the master branch with this PR. Please consider if a version branch might be more appropriate:

  • maintenance-9.x - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 9.x versions. This will allow your PR to be included in the next 9.x release.

  • maintenance-10.x - If your change introduces compatibility requirements between firmware and configurator that would break 9.x compatibility. This is for PRs which will be included in INAV 10.x

If master is the correct target for this change, no action is needed.


This is an automated suggestion to help route contributions to the appropriate branch.

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 11, 2026

PR Compliance Guide 🔍

All compliance sections have been disabled in the configurations.

@sensei-hacker sensei-hacker added this to the 9.1 milestone Jan 11, 2026
@sensei-hacker sensei-hacker changed the base branch from master to maintenance-8.x.x January 11, 2026 22:29
Adds safety check for limitValue to prevent potential division by zero
in climb rate calculation. While the existing constraint on
altHoldThrottleRCZero should prevent this condition under normal
operation, this defensive check protects against:

- Configuration corruption or invalid EEPROM values
- Extremely narrow throttle range configurations
- Future code changes that might affect the constraint behavior

Addresses code review feedback on PR iNavFlight#11241.
@sensei-hacker sensei-hacker changed the base branch from maintenance-8.x.x to maintenance-9.x January 11, 2026 22:54
@Jetrell
Copy link

Jetrell commented Feb 11, 2026

@sensei-hacker I gave this a test today. And unfortunately I couldn't see or feel any difference with or without this change.

But there certainly is an issue with the way Copter Poshold responds to a throttle stick input command to reduce altitude, especially.
I can reduce the stick a little and wait for the altitude to lower, maybe at 0.2m/s.. Even though nav_mc_manual_climb_rate = 600... But if you lower the throttle anymore, it either doesn't move any faster, or often refuses to budge. Until I lower the throttle down too far. Then the motors shutoff and it drops.

@breadoven
Copy link
Collaborator

breadoven commented Feb 11, 2026

Having looked at this again I'm pretty sure the code should simply be as follows to work as required:

        if (rcThrottleAdjustment) {
            /* Set velocity proportional to stick movement
             * Scale from altHoldThrottleRCZero to maxthrottle or minthrottle to altHoldThrottleRCZero */

            int16_t rcClimbRate = rcThrottleAdjustment * navConfig()->mc.max_manual_climb_rate / 500;

rcThrottleAdjustment will be between -500 and 500 after the first deadband is applied so just divide by 500 to get scaled max_manual_climb_rate climb rate, no need for limits. I should have realised this when I changed this before to add the limits in https://github.com/iNavFlight/inav/pull/10664/changes. The second deadband was added in #10664 because that's what the original code was doing just without using the scale deadband function but it seems unnecessary anyway.

Things are also a bit confused given deadband in INAV seems to refer to half the actual deadband, e.g. if deadband is 1400 to 1600, INAV deadband would use 100 rather than the correct value of 200 (if I understand applyDeadbandRescaled correctly).

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.

Please, correct error in climb rate calculation.

3 participants