Plane TAKEOFF mode can reuse prior level-off height on later takeoffs

I think I have found a state-reset issue in Plane TAKEOFF mode (Mode 13).

Environment

  • ArduPlane 4.7.0 stable (1511f271)
  • Conventional fixed-wing
  • TAKEOFF mode (ModeNum 13)
  • TKOFF_PLIM_SEC = 2
  • TKOFF_LVL_PITCH = 18°
  • TKOFF_ALT = 30 m

I also checked the relevant source in:

  • Plane 4.7.1
  • current master at de411b3818bd9ccabab90151c22f4bb3bb367353

The same reset behavior appears to remain present in all three.

What I observed

On the first TAKEOFF execution, Plane reached the level-off region and logged:

Takeoff level-off starting at 10m

At that point Plane stores:

auto_state.height_below_takeoff_to_level_off_cm

Nearby altitude evidence puts that stored reference at approximately 10.9 m.

After exiting TAKEOFF, landing and disarming, I later entered TAKEOFF mode again without rebooting.

The later takeoffs started with about 30 m remaining to the takeoff target.

The retained reference then appears to be reused by:

get_takeoff_pitch_min_cd()

which effectively gives:

18° × 30 m / 10.9 m ≈ 49.5°

The first fresh TECS records on the later takeoffs show:

Takeoff 2: pmin = pmax = 49.53°
Takeoff 3: pmin = pmax = 49.51°

and both later executions reach:

CTUN.NavPitch = 45°

The pitch controller also reaches its configured output limit in those later takeoffs.

Source behavior

The key difference I found is:

  • AUTO mission NAV_TAKEOFF explicitly clears auto_state.height_below_takeoff_to_level_off_cm in do_takeoff().
  • Mode 13 TAKEOFF does not appear to perform the equivalent reset.
  • ModeTakeoff::_enter() does not clear it.
  • TAKEOFF mode exit does not clear it.
  • Disarm/re-arm does not clear it.

takeoff_state.level_off_start_time_ms is separate and does get reset through other paths, but the retained height is in auto_state, so clearing takeoff_state does not affect it.

Expected behavior

A new independent TAKEOFF-mode execution should establish a new level-off reference, consistent with the per-item reset already performed by AUTO NAV_TAKEOFF.

Actual behavior

The previous nonzero level-off-height reference remains available to the next Mode-13 TAKEOFF execution and is reused in the takeoff-pitch-minimum calculation.

If the next takeoff begins with a substantially larger remaining altitude, the calculated minimum pitch can therefore be much higher than TKOFF_LVL_PITCH.

TECS interaction

The effect can also push the effective TECS limit above the configured TECS_PITCH_MAX.

In this case:

TKOFF_LVL_PITCH = 18°
TECS_PITCH_MAX  = 20°
PTCH_LIM_MAX_DEG = 45°

but the retained-state calculation produces about 49.5°.

TECS applies the TAKEOFF minimum and then ensures:

pmax >= pmin

so the effective pmax becomes about 49.5°.

Plane then reaches a 45° navigation-pitch demand.

Possible reset point

A minimal correction appears to be clearing:

plane.auto_state.height_below_takeoff_to_level_off_cm

once in:

ModeTakeoff::_enter()

That would give the field ownership per independent Mode-13 execution without clearing it repeatedly during one continuing takeoff.

AUTO NAV_TAKEOFF could retain its existing reset in do_takeoff().

A useful SITL regression test might be two sequential Mode-13 takeoffs without rebooting:

  1. first takeoff establishes the level-off reference;
  2. exit TAKEOFF;
  3. second takeoff starts with different remaining-height geometry;
  4. verify that the second execution establishes its own reference rather than reusing the first.

Scope of the finding

I am not claiming that the aircraft has insufficient elevator authority or that this necessarily creates a safety problem.

The log does show software/controller output saturation during the later high-demand takeoffs, but there is no actuator-position feedback proving physical surface position or aerodynamic authority.

Here is the log, I discovered this anomaly while working on an Auto-takeoff analyser.

I think your assessment is correct. Can you do a PR to fix it for us?

Done. thx.