Loading model…

Guadaloop
Testrig

Scroll to explore

Click to replay the 3D · minimise ›
0%
press G to edit part groups

Grouping editor

yoke (BabyYoke + coils)
sensors (DW-AD modules)
rails (slide system)
chassis (frame)
other / hidden
Drag to orbit. Click a part to cycle its group. Press E to export JSON, G to exit.
click a part…
✕ close
Copied to clipboard. Paste this into groups.json (replace the whole file), then reload.
Texas Guadaloop · Levitation

LevSim is the simulation environment I built so levitation controllers can be designed and tuned against the rig's real magnetic behaviour — not a hand-derived model that falls apart on contact with hardware.

Ansys FEASciKit-LearnPyBulletGymnasiumPID · LQR · RL
Role
CAD · All Software Architecture + Implementation · Ansys work guided by Aditya Matam & Neha Ramachandran
Timeline
Nov – Dec 2025
Stack
Ansys Electronics Desktop · SciKit-Learn · PyBullet · Gymnasium
Status
Functional prototype

The problem

Hybrid electromagnetic suspension (HEMS) is a proven low-power way to levitate, but it's brutally nonlinear — and for a student team there's no clean way to simulate one without re-deriving the magnetic flux through the whole structure (and the air around it) for every design change. At best that's tedious; at worst it's a wall that keeps teams without graduate-level magnetostatics from ever touching the control problem.

After two years on the lev sub-team I'd watched the same gap open again and again: controllers that held rock-steady in our MATLAB sim under any disturbance fell apart on the real rig under near-perfect conditions. We were missing a fundamental piece of the analytical model, and MATLAB wasn't scaling past PID anyway. The fix was to stop hand-calculating forces and root the simulation in empirical data instead — Ansys FEA (verified against load-cell measurements) → a polynomial force model → a PyBullet rigid-body sim.

System overview

LevSim system architecture An offline Ansys FEA sweep of a single yoke is fit to a polynomial force model. At run time, Lev_pod_env.py orchestrates a loop: it reads pod state from PyBullet, converts controller output to coil currents with maglev_coil.py, queries the MagLev Predictor for per-yoke force and torque, and feeds those back into PyBullet — all wrapped in a Gymnasium interface a PID, LQR, or RL controller can drive. Ansys FEA single-yoke magnetostatic Force / torque LUT 4 states → force + torque Polynomial fit Maglev_Model.pkl parametric sweep SciKit-Learn fit loaded at startup MagLev Predictor state → force / torque mini physics server Lev_pod_env.py Gymnasium env, connective tissue. implements sensor noise + reward Controllers PID · LQR · RL PyBullet rigid-body dynamics · 240 Hz maglev_coil.py PWM → coil current incl. inductive impedance ↓ force, torque ↑ state + currents state + reward control output per-step force / torque physical state of pod ↓ analog PWM ↑ coil current
Two-phase architecture: an Ansys FEA sweep of a single yoke is distilled offline into a polynomial force model, which a 240 Hz runtime loop (Lev_pod_env.py ⇄ PyBullet) queries every step while a controller drives the pod. Redrawn from the project's dataflow diagram.

The pipeline splits in two. Offline, an Ansys magnetostatic model of a single yoke is swept across the coil currents, gap heights and roll angles the rig actually sees; the resulting force/torque table is fit to a polynomial (Maglev_Model.pkl) so it can be evaluated in microseconds. At run time, Lev_pod_env.py is the orchestrator: each step it pulls the pod's state from PyBullet, converts the controller's analog output into real coil currents with maglev_coil.py, asks the MagLev Predictor for the per-yoke force and torque, and feeds those point loads back into PyBullet — all wrapped in a Gymnasium interface so any controller can drive it.

Decisions & deep dives

Why FEA, not an analytical model?

I first proved FEA was trustworthy: a load-cell setup measured the force on a single small yoke, and Ansys magnetostatic results at the same gaps agreed within ~10%. That made an FEA-derived lookup a reliable replacement for the broken analytical chain.

Why a polynomial on top of FEA?

Running Ansys inside the sim loop is infeasible. A parametric sweep across the rig's working range of heights, roll angles and coil currents gives a discrete table; fitting it in SciKit-Learn (lev_sim/Function Fitting.ipynb) turns each step into a cheap polynomial evaluation — and makes the pipeline plug-and-play for new yoke designs.

Why PyBullet + Gymnasium?

PyBullet handles the rigid-body dynamics; a custom maglev_coil component models coil current (including inductive impedance) so the force model gets real currents. Our LUT-fit polynomial model ensures we have FEA-backed force and torque driving our simulation, and Gymnasium standardizes the interface, so the same environment runs under PID (lev_PID) or RL (lev_PPO).

How do you reuse it across controllers?

lev_pod_env.py exposes exactly the I/O a controller sees on the real pod — distance-sensor readings in, motor-controller PWM out — so anything written against the sim can move straight onto the rig with no interface changes.

Results & honest limits

  • A repeatable simulation process that works for complex systems like maglev, grounded in FEA data and tested with both a hand-tuned PID loop and a trained PPO policy.
  • The force model is only as good as the swept range — extrapolate far outside it and the polynomial is unreliable.
  • It's a functional prototype: the coil model is a simplification, and fully closing the sim-to-real gap still requires tuning runs on the physical rig, though our starting point improves considerably.

The team

Videos

Full walkthrough · 8:22
Working demo · 1:43
Safe completion demo · 0:58
Clean levitation run · 0:08
Early instability · 0:42
This is a condensed case study. Want more details? Reach out.