Skip to content

feat(fw_performance_model): scale vehicle weight by remaining fuel#27901

Open
mahima-yoga wants to merge 4 commits into
mainfrom
pr-fuel-level-tecs-scale
Open

feat(fw_performance_model): scale vehicle weight by remaining fuel#27901
mahima-yoga wants to merge 4 commits into
mainfrom
pr-fuel-level-tecs-scale

Conversation

@mahima-yoga

@mahima-yoga mahima-yoga commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Thought I would push something to get the discussion going:

Solved Problem

The FW performance model scales trim throttle, min/stall airspeed, and climb/sink rates from the static WEIGHT_GROSS parameter. For combustion vehicles a large share of the takeoff weight is fuel, so these limits become increasingly wrong
as fuel burns off during flight - which leads to inefficient flight.

Solution

Add an optional WEIGHT_FUEL parameter (mass of a full fuel load). When set, the weight used by the performance model is reduced by the burned fuel mass derived from fuel_tank_status (remaining fuel preferred, then percentage, then consumed fuel), low-pass filtered to reject sloshing.

Also adds weight_ratio to TecsStatus (appended field, uLog-compatible) for log analysis.

Test coverage

  • Needs to be tested.

  • Unit tests for the weight-ratio math and the fuel-fraction fallback chain
    (make tests TESTFILTER=PerformanceModel)

Some points / limitations:

  1. Currently only supports a single fuel tank.
  2. Filter parameters haven't been tested / verified.

Add a WEIGHT_FUEL parameter for the mass of a full fuel load. When set,
the weight used for trim throttle, min/stall airspeed, and climb/sink
rate scaling is reduced by the burned fuel mass derived from
fuel_tank_status (filtered to reject sloshing). Disabled by default.
@github-actions github-actions Bot added kind:feature Request or change that adds new functionality. vehicle:fixed-wing Fixed-wing-specific behavior. kind:test Adds or improves tests. scope:control Rate, attitude, position, allocation, or actuator control. scope:uorb uORB messages, generated interfaces, or message translation. scope:parameters Parameter definitions, metadata, migration, or defaults. scope:testing Unit, integration, fuzzing, or test data. labels Jul 14, 2026
@mahima-yoga
mahima-yoga requested review from mbjd and sfuhrer July 14, 2026 17:03
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

🔎 FLASH Analysis

px4_fmu-v5x [Total VM Diff: 920 byte (0.05 %)]
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +920  +0.0%    +920    .text
    [NEW]    +260  [NEW]    +260    FwLateralLongitudinalControl::updateFuelState()
    [NEW]    +200  [NEW]    +200    PerformanceModel::getFuelFractionRemaining()
    +0.1%    +116  +0.1%    +116    g_cromfs_image
    +3.6%     +64  +3.6%     +64    FwLateralLongitudinalControl::FwLateralLongitudinalControl()
    [NEW]     +64  [NEW]     +64    PerformanceModel::setFuelFractionRemaining()
     +62%     +52   +62%     +52    PerformanceModel::getWeightRatio()
     +24%     +48   +24%     +48    FwLateralLongitudinalControl::tecs_status_publish()
    +8.0%     +28  +8.0%     +28    PerformanceModel::PerformanceModel()
    +0.0%     +16  +0.0%     +16    [section .text]
    +4.7%     +12  +4.7%     +12    FwLateralLongitudinalControl::getCorrectedLateralAccelSetpoint()
    +6.3%     +12  +6.3%     +12    PerformanceModel::updateParamsImpl()
    +0.1%     +12  +0.1%     +12    uORB::compressed_fields
    +0.6%      +8  +0.6%      +8    AirspeedModule::AirspeedModule()
    +0.5%      +8  +0.5%      +8    FwLateralLongitudinalControl::Run()
    +3.1%      +8  +3.1%      +8    FwLateralLongitudinalControl::~FwLateralLongitudinalControl()
    +0.1%      +8  +0.1%      +8    px4::parameters
    +4.8%      +4  +4.8%      +4    FlightTask
    +1.2%      +4  +1.2%      +4    FwLateralLongitudinalControl::parameters_update()
   -50.0%      +4 -50.0%      +4    [1 Others]
    -0.4%      -4  -0.4%      -4    VtolAttitudeControl::Run()
    -0.3%      -4  -0.3%      -4    VtolAttitudeControl::VtolAttitudeControl()
  +0.0%    +219  [ = ]       0    .debug_abbrev
  +0.0%     +24  [ = ]       0    .debug_aranges
  +0.0%    +132  [ = ]       0    .debug_frame
  +0.0% +5.53Ki  [ = ]       0    .debug_info
  +0.0% +1.14Ki  [ = ]       0    .debug_line
   -50.0%      -1  [ = ]       0    [Unmapped]
    +0.0% +1.14Ki  [ = ]       0    [section .debug_line]
  +0.0% +1.68Ki  [ = ]       0    .debug_loclists
  +0.0%    +209  [ = ]       0    .debug_rnglists
  +0.0% +1.31Ki  [ = ]       0    .debug_str
  +0.8%      +2  [ = ]       0    .shstrtab
  +0.0%    +174  [ = ]       0    .strtab
    [NEW]     +53  [ = ]       0    FwLateralLongitudinalControl::updateFuelState()
    [NEW]     +71  [ = ]       0    PerformanceModel::getFuelFractionRemaining()
    [NEW]     +50  [ = ]       0    PerformanceModel::setFuelFractionRemaining()
   -32.7%     -16  [ = ]       0    __nxsched_add_prioritized_veneer
     +67%     +16  [ = ]       0    __stm32_dmastart_veneer
  +0.0%    +144  [ = ]       0    .symtab
    [NEW]     +48  [ = ]       0    FwLateralLongitudinalControl::updateFuelState()
    [NEW]     +48  [ = ]       0    PerformanceModel::getFuelFractionRemaining()
    [NEW]     +48  [ = ]       0    PerformanceModel::setFuelFractionRemaining()
   -40.0%     -32  [ = ]       0    __nxsched_add_prioritized_veneer
     +67%     +32  [ = ]       0    __stm32_dmastart_veneer
 -10.3%    -920  [ = ]       0    [Unmapped]
  +0.0% +10.6Ki  +0.0%    +920    TOTAL

px4_fmu-v6x [Total VM Diff: 984 byte (0.05 %)]
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +984  +0.1%    +984    .text
    [NEW]    +260  [NEW]    +260    FwLateralLongitudinalControl::updateFuelState()
    [NEW]    +200  [NEW]    +200    PerformanceModel::getFuelFractionRemaining()
    +0.1%    +132  +0.1%    +132    g_cromfs_image
    +3.6%     +64  +3.6%     +64    FwLateralLongitudinalControl::FwLateralLongitudinalControl()
    [NEW]     +64  [NEW]     +64    PerformanceModel::setFuelFractionRemaining()
     +62%     +52   +62%     +52    PerformanceModel::getWeightRatio()
   -98.9%     +52 -98.9%     +52    [19 Others]
     +24%     +48   +24%     +48    FwLateralLongitudinalControl::tecs_status_publish()
    +8.0%     +28  +8.0%     +28    PerformanceModel::PerformanceModel()
    +4.7%     +12  +4.7%     +12    FwLateralLongitudinalControl::getCorrectedLateralAccelSetpoint()
    +6.3%     +12  +6.3%     +12    PerformanceModel::updateParamsImpl()
    +0.1%     +12  +0.1%     +12    uORB::compressed_fields
    +0.6%      +8  +0.6%      +8    AirspeedModule::AirspeedModule()
    +0.5%      +8  +0.5%      +8    FwLateralLongitudinalControl::Run()
    +3.1%      +8  +3.1%      +8    FwLateralLongitudinalControl::~FwLateralLongitudinalControl()
    +0.0%      +8  +0.0%      +8    [section .text]
    +0.1%      +8  +0.1%      +8    px4::parameters
     +33%      +4   +33%      +4    ConstLayer::contains()
     +17%      +4   +17%      +4    ConstLayer::get()
    +1.2%      +4  +1.2%      +4    FwLateralLongitudinalControl::parameters_update()
    -4.5%      -4  -4.5%      -4    FlightTask
  +0.0%    +219  [ = ]       0    .debug_abbrev
  +0.0%     +24  [ = ]       0    .debug_aranges
  +0.0%    +132  [ = ]       0    .debug_frame
  +0.0% +5.48Ki  [ = ]       0    .debug_info
  +0.0% +1.17Ki  [ = ]       0    .debug_line
   -14.3%      -1  [ = ]       0    [Unmapped]
    +0.0% +1.17Ki  [ = ]       0    [section .debug_line]
  +0.0% +1.57Ki  [ = ]       0    .debug_loclists
  +0.0%    +214  [ = ]       0    .debug_rnglists
    [NEW]      +1  [ = ]       0    [Unmapped]
    +0.0%    +213  [ = ]       0    [section .debug_rnglists]
  +0.0% +1.31Ki  [ = ]       0    .debug_str
  -0.8%      -2  [ = ]       0    .shstrtab
  +0.0%    +174  [ = ]       0    .strtab
    [NEW]     +53  [ = ]       0    FwLateralLongitudinalControl::updateFuelState()
    [NEW]     +71  [ = ]       0    PerformanceModel::getFuelFractionRemaining()
    [NEW]     +50  [ = ]       0    PerformanceModel::setFuelFractionRemaining()
  +0.0%    +144  [ = ]       0    .symtab
   -50.0%     -16  [ = ]       0    ConstLayer::contains()
     +50%     +16  [ = ]       0    ConstLayer::store()
   -20.0%     -16  [ = ]       0    DynamicSparseLayer::DynamicSparseLayer()
    [NEW]     +48  [ = ]       0    FwLateralLongitudinalControl::updateFuelState()
    [NEW]     +48  [ = ]       0    PerformanceModel::getFuelFractionRemaining()
    [NEW]     +48  [ = ]       0    PerformanceModel::setFuelFractionRemaining()
    +0.4%     +48  [ = ]       0    [section .symtab]
   -50.0%     -16  [ = ]       0    param_for_index
   -50.0%     -16  [ = ]       0    param_get_index
 -16.7%    -984  [ = ]       0    [Unmapped]
  +0.0% +10.4Ki  +0.0%    +984    TOTAL

Updated: 2026-07-15T12:18:04

@mbjd mbjd 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.

Cool stuff! Looks nice and correct, some minor points below 👇

// only a single fuel tank is supported: use the first reported tank id and ignore all others
if (_fuel_tank_id < 0) {
_fuel_tank_id = fuel_tank_status.fuel_tank_id;
}

@mbjd mbjd Jul 15, 2026

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.

could we not support multiple instances very easily too?

  • Change weight param to fuel density or total fuel mass when all tanks are full (assume the same fuel is in all tanks)
  • Just below, loop over all tanks, accumulate the consumed fuel weight, and convert that back to the fraction of total tank volume
    • or just always use weight

maybe multiple tanks are outlandish enough to not worry as well though

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.

I shall give this a think

Comment thread src/modules/fw_lateral_longitudinal_control/FwLateralLongitudinalControl.cpp Outdated
Comment thread src/lib/fw_performance_model/PerformanceModel.cpp Outdated
Comment thread src/lib/fw_performance_model/performance_model_params.yaml Outdated
@github-actions

Copy link
Copy Markdown
Contributor

💡 Commit messages could be improved

Not blocking, but these commit messages could use some cleanup.

Commit Message Suggestion
1063b60e6f fix: don't set max climb/sink rates based on fuel fraction Missing conventional commit format (e.g. "feat(ekf2): add something")
1c24ac533a chore: shorten param description Missing conventional commit format (e.g. "feat(ekf2): add something")
c49a08d329 chore: move _fuel_fraction_remaining constraint Missing conventional commit format (e.g. "feat(ekf2): add something")

See the commit message convention for details.


This comment will be automatically removed once the issues are resolved.

@hamishwillee hamishwillee 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.

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

Labels

kind:feature Request or change that adds new functionality. kind:test Adds or improves tests. scope:control Rate, attitude, position, allocation, or actuator control. scope:parameters Parameter definitions, metadata, migration, or defaults. scope:testing Unit, integration, fuzzing, or test data. scope:uorb uORB messages, generated interfaces, or message translation. vehicle:fixed-wing Fixed-wing-specific behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants