Skip to content

BUG: Flight.potential_energy has the wrong sign (decreases with altitude) #1202

Description

@yu010101

Describe the bug

Flight.potential_energy becomes more negative as the rocket climbs. The implementation computes

standard_gravitational_parameter * total_mass * (1 / (self.z + self.env.earth_radius) - 1 / self.env.earth_radius)

which is negative for z > 0. The gravitational potential energy relative to sea level should be mu * m * (1 / R - 1 / (R + z)), which is positive and increases with z. Flight.total_energy inherits the sign error. The trajectory itself is not affected; only the potential_energy and total_energy outputs.

To Reproduce

Standard atmosphere, tabulated thrust, no data files. Between burn-out and apogee the mass is constant, so the change in potential energy should match m·g·Δz:

"""Minimal reproduction: Flight.potential_energy has the wrong sign (decreases as altitude increases).
Uses only the standard atmosphere and a tabulated thrust curve (no data files, no network)."""
import warnings; warnings.filterwarnings("ignore")
from rocketpy import Environment, SolidMotor, Rocket, Flight

env = Environment(latitude=32.990254, longitude=-106.974998, elevation=1400)
env.set_atmospheric_model(type="standard_atmosphere")
motor = SolidMotor(thrust_source=[[0, 0], [0.1, 1800], [1, 1700], [3, 1500], [3.8, 1400], [3.9, 0]],
                   dry_mass=1.815, dry_inertia=(0.125, 0.125, 0.002), nozzle_radius=0.033, grain_number=5,
                   grain_density=1815, grain_outer_radius=0.033, grain_initial_inner_radius=0.015,
                   grain_initial_height=0.12, grain_separation=0.005, grains_center_of_mass_position=0.397,
                   center_of_dry_mass_position=0.317, nozzle_position=0, throat_radius=0.011,
                   coordinate_system_orientation="nozzle_to_combustion_chamber")
rocket = Rocket(radius=0.0635, mass=14.426, inertia=(6.321, 6.321, 0.034), power_off_drag=0.5, power_on_drag=0.5,
                center_of_mass_without_motor=0, coordinate_system_orientation="tail_to_nose")
rocket.add_motor(motor, position=-1.255)
rocket.set_rail_buttons(0.0818, -0.618, 45)
rocket.add_nose(length=0.55829, kind="von karman", position=1.278)
rocket.add_trapezoidal_fins(n=4, root_chord=0.12, tip_chord=0.06, span=0.11, position=-1.04956)
flight = Flight(rocket=rocket, environment=env, rail_length=5.2, inclination=85, heading=0, terminate_on_apogee=True)

tb, ta = motor.burn_out_time, flight.apogee_time          # after burn-out the mass is constant
zb, za = flight.z(tb), flight.z(ta)
dpe = flight.potential_energy(ta) - flight.potential_energy(tb)
m = flight.rocket.total_mass(ta)
print(f"z: {zb:.1f} m -> {za:.1f} m (rising), constant mass {m:.3f} kg")
print(f"Delta potential energy reported: {dpe:+.1f} J")
print(f"m*g*dz (g=9.80665):              {m*9.80665*(za-zb):+.1f} J")
print("SIGN BUG" if dpe < 0 < za - zb else "ok")

Output on RocketPy 1.13.0:

z: 1981.8 m -> 4485.2 m (rising), constant mass 16.241 kg
Delta potential energy reported: -398754.6 J
m*g*dz (g=9.80665):              +398711.0 J
SIGN BUG

Expected behavior

With the two terms swapped, the same script gives +398754.6 J, within 0.01 % of m·g·Δz (the residual is consistent with g decreasing with altitude).

Screenshots

N/A

Additional context

  • Same behaviour on RocketPy 1.10.0 (Python 3.9) and 1.13.0 (Python 3.14). The formula is unchanged on develop (a50d07d, 2026-09-14).
  • Proposed fix in Flight.potential_energy: mu * total_mass * (1 / self.env.earth_radius - 1 / (self.z + self.env.earth_radius)). Happy to open a PR with a regression test, e.g. potential_energy(apogee) - potential_energy(burn_out) > 0.
  • I searched issues and PRs for "potential energy", "potential_energy", "total_energy" and "mechanical energy" and found no report of this.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions