Symbolic control-law extraction for embedded systems.
EdgeSense fits compact, human-readable equations to logged sensor/actuator data using symbolic regression (PySR) and exports the selected equation as a plain C function for microcontrollers (STM32 / Arduino / ESP32). No neural network is needed at runtime.
Status: research prototype. No validation on real hardware yet (planned, BSHC Varna).
Correction (v2.1): versions up to 2.0 fitted the output of an untrained neural network instead of the logged data. The equation previously shown in this README (
thrust_cmd = ((error × −1.019) + gyro_y + 1.337) × 0.271) therefore does not describe the data and has been withdrawn. The pipeline has been fixed; results will be regenerated.
Given a CSV with input columns (e.g. error, gyro_y) and a target column
(the actuator command, e.g. thrust), EdgeSense:
- splits the data chronologically into a training part and a held-out test part,
- runs symbolic regression on the training part to find
target = f(inputs), - reports held-out RMSE and R² against a constant-mean baseline,
- saves all candidate equations (
hall_of_fame.csv), - exports the selected equation as a C function.
The result is a fitted expression, not a derived physical law. Its value is that it is short, inspectable, and cheap to run, and that it can be bounded by a runtime safety filter.
# 1. Self-test on synthetic data generated from a known PD law
python scripts/generate_and_test.py
# 2. Fit your own log
python scripts/train_on_real_data.py --csv data/pool_record.csv \
--inputs error gyro_y --target thrust --data-label SIMULATEDThe self-test generates data from thrust = −0.28·error + 0.27·gyro_y + 0.36 + noise
and checks that the pipeline recovers those coefficients. It tests the pipeline only.
Outputs (in outputs/): hall_of_fame.csv, <model_name>.c.
Runs are reproducible for a given --seed.
Logged CSV (inputs + actuator command)
↓
Chronological train / test split
↓
Symbolic regression (PySR) → hall_of_fame.csv
↓
Held-out evaluation (RMSE, R²)
↓
<model_name>.c ← selected equation as a C function
↓
MicroSafe-RL ← runtime output filter (hard bounds, NaN guard, instability score)
↓
Actuator
/* GENERATED BY EDGESENSE NANO v2.1
* Symbolic regression fit: thrust = f(error, gyro_y)
* Data type: SYNTHETIC (known PD law)
* Inputs: x0 = error, x1 = gyro_y
*/
float synthetic_model_inference(float x0, float x1, float x2) {
(void)x2;
return -0.279520f*x0 + 0.270055f*x1 + 0.359872f;
}The function signature is fixed at three float arguments for compatibility with
MainDemo.ino; unused arguments are cast to void. No heap allocation. A linear
expression like this is a few floating-point operations on a Cortex-M4F; timing on target
hardware has not yet been measured for this repository.
#include "MicroSafeRL.h"
MicroSafeRL safety; // default bounds [-1.5, +1.5]
void loop() {
float cmd = real_physics_model_inference(error, gyro_y, thrust);
float safe_cmd = safety.apply_safe_control(cmd, gyro_y);
motor.set(safe_cmd);
}MicroSafe-RL is a model-free output filter, not a control barrier function. What it guarantees: for finite inputs the output stays within the configured bounds, and an invalid (NaN/Inf) command becomes 0. Its adaptive attenuation is small at default settings (at most ~4.8%), and it has not yet been shown to outperform plain clipping. See the MicroSafe-RL repository for its validation status and limitations.
MainDemo/MicroSafeRL.h is an unmodified copy of the header from
github.com/Kretski/MicroSafe-RL-core
MainDemo/MainDemo.ino runs on an STM32 (Arduino core) with scripted, simulated inputs:
calm, acceleration, disturbance, sensor failure (NaN) and recovery phases. Over serial it
prints the raw and filtered command, the instability penalty, and the measured latency of
model + filter (DWT cycle counter). It does not measure energy or vessel behaviour.
MainDemo/real_symbolic_model.c currently contains a placeholder model (the withdrawn
equation) so that the demo compiles. Replace it with a regenerated file before drawing any
conclusions from the demo output.
├── scripts/
│ ├── train_on_real_data.py # fit target = f(inputs) from a CSV, export C
│ └── generate_and_test.py # synthetic self-test with a known PD law
├── src/
│ ├── edgesense_core.py # NN + ensemble training (baseline, separate use)
│ └── symbolic_from_nn.py # distil a TRAINED network into an equation
├── edgesense/ # data loading, feature selection, drift detection
├── MainDemo/
│ ├── MainDemo.ino # STM32/Arduino bench demo (simulated inputs)
│ ├── MicroSafeRL.h # output filter, copy from MicroSafe-RL-core
│ └── real_symbolic_model.c # model used by the demo (currently a placeholder)
└── outputs/ # generated equations and C files (created by the scripts)
data/*.csv is git-ignored; datasets are not included in the repository.
- No real-hardware validation. No result in this repository comes from a real vessel.
- Fitted, not discovered. Symbolic regression finds an expression that reproduces the target from the given inputs; it does not establish causality or physical meaning.
- Closed-loop data. When the log comes from a system already under feedback control, the fit mostly recovers that controller.
- Disturbances not characterised. Waves, current, wind, sensor noise and actuator saturation are not represented in current data.
- Inputs must be chosen by the user.
- Logs from a real USV platform (model or full scale), including runs in waves
- Comparison against the controller actually running on the vessel
- Robustness tests: sensor noise, actuator saturation, sensor dropout
- Measured timing and memory footprint on target MCUs
Autonomous surface vessels, drone attitude control, industrial process control — any system where a short, inspectable control expression is wanted and logged data exist. None has been validated on real hardware yet.
- arXiv (cs.SY / cs.RO): in preparation
Copyright © 2025 Dimitar Kretski. All rights reserved.
Non-commercial use (research, education, personal projects): free to use with attribution.
Commercial use: requires a separate license. Contact: kretski1@gmail.com · github.com/Kretski
This repository is not MIT-licensed.