# Levitation Control Repository This repository contains embedded firmware, sensor characterization tooling, and a physics-based simulation stack as well as control algorithm trials for the Texas Guadaloop maglev system. This code is property of **Texas Guadaloop**, a student-led hyperloop team from the University of Texas at Austin. --- ## Repository Structure ``` . ├── AltSensorTesting/ # Arduino firmware for Baumer inductive sensor characterization ├── sensor/ # Python scripts to collect and fit sensor calibration data ├── loadCellCode/ # Arduino firmware for HX711 load-cell calibration ├── TwoCellMagChar/ # Two-cell magnetic characterization rig (validates Ansys data) ├── lev_sim/ # PyBullet simulation driven by Ansys sweep data ├── MAGLEV_DIGITALTWIN_PYTHON/ # Earlier single-axis analytical digital twin (reference) ├── serial_plotter.py # Live serial plotter utility ├── equilibrium.py # Equilibrium gap/current solver └── requirements.txt # Python dependencies ``` --- ## Embedded Stack ### `AltSensorTesting/` Arduino firmware for reading Baumer inductive analog distance sensors. Uses interrupt-driven ADC sampling at ~77 kHz (16 MHz / prescaler 16) for low-latency gap measurement. Tracks the 10 lowest and 10 highest in-range ADC values over a sampling window to help establish calibration bounds. An out-of-range (OOR) digital pin is monitored in the ISR to discard invalid readings. Key details: - ADC ISR at ~77 kHz; readings discarded automatically when OOR pin is HIGH - Serial commands: `1` to start sampling, `0` to stop and print boundary statistics - Baud rate: 2,000,000 --- ## Sensor Characterization ### `sensor/` Python pipeline for converting raw ADC readings from the inductive gap sensors into calibrated millimeter distances. - **`sensorCollector.py`** — Serial interface that reads live ADC values from Arduino and applies the calibration model in real time. - **`analogFitter-*.py`** — Curve-fitting scripts (polynomial, exponential, 3/4/5-parameter logistic) that fit calibration sweep data (`data*.csv`) to find the best sensor model. The 5-parameter generalized logistic form was found to give the best fit. - **`Sensor*Averages.csv` / `data*.csv`** — Raw and averaged calibration data for sensors 0–3. Sensor 3 required a different voltage divider (20 kΩ / 50 kΩ) because the induction sensor output exceeds 6 V. Calibration constants (A, K, B, C, v) for the generalized logistic model are embedded directly in `sensorCollector.py` and `sensor_simplerNew.py` for deployment. --- ## Magnetic Characterization (`TwoCellMagChar/`) A minimal bench rig used to validate Ansys Maxwell FEA force predictions experimentally. - **`TwoCellMagChar.ino`** — Drives two H-bridge coil channels across a sweep of PWM values (−250 to +250 in steps of 50) while reading two HX711 load cells simultaneously. Averages 10 measurements per PWM step and reports gram-force readings over serial. - **`MagCharTrial.xlsx`** — Recorded force-vs-PWM data from physical trials. - **`CalibConsts.hpp`** — Load-cell offset and scale constants shared with `loadCellCode/`. The measured force curves confirmed that the Ansys sweep data is in reasonable agreement with physical hardware, providing confidence for using the FEA model inside the simulation. --- ## Levitation Simulation (`lev_sim/`) A PyBullet-based simulation environment for 4-point active magnetic levitation of the pod. The simulation is driven by an Ansys Maxwell parametric sweep (coil currents × gap height × roll angle → force & torque), fitted to a polynomial regression model for fast inference. ### Data pipeline 1. **Ansys sweep** — `Ansys Results 12-9.csv / .xlsx` contains FEA results sweeping left/right coil currents, roll angle, and gap height. 2. **Function Fitting** — `Function Fitting.ipynb` fits the Ansys data to a `PolynomialFeatures + LinearRegression` model (inputs: `currL`, `currR`, `roll`, `1/gap`). The trained model is saved to `maglev_model.pkl`. 3. **Fast inference** — `maglev_predictor.py` (`MaglevPredictor`) loads the pickle and bypasses sklearn overhead by extracting raw weight matrices, running pure-NumPy polynomial expansion for ~100× faster per-sample prediction. ### Simulation environment `lev_pod_env.py` implements a [Gymnasium](https://gymnasium.farama.org/) `Env` wrapping PyBullet: - **State**: 4 gap heights (normalized) + 4 gap-height velocities - **Action**: 4 PWM duty cycles ∈ [−1, 1] (front-left, front-right, back-left, back-right coils) - **Physics**: first-order RL circuit model per coil (`mag_lev_coil.py`); coil parameters: R = 1.1 Ω, L = 2.5 mH, V_supply = 12 V, I_max = 10.2 A - **Forces**: `MaglevPredictor.predict()` maps coil currents + gap + roll → force and torque applied to the pod body in PyBullet - **Noise**: configurable Gaussian sensor noise (default σ = 0.1 mm) and stochastic disturbance forces - Target equilibrium gap: 11.86 mm (9.4 kg pod) - Simulation timestep: 1/240 s The environment is controller-agnostic — any control algorithm can be plugged in: | File | Controller | |------|-----------| | `lev_PID.ipynb` | Interactive PID tuning notebook | | `lev_PPO.ipynb` | PPO reinforcement learning via Stable-Baselines3 | ### Supplementary Files for PID: `pid_simulation.py`: Feedforward LUT + PID `optuna_pid_tune.py`: Optuna-based automated PID hyperparameter search Pre-tuned PID gain sets are saved in `pid_best_params*.json` (variants for 1500, 3000, and 6000 Optuna trials). ### PWM circuit model `PWM_Circuit_Model.py` is a standalone electrical model of the H-bridge PWM drive circuit used for offline verification of the coil current dynamics. --- ## Setup ```bash pip install -r requirements.txt ``` Key dependencies: `pybullet`, `gymnasium`, `stable-baselines3`, `scikit-learn`, `optuna`, `pyserial`, `numpy`, `scipy`, `pandas`, `matplotlib`.