Quick Start: Your First FES Application
Get a minimal FES application running in under 10 minutes.
What you'll build: An application that stimulates the right quadriceps whenever the right foot is in contact with the ground.
⚠️ Before you stimulate anyone. Never run stimulation on an uncalibrated suit — calibrate the wearer in Control Center first, keep the amplitude low (20–40%), and keep one hand on Ctrl-C, which stops all EMS immediately. If anything feels wrong, unplug the power bank and remove the suit. Full rules: Concept - Haptics and Hardware - Safety.
Prerequisites#
- Windows 10/11 (64-bit)
- Python ≥ 3.10
- Teslasuit Control Center installed and running
- Teslasuit hardware powered and on the same WiFi network
- Suit calibrated to the current wearer in Control Center. Stimulation amplitude is a percentage of that calibrated range, so an uncalibrated suit can deliver a far stronger sensation than intended. See Concept - Calibration.
See Installation if you haven't set up the environment yet.
Step 1: Install#
# From the project root:
pip install -e .
# Verify:
python -c "import fes_framework; print('OK')"Step 2: Write Your Strategy#
Create my_strategy.py:
from fes_framework.control.strategy_base import ControlStrategyBase
from fes_framework.data.types import EMSParamData
class StanceQuadStrategy(ControlStrategyBase):
"""Stimulate right quadriceps during right stance phase."""
def process(self) -> None:
if self.contacts.right_foot_contact:
self.ems_output.quadriceps_right = EMSParamData(
IsMuted=False,
Amplitude=40, # 40% — start conservative
PulseWidth=120, # 120 μs
Period=20.0, # 20 ms = 50 Hz
)
else:
self.ems_output.quadriceps_right = EMSParamData(IsMuted=True)This is the complete strategy. The framework handles everything else.
Step 3: Run It#
⚠️ Do not run this on a person until the suit is calibrated (see
Prerequisites) and you have confirmed Ctrl-C stops stimulation. The
bare run.py below has no mocap calibration gate — add the gate from Step 4
for any run with the suit worn.
Create run.py:
from fes_framework.orchestrator import launch
from my_strategy import StanceQuadStrategy
if __name__ == "__main__":
launch(StanceQuadStrategy)python run.pyExpected output:
[Orchestrator] Starting backend process…
[Backend] Initialising engine (hardware auto-detected)…
[Backend] Starting engine (LSL OFF)
[Orchestrator] Running headless (Ctrl-C to stop)Press Ctrl-C to stop. The engine shuts down cleanly (stops mocap, mutes all EMS).
Step 4: Add the Mocap Calibration Gate#
This step is mocap calibration (I-pose / self.calibration.calibrate()),
not the EMS suit calibration done in Control Center. It improves motion-capture
accuracy so the foot-contact trigger fires at the right moment. Add a gate that
runs mocap calibration and refuses to start if it fails:
# run_calibrated.py
from fes_framework.engine import ClosedLoopEngine
from my_strategy import StanceQuadStrategy
class CalibratedEngine(ClosedLoopEngine):
def on_start(self) -> None:
input("Stand in I-pose (upright, arms at sides). Press ENTER to calibrate...")
result = self.calibration.calibrate()
if not result.success:
print(f"Calibration failed: {result.message}")
self.stop()
return
print("Calibration OK.")
if __name__ == "__main__":
engine = CalibratedEngine(control_strategy=StanceQuadStrategy())
engine.run()What's Available in process()#
| Attribute | What it contains |
|---|---|
self.contacts.right_foot_contact | True = right foot on ground (stance) |
self.contacts.left_foot_contact | True = left foot on ground |
self.joints.KneeFlexExtR | Right knee flexion angle (degrees) |
self.joints.HipFlexExtR | Right hip flexion angle (degrees) |
self.joints.* | 29 joint angles total — see Data Types Reference → BiomechanicalData |
self.ems_output.quadriceps_right | Write EMSParamData here to stimulate |
self.ems_output.* | 20 muscles total — see muscle table below |
All 20 EmsData Muscles#
Lower body (10):
self.ems_output.quadriceps_left, self.ems_output.quadriceps_right,
self.ems_output.hamstring_left, self.ems_output.hamstring_right,
self.ems_output.gastrocnemius_left, self.ems_output.gastrocnemius_right,
self.ems_output.tibialis_anterior_left, self.ems_output.tibialis_anterior_right,
self.ems_output.gluteus_left, self.ems_output.gluteus_right
Upper body (10):
self.ems_output.deltoid_left, self.ems_output.deltoid_right,
self.ems_output.biceps_left, self.ems_output.biceps_right,
self.ems_output.triceps_left, self.ems_output.triceps_right,
self.ems_output.wrist_flexors_left, self.ems_output.wrist_flexors_right,
self.ems_output.wrist_extensors_left, self.ems_output.wrist_extensors_right
Safety Notes#
- Never stimulate on an uncalibrated suit. Calibrate the wearer in Control Center first; amplitude is relative to that calibrated range.
- Start with Amplitude 20–40%. Increase slowly while observing the user.
- The FES Active flag is
Trueby default when running headless. Pass autility_queueand setFesIsActive = Falseto mute all stimulation programmatically. - Ctrl-C stops the application cleanly — all EMS stops immediately.
Next Steps#
| Guide | What it covers |
|---|---|
| Project anatomy | The shape of an RapidKit application |
| Implementation Guide | The 9-step linear build of a complete FES application |
| Concepts → overview | The framework's building blocks and how they compose |
| Examples → Walking FES | Full walking FES application walkthrough |
| API Reference | Complete class/method signatures |
