Building a High-Fidelity 6-DoF Satellite Simulation with Python
- Aman Kumar Singh
- Apr 26
- 4 min read

Have you ever wondered how satellites maintain their orientation in space or how engineers simulate their complex dynamics? In this tutorial, we’ll create a high-fidelity 6 Degrees of Freedom (6-DoF) satellite simulation in Python. We will use Quaternion representation for the attitude and try aligning the satellite with a given reference attitude.
We’ll model realistic orbital mechanics and environmental effects (gravity gradient, drag, solar pressure) and implement an attitude controller, all while visualizing the satellite’s motion in 3D using an STL file.
By the end, you’ll have a fully functional simulation that:
Models a satellite in a 400 km circular orbit.
Accounts for environmental torques and forces.
Uses a PD controller to keep the satellite in a desired orientation.
Visualizes the satellite’s motion in real-time with VTK.
Let’s get started! 🛰️
Prerequisites
Before we dive in, make sure you have the following installed:
Python 3.x
NumPy: For numerical computations - pip3 install numpy
SciPy: For ODE integration - pip3 install scipy
VTK: For 3D visualization - pip3 install vtk
numpy-stl: To load STL files - pip3 install numpy-stl
Matplotlib: Optional for additional plotting - pip3 install matplotlib
You’ll also need an STL file of a satellite (a 3D model). You can find download it from here.
Apart from this, I assume you are well-versed in basic orbital mechanics, dynamics and controls. If not, you can find a lot of NPTEL videos on it.
Linux is always recommended for aerospace application purposes. I have implemented it on Linux, but I assume it will also work on Windows. Let me know if you face any problems.
Step 1: Setting Up the Environment
First, let’s define some physical constants and import our required libraries as mentioned above
These values represent Earth’s properties and space environment parameters. For example, MU is the gravitational parameter used in orbital mechanics and RHO_0 models atmospheric density at 400 km altitude.
Step 2: Defining the Satellite
Next, let’s create a Satellite class to represent our spacecraft. It’ll hold physical properties like mass and inertia and define its initial state. We also store the 3D model of the satellite (.stl) for visualization. We also define the satellite's drag and reflectivity coefficient (c_d and c_r, respectively) to calculate drag forces and solar pressure on the satellite.
Inertia Tensor: A diagonal matrix [100, 80, 60] represents the satellite’s mass distribution. You can tweak this based on your satellite’s design. Either modify the self.inertia or pass inertia as the parameter while declaring an object of the satellite.
Initial State: Places the satellite in a circular orbit at 400 km, with a small initial angular velocity (omega0) to test the controller. You can modify the input parameter of initial attitude or angular velocity according to your requirements.
Step 3: Modeling the Space Environment
The Environment class handles forces and torques acting on the satellite, like gravity, atmospheric drag, and solar pressure.
The use of each function is given below
Gravity: Here, we use the two-body problem equation.
Gravity Gradient: A torque that arises due to Earth’s gravitational field varying across the satellite.
Using first-order gravity gradient equation Drag: Models atmospheric effects (minimal at 400 km but included for realism, using standard drag model)
Solar Pressure: Simplified with a constant sun direction and basic shadowing. (Using standard solar radiation pressure model)
Step 4: Adding an Attitude PD Controller
![A standard PD Controller [Ref: Electronics Coach]](https://static.wixstatic.com/media/3254fe_a9d949dfb7b04f4b922b0eff843ba8b5~mv2.png/v1/fill/w_600,h_236,al_c,q_85,enc_avif,quality_auto/3254fe_a9d949dfb7b04f4b922b0eff843ba8b5~mv2.png)
To keep the satellite in a specific attitude, we implement a PD (Proportional-Derivative) controller in the Controller class. We can use a very complex controller here, like model-predictive-control or LQR control, but for the sake of simplicity, we will use a standard PD controller.
Note: You can set up reference attitude by modifying q_desired in quaternion. If you're unfamiliar with it, watch some lectures on Quaternions on NPTEL. A few videos that I recommend are
3 Blue 1 Brown
By Zachary Manchester w.r.t. Optimal Control
Step 5: Simulating the Dynamics
The Dynamics class ties everything together, integrating the 6-DoF equations with SciPy’s solve_ivp. Here, we use the famous Runge-Kutta integrator to integrate the dynamics with time. This 6-DoF model employs quaternion-based attitude dynamics, for a singularity-free representation of the satellite’s orientation.
The primary torque considered here is the gravity gradient torque, which arises from Earth’s varying gravitational pull across the satellite’s body. To keep things straightforward, we assume the satellite’s Center of Mass (CoM) coincides with its Center of Pressure (CoP), eliminating torques from atmospheric drag pressure. Similarly, we assume no offset between the CoM and the point of solar pressure application, resulting in zero torque from solar radiation.
State: Includes position (r), velocity (v), quaternion (q), & angular velocity (omega).
RK45: An adaptive Runge-Kutta solver for high accuracy over 1 hour (3600 s).
Step 6: Visualizing with VTK
The Visualizer class renders the satellite and Earth in 3D using VTK. Here, we use the code snippet without explanation, as it is out of the scope of this blog. Let me know in the comments if a small tutorial on vtk is required.
Step 7: Running the Simulation
Finally, the SatelliteSimulation class declares objects of all the classes above and runs the visualization
Finally, we define the main function
Replace sat.stl with your STL file path.
Run the script: python satellite_sim.py.
When you run this, a VTK window will pop up showing:
A blue Earth sphere at the origin.
Your satellite orbiting around it
Console output showing simulation progress.

Tuning
Controller Gains: Adjust kp and kd in Controller() for faster or smoother control. Higher values of kp increase responsiveness but may cause oscillations.
Conclusion
Congratulations! You’ve built a high-fidelity 6-DoF satellite simulation with Python. This code combines orbital mechanics, attitude dynamics, and 3D visualization, perfect for learning aerospace concepts or prototyping satellite missions. Play around with the parameters, swap in your own STL model, and let me know how it goes in the comments!
Happy coding!!!!
Comments