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
Import the
jsbsimPython module.Create an
FGFDMExecinstance – the top-level JSBSim object.Load the bundled Cessna 172P aircraft model.
Set initial conditions and trim the aircraft.
Step the simulation and read back properties.
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
FGFDMExecinstance.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.