Portfolio
Portfolio
Pytellite is an open-source tool for quickly testing and visualizing satellite attitude control laws in a web app. As of early September 2025, it supports PD controllers for inertial pointing with reaction wheels based on error quaternion and angular velocity, calculated with:
Here, ω is the angular velocity of the body frame with respect to the inertial frame, in body frame coordinates; J is the inertia matrix in body coordinates; L is the effective wheel control torque in body coordinates; h is the wheel angular momentum in body coordinates; q is the current attitude quaternion, from body to inertial frame; qc is the desired attitude quaternion; ẟq is the error quaternion; ϵ and η are the vector and scalar components of the quaternion, respectively; ⊗ is the left quaternion product.
Currently, the code assumes that there are three reaction wheels whose axes are aligned with the principal axes of inertia of the satellite. The following torque control laws are implemented in Pytellite, obtained from Eqs. (7.12) and (7.14) from Fundamentals of Spacecraft Attitude Determination and Control by Markley (2014):
Here, kp and kd are the proportional and derivative gains, respectively. The first law is the "linear" option on Pytellite (although not technically linear due to the sign factor), and the second is the nonlinear controller option. Pytellite integrates these equations using an adaptive step-size solver and feeds interpolated state solutions to the frontend at fixed time intervals, allowing the satellite motion to play smoothly. Math-heavy functions are accelerated using Numba's JIT compilation. Quaternion interpolation is handled with a slerp function.
Users can easily adjust controller settings and satellite parameters, then visualize the results in real time. I’m currently adding a nadir-pointing controller using sliding mode control (requiring modeling the orbit of the spacecraft), as well as modeling torque perturbations (gravity gradient, drag, Solar radiation pressure, which also requires modeling the orbit). You can test the simulator at Pytellite.org and find the source code in Github.
I implemented an error-state multiplicative extended Kalman filter (MEKF) for attitude determination to carry out software-in-the-loop simulations. The filter assumes a satellite equipped with gyroscopes and a star tracker, providing noisy angular rate and attitude measurements, respectively. Gyroscope outputs are modeled with white noise (angle random walk, ARW) and bias drift, the latter represented as a Wiener process (rate random walk, RRW). Star tracker measurements are modeled by injecting a white noise quaternion multiplicatively into the true attitude quaternion. I will soon implement this estimation feature to Pytellite.
The full algorithm is a bit too long to detail here, but I have written a dedicated page on the theory behind it in the project’s documentation.
Below are example outputs from the code: the time evolution of total pointing error, as well as the bias and attitude estimation errors relative to ground truth.
In my PhD research I found a method that increases the specific impulse (Isp) of actively fed (capillary) electrospray thrusters by a large factor. I also showed that the common indirect characterization technique (mass spectrometry) systematically overestimates both Isp and overall efficiency, and I proposed a plausible physical explanation for that discrepancy.
These findings were in part enabled by the automated experimental setup I built: it automated instruments (oscilloscopes, signal generators, valves, etc.), data acquisition, and post-processing through a Python script and GUI. That automation dramatically increased experimental throughput compared to previous studies, letting me explore many operating variables.
Electrospray propulsion accelerates charged droplets and ions emitted from an electrospray source. It gained attention in the early 2000s as a high-efficiency option for small satellites, where conventional plasma thrusters suffer from low efficiency at small scales. Actively fed devices use capillary emitters with controlled propellant feed and primarily emit charged droplets. They are highly reliable (an actively fed thruster was used on the ST-7 mission and operated for over 3,000 hours), but until my work their demonstrated Isp was modest (below ~200 s). Passively fed emitters rely on capillarity to draw liquid to the tip, tend to emit mostly ions and achieve higher Isp, but without active control they have only demonstrated runs under ~200 hours before failure. My research demonstrates that with certain capillary geometries and ionic liquid propellants, actively fed electrosprays can operate stably long-term at Isp values up to 1100 s.
Below are a schematic of the setup and a screenshot of the Python GUI (designed in early 2022).
A microscope image of a capillary emitter I tested. The jet that is ejected from the Taylor cone tip is not visible as its diameter is about ~10 nm.
Trada calculates impulsive transfers to all known small bodies in the Solar System by solving the Lambert problem and storing the trajectories on a SQL database. Ephemerides are imported from JPL's Small-Body Database. A local web-based GUI allows to search candidate bodies within the user's requirements of time-of-flight, departure trajectory direction and dates, delta v, amongst other settings. It can also show Pareto fronts, porkchop plots, and more plots. I created this tool during my stay at JAXA as a Visiting Scholar in 2020. The app was mostly developed in Python, with Dash/Plotly for the web app.
I co-founded and led the engineering team of Cosmic Research from its inception in 2016 until mid 2019. Cosmic Research is a student rocket team that develops solid rocket motors sounding rockets for peaceful applications. Below are pictures of the culmination of our work, the test of the Nebula-III, a 10 kN solid rocket motor I co-led the design of (along with Xavier López).
Static test of Nebula-III
Xavier López holding one of the propellant grains of Nebula-III that we manufactured with a custom hydraulic press system
Some parts of the rocket motor assembly, including the ignitor bulkhead and graphite nozzle
Me with Nebula-III at the test stand
A close-up of the igniter subassembly of the Nebula-III motor.
Before Nebula-III, we designed and tested many other smaller solid rocket motors, learning from each success and failure.
Xavier López (left) and myself (right), about to test Nebula-II
Close-up of Nebula-II on the test stand. We measured chamber pressure, thrust, and temperature at several points of the outer part of the chamber. Nebula-II was a 1 kN aluminum/ammonium nitrate motor, based on Nebula-I but with a thin aluminum chamber
Static tests of Nebula-I, a 1 kN solid rocket motor with a aluminum/ammonium nitrate propellant and a thick stainless steel motor chamber for initial characterization
Some unexpected outcomes were inevitable on our way. Here is the fate of the chamber of Nebula-0
This course covers everything from aerodynamics of sounding rockets to flight instability induced by pitch-roll resonance. Examples of topics covered are subsonic and supersonic models of drag and lift of fins and body sections, analysis of flight dynamics, and trajectory simulation. You can find the link to the 10h course here.