Note

This page was generated from a Jupyter notebook.

JSBSim Hello World

This notebook provides a minimal introduction to the JSBSim Python API.

JSBSim is a fully featured, open-source, multi-platform, flight dynamics model (FDM) written in C++ and exposed to Python via a Cython wrapper. The same FDM is used in FlightGear, OpenPilot, Paparazzi UAV, and many other simulators.

What we will do

  1. Import the jsbsim Python module.

  2. Create an FGFDMExec instance – the top-level JSBSim object.

  3. Load the bundled Cessna 172P aircraft model.

  4. Set initial conditions and trim the aircraft.

  5. Step the simulation and read back properties.

  6. Print a summary of the simulation state.

Install

pip install jsbsim

1. Import and version check

[1]:
# If running on Google Colab, install the required packages.

import sys

if 'google.colab' in sys.modules:
    print('Running on Google Colab \u2013 installing jsbsim \u2026')
    !pip install jsbsim
[2]:
import jsbsim

print(f"JSBSim version: {jsbsim.__version__}")
JSBSim version: 1.3.0

2. Create the Flight Dynamics Model executor

FGFDMExec is the main JSBSim class. Passing None as the root_dir argument makes it use the aircraft and engine data bundled with the Python wheel.

[3]:
fdm = jsbsim.FGFDMExec(None)   # None → use data bundled with the pip package
fdm.set_debug_level(0)         # Suppress verbose JSBSim console output

if fdm is not None:
    print("FDM created successfully")
else:
    print("Failed to create FDM")


     JSBSim Flight Dynamics Model v1.3.0 Apr  9 2026 10:00:08
            [JSBSim-ML v2.0]

JSBSim startup beginning ...

FDM created successfully

3. Load an aircraft model

The JSBSim wheel ships with many aircraft models. Here we use the c172p (Cessna 172P).

[4]:
aircraft = 'c172p'
result = fdm.load_model(aircraft)

print(f"load_model('{aircraft}') → {result}")
load_model('c172p') → True

4. Set initial conditions

JSBSim exposes all model state through a property tree. Initial-condition properties are prefixed with ic/.

[5]:
# Initial altitude above sea level [ft]
fdm['ic/h-sl-ft'] = 3000.0

# Initial calibrated airspeed [knots]
fdm['ic/vc-kts'] = 80.0

# Flight path angle [deg]  (0 = level flight)
fdm['ic/gamma-deg'] = 0.0

# Heading [deg]
fdm['ic/psi-true-deg'] = 45.0

# Apply the initial conditions
fdm.run_ic()

print("Initial conditions applied")
Initial conditions applied

5. Trim the aircraft

Trimming finds a steady-state flight condition where the net forces and moments acting on the aircraft are (approximately) zero. JSBSim provides a built-in full trim algorithm.

[6]:
# Start engines
fdm['propulsion/set-running'] = -1

# Request a full trim (blocks until convergence)
fdm['simulation/do_simple_trim'] = 1

print("Trim complete")
print(f"  Throttle        : {100.*fdm['fcs/throttle-cmd-norm[0]']:.3f} (perc.)")
print(f"  Elevator trim   : {100.*fdm['fcs/pitch-trim-cmd-norm']:.4f} (perc.)")
print(f"  Angle of attack : {fdm['aero/alpha-deg']:.2f} deg")
Trim complete
  Throttle        : 62.157 (perc.)
  Elevator trim   : 5.2799 (perc.)
  Angle of attack : 2.53 deg

6. Step the simulation and read properties

fdm.run() advances the simulation by one time step (fdm.get_delta_t() seconds, typically 1/120 s). Properties are read with dictionary-style access.

[7]:
dt = fdm.get_delta_t()
print(f"Time step Delta t = {dt:.6f} s  ({1/dt:.1f} Hz)")

# Run for 1 second
n_steps = int(1.0 / dt)
for _ in range(n_steps):
    fdm.run()

print("\nSimulation state after 1 second:")
print(f"  Simulation time : {fdm['simulation/sim-time-sec']:.3f} s")
print(f"  Altitude (MSL)  : {fdm['position/h-sl-ft']:.1f} ft")
print(f"  True airspeed   : {fdm['velocities/vt-fps']:.1f} fps")
print(f"  Pitch angle     : {fdm['attitude/theta-deg']:.2f} deg")
print(f"  Roll angle      : {fdm['attitude/phi-deg']:.2f} deg")
print(f"  Heading         : {fdm['attitude/psi-deg']:.1f} deg")
Time step Delta t = 0.008333 s  (120.0 Hz)

Simulation state after 1 second:
  Simulation time : 1.000 s
  Altitude (MSL)  : 3000.0 ft
  True airspeed   : 141.1 fps
  Pitch angle     : 2.53 deg
  Roll angle      : 0.06 deg
  Heading         : 45.0 deg

7. Explore the property tree

JSBSim exposes hundreds of properties. The query_property_catalog method searches by substring.

[8]:
# Find all velocity-related properties
catalog_str = fdm.query_property_catalog('velocities')
velocity_props = [p for p in catalog_str.split('\n') if p.strip()]

print(f"Found {len(velocity_props)} velocity properties (first 15):")
for p in velocity_props[:15]:
    name = p.strip().split(' ')[0]   # strip access flag suffix
    try:
        value = fdm[name]
        print(f"  {name:<45s} = {value:.4f}")
    except Exception:
        print(f"  {name:<45s} (unreadable)")
Found 40 velocity properties (first 15):
  velocities/h-dot-fps                          = 0.0013
  velocities/v-north-fps                        = 99.7897
  velocities/v-east-fps                         = 99.7803
  velocities/v-down-fps                         = -0.0013
  velocities/u-fps                              = 140.9793
  velocities/v-fps                              = -0.0000
  velocities/w-fps                              = 6.2395
  velocities/p-rad_sec                          = 0.0000
  velocities/q-rad_sec                          = 0.0000
  velocities/r-rad_sec                          = -0.0000
  velocities/pi-rad_sec                         = 0.0001
  velocities/qi-rad_sec                         = -0.0000
  velocities/ri-rad_sec                         = 0.0000
  velocities/eci-x-fps                          = -0.1255
  velocities/eci-y-fps                          = 1625.9213

Summary

In this notebook you learned how to:

  • Create an FGFDMExec instance.

  • Load an aircraft model bundled with the JSBSim Python wheel.

  • Set initial conditions and perform a trim.

  • Advance the simulation with fdm.run() and read properties.

  • Query the property tree.

Next: 02_jsbsim_flight_simulation.ipynb – a longer simulation with time-history plots.