Skip to main content

Overview

Basilisk is a software framework, not a standalone program. It gives you a library of spacecraft simulation building blocks — called modules — that you assemble into complete mission simulations. The framework is designed around four goals that often compete with each other:

Speed

All simulation logic executes in C/C++. A design goal is to simulate a full mission year of 6-DOF dynamics in under a day — a 365× speedup.

Reconfiguration

The Python interface lets you change task rates, module parameters, and output options dynamically without recompiling.

Scriptability

SWIG binds the C/C++ layer to Python, giving you full scripting control and access to NumPy and Matplotlib for inline analysis.

Hardware-in-the-loop

Clock-tracking modules synchronize the simulation to real time for HIL testing with flight hardware.

Language layers

Basilisk separates what runs fast from what is easy to configure:
┌─────────────────────────────────────────────────────┐
│  Python scripting layer                             │
│  - Build simulations, set parameters, analyze data  │
│  - numpy, matplotlib, pytest integration            │
└────────────────────┬────────────────────────────────┘
                     │ SWIG bindings
┌────────────────────▼────────────────────────────────┐
│  C/C++ simulation core                              │
│  - All module Update() and Reset() logic            │
│  - Message passing infrastructure                   │
│  - Time loop and task scheduling                    │
└─────────────────────────────────────────────────────┘
The Simplified Wrapper and Interface Generator (SWIG) is a cross-platform tool that exposes C/C++ interfaces to Python. A single compilation of the Basilisk source supports entirely different simulation configurations because parameters and wiring are set in Python at runtime.

SimBaseClass

Every Basilisk simulation starts with a SimBaseClass instance. This object is the root simulation container — it manages processes, tasks, and the simulation time loop.
from Basilisk.utilities import SimulationBaseClass
from Basilisk.utilities import macros

scSim = SimulationBaseClass.SimBaseClass()
SimBaseClass provides:
  • CreateNewProcess(name) — create a named process (task group)
  • CreateNewTask(name, updateRate) — create a task with a fixed update rate in nanoseconds
  • AddModelToTask(taskName, module) — register a module for execution
  • InitializeSimulation() — reset all modules and prepare the time loop
  • ConfigureStopTime(stopTime) — set the absolute simulation stop time in nanoseconds
  • ExecuteSimulation() — advance the simulation to the configured stop time

Processes and tasks

Module execution is organized through a two-level hierarchy: Process (task group) : A named container for related tasks. In a multi-satellite simulation, each satellite typically gets its own process. Processes execute in the order they are created, or by explicit priority. Task : A list of modules that all run at the same fixed update rate. A task belongs to exactly one process.
SimBaseClass
├── dynamicsProcess
│   ├── dynamicsTask  (rate: 5 s)
│   │   ├── spacecraftPlus
│   │   └── gravityEffector
│   └── sensorsTask   (rate: 10 s)
│       └── imuSensor
└── fswProcess
    └── fswTask       (rate: 10 s)
        ├── sunSafePoint
        └── mrpFeedback
The time unit in Basilisk is the nanosecond. A 64-bit unsigned integer at nanosecond resolution can represent 584 years of simulation time. The macros.sec2nano() helper converts seconds to nanoseconds.

Module packages

Basilisk modules are distributed across two top-level Python packages:
PackageImport pathContents
Simulation modulesBasilisk.simulationDynamics, environment, sensors, power, thermal, communication
FSW algorithm modulesBasilisk.fswAlgorithmsAttitude determination, guidance, control, orbit control
C-based modules are imported from Basilisk.fswAlgorithm (note: no trailing s) while C++ modules come from Basilisk.simulation. Both are used identically from Python — the distinction is a packaging convention from the module’s implementation language.

Module structure

Every Basilisk module — whether C, C++, or Python — follows the same interface:
  • ModelTag — a unique string name identifying the module instance
  • Reset(callTime) — called once at InitializeSimulation() to set module to its initial state
  • UpdateState(callTime) — called every task update tick to compute outputs from inputs
  • Input messages — named xxxInMsg, subscribe to another module’s output
  • Output messages — named xxxOutMsg, written during UpdateState()
# C module convention
mod = cModuleTemplate.cModuleTemplate()
mod.ModelTag = "myModule"

# C++ module convention (class name capitalized)
mod = cppModuleTemplate.CppModuleTemplate()
mod.ModelTag = "myModule"
Basilisk assigns each module a unique positive integer ID in the order modules are created.

Validation and verification

Every module ships with a _UnitTest folder containing pytest scripts that test the module in isolation. Integrated scenario tests in src/examples validate coupled behavior across modules. Dynamics modules include energy, momentum, and power conservation tests.

Build docs developers (and LLMs) love