TeslasuitDocumentation
Frameworks

Implementation Guide

A 9-step linear build of one FES application. Each step adds one capability. Read in order; copy code as you go; you'll have a complete working application by the end.


How this guide works#

You're going to build the same application across 9 steps. Each step adds exactly one new capability — sensors, stimulation, calibration, runtime parameters, external inputs, recording, GUI — without breaking what you had at the end of the previous step.

By the end, you'll have an application that:

  • runs a closed-loop control strategy at 100 Hz,
  • reads joint angles and foot contacts each cycle,
  • stimulates muscles by anatomical name,
  • refuses to start until calibration quality is acceptable,
  • accepts runtime parameter changes from a GUI,
  • fuses external LSL device data into the strategy,
  • streams every channel to LabRecorder for offline analysis,
  • shows real-time data in a PyQt5 operator interface.

That is essentially the full feature set of the framework. Once you understand each step in isolation, mixing and matching for your own research application is straightforward.


Prerequisites#

Before starting:

  1. Install the framework and verify with python -c "import RapidKit; print('OK')".
  2. Skim the Concepts overview so you recognise the names that appear here (ControlStrategyBase, EmsData, MuscleMap, ClosedLoopEngine, etc.).
  3. Have a Teslasuit available, powered, and on the same WiFi network as your computer. Teslasuit Control Center should be running.
  4. The first three steps are safe to run on any user; steps 3 onward deliver actual stimulation, so test on yourself first at low amplitude before involving anyone else.

The 9 steps#

#CapabilityAnchored exampleNew concept introduced
1First strategy — closed loop, no stimulationexamples/atomic/minimal_closed_loop.pyControlStrategyBase, orchestrator.launch()
2Reading sensor dataexamples/atomic/reading_sensor_data.pyself.joints, self.contacts
3Stimulating muscles by nameexamples/atomic/semantic_muscle_control.pyself.muscles, EMSParamData, self.ems_output
4Calibration gateexamples/atomic/calibration_gate.pyengine.calibration, on_start()
5Runtime parameters(new)ControlMessage subclass, self.params
6External inputs (LSL inlets)(extended from lsl_streaming.py)ExternalInputManager, self.external_data
7Recording and LSL outletsexamples/atomic/lsl_streaming.pylsl_enabled, LabRecorder, XDF
8Adding a GUI(built around examples/generic_gui/)PyQt5, SharedRingBuffer, QueueHandler
9Full application(the working app you've built)Bringing it all together

How to use a step#

Each step page follows the same shape:

Goal: one sentence You'll use: [Concept A], [Concept B] Builds on: the previous step Anchored example: examples/atomic/<file>.py

What you're adding: two paragraphs explaining the new capability.

Code: a self-contained file you can save and run.

Walkthrough: annotated explanation of what the new lines do.

Verify: how to confirm the step worked.

Next: pointer to the next step.

The "Code" block is complete — paste it into a fresh .py file and run it. If a snippet is partial, the step says so explicitly.


When you're stuck#

  • The Troubleshooting page catalogues every common error and its fix.
  • Each step has its own anchored example file; if your code disagrees with the example, the example is the source of truth.
  • The API Reference gives every signature.
  • For deep questions, the Design principles page explains why things are the way they are — useful when something feels surprising.

Ready?#

Start with Step 1 — First strategy.