TeslasuitDocumentation
Frameworks

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.py

Expected 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()#

AttributeWhat it contains
self.contacts.right_foot_contactTrue = right foot on ground (stance)
self.contacts.left_foot_contactTrue = left foot on ground
self.joints.KneeFlexExtRRight knee flexion angle (degrees)
self.joints.HipFlexExtRRight hip flexion angle (degrees)
self.joints.*29 joint angles total — see Data Types Reference → BiomechanicalData
self.ems_output.quadriceps_rightWrite 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 True by default when running headless. Pass a utility_queue and set FesIsActive = False to mute all stimulation programmatically.
  • Ctrl-C stops the application cleanly — all EMS stops immediately.

Next Steps#

GuideWhat it covers
Project anatomyThe shape of an RapidKit application
Implementation GuideThe 9-step linear build of a complete FES application
Concepts → overviewThe framework's building blocks and how they compose
Examples → Walking FESFull walking FES application walkthrough
API ReferenceComplete class/method signatures