TeslasuitDocumentation
Frameworks

LSL Data Streams

This document describes all Lab Streaming Layer (LSL) data streams provided by RapidKit.

Overview#

RapidKit provides 7 LSL outlets from LSLStreamer (fes_framework/io/lsl_streamer.py):

  • TS_Biomechanics — Biomechanical joint angles
  • TS_API_StepDetector — Teslasuit SDK step detector
  • TS_EMSParameters — EMS stimulation parameters
  • AppData_ControlMessage — Application runtime parameters
  • AppData_UtilityMessage — System state flags
  • TS_BonePosition — Skeleton bone positions and rotations
  • TS_RawData — Raw IMU sensor data

All streams are disabled by default and must be enabled via lsl_enabled=True in ClosedLoopEngine. All streams run at 100 Hz nominal sample rate.

Walking FES example note: The Walking FES application (examples/walking_fes/) also provides an 8th stream — ModelBasedStepDetector — from its ML-based step detector. This stream is not part of RapidKit; see Walking FES-specific streams below.


Framework Streams (LSLStreamer)#

1. Biomechanical Data Stream#

Stream Info:

  • Name: TS_Biomechanics
  • Type: Biomechanical
  • Source ID: {source_id}_biomech
  • Sample Rate: 100 Hz
  • Format: cf_double64 (64-bit float)
  • Channel Count: 29 channels

Description: Streams processed joint angles in degrees from the OpenSim biomechanical analysis. Contains all major body joint angles including pelvis, hips, knees, ankles, shoulders, elbows, and wrists. More about biomechnical data in Teslasuit you find here

Channel Structure: All fields from BiomechanicalData dataclass (excluding timestamp):

  • PelvisTilt, PelvisList, PelvisRotation
  • HipFlexExtL/R, HipAddAbdL/R, HipRotL/R
  • KneeFlexExtL/R
  • AnkleFlexExtL/R, FootProSupL/R
  • ShoulderFlexExtL/R, ShoulderAddAbdL/R, ShoulderRotL/R
  • ElbowFlexExtL/R
  • ForearmProSupL/R
  • WristFlexExtL/R, WristUlnRadDevL/R

Metadata per Channel:

  • label: Field name (e.g., "HipFlexExtL")
  • unit: "degrees"
  • type: "angle"
  • id: Channel index

2. Tesla Suit API Step Detector Stream#

Stream Info:

  • Name: TS_API_StepDetector
  • Type: StepDetection
  • Source ID: {source_id}_steps
  • Sample Rate: 100 Hz
  • Format: cf_float32 (32-bit float)
  • Channel Count: 2

Description: Streams foot contact detection from the Tesla Suit SDK's built-in step detector algorithm.

Channels:

  1. left_foot_contact - Boolean flag (0.0/1.0) for left foot ground contact
  2. right_foot_contact - Boolean flag (0.0/1.0) for right foot ground contact

Metadata per Channel:

  • label: "left_foot_contact" or "right_foot_contact"
  • unit: "boolean"
  • type: "contact"
  • id: Channel index

3. EMS Parameters Stream#

Stream Info:

  • Name: TS_EMSParameters
  • Type: EMSParameters
  • Source ID: {source_id}_ems
  • Sample Rate: 100 Hz
  • Format: cf_float32 (32-bit float)
  • Channel Count: 80 channels (20 muscles × 4 parameters)

Description: Streams electrical muscle stimulation parameters for all 20 muscle groups in EmsData. More about EMS parameters in Teslasuit you find here

Channel Structure: All 20 muscles from EmsData (10 lower body + 10 upper body), each with 4 parameters:

  • {Muscle}IsMuted - Boolean (0.0/1.0)
  • {Muscle}Amplitude - Percentage (0–100)
  • {Muscle}Period - Milliseconds (period between pulses)
  • {Muscle}PulseWidth - Microseconds (μs)

Metadata per Channel:

  • label: Field name (e.g., "LeftQuadAmplitude")
  • unit: "boolean", "percent", "Hz", or "us" (depending on parameter type)
  • type: "flag", "amplitude", "frequency", or "pulse_width"
  • id: Channel index

4. Control Message Stream#

Stream Info:

  • Name: AppData_ControlMessage
  • Type: ControlMessage
  • Source ID: {source_id}_control
  • Sample Rate: 100 Hz
  • Format: cf_float32 (32-bit float)
  • Channel Count: Application-dependent (determined by your ControlMessage subclass fields)

Description: Streams the runtime control parameters defined by your application's ControlMessage subclass. The base ControlMessage class is empty; fields are added by subclassing it in your application. Channel count and structure therefore depend entirely on what fields your subclass defines.

Walking FES example: The Walking FES application's WalkingControlMessage subclass defines 80 channels (10 muscle groups × 8 stimulation parameters per muscle). These are Walking FES-specific; your application's channel structure will differ.

Metadata per Channel:

  • label: Field name from your ControlMessage subclass
  • unit: Depends on field type (e.g., "boolean", "Hz", "percent", "us")
  • id: Channel index

5. Utility Message Stream#

Stream Info:

  • Name: AppData_UtilityMessage
  • Type: UtilityMessage
  • Source ID: {source_id}_utility
  • Sample Rate: 100 Hz
  • Format: cf_float32 (32-bit float)
  • Channel Count: 6 channels

Description: Streams system utility flags including the global FES enable state, recording/calibration status, and step detection modes.

Channels: From UtilityMessage dataclass (excluding _on_change and FolderPath):

  • FesIsActive - Boolean flag (0.0/1.0)
  • RecordingIsActive - Boolean flag (0.0/1.0)
  • CalibrationLoopIsActive - Boolean flag (0.0/1.0)
  • TSAPIStepDetectionIsActive - Boolean flag (0.0/1.0)
  • VUStepDetectionIsActive - Boolean flag (0.0/1.0)
  • ModelBasedStepDetectionIsActive - Boolean flag (0.0/1.0)

Metadata per Channel:

  • label: Field name
  • unit: "boolean"
  • type: "recording_flag", "calibration_flag", or "status_flag"
  • id: Channel index

6. Bone Position Stream#

Stream Info:

  • Name: TS_BonePosition
  • Type: BonePosition
  • Source ID: {source_id}_boneposition
  • Sample Rate: 100 Hz
  • Format: cf_double64 (64-bit float)
  • Channel Count: 140 channels (20 bones × 7 channels/bone)

Description: Streams processed skeleton data including 3D position and quaternion rotation for each bone in the Tesla Suit's skeletal model. More about processed skeleton data in Teslasuit you find here

Channel Structure: For each bone in ProcessedData dataclass (excluding timestamp), 7 channels:

  1. {bone}_pos_x - X position (meters or suit units)
  2. {bone}_pos_y - Y position
  3. {bone}_pos_z - Z position
  4. {bone}_rot_w - Quaternion W component
  5. {bone}_rot_x - Quaternion X component
  6. {bone}_rot_y - Quaternion Y component
  7. {bone}_rot_z - Quaternion Z component

Example bones:

  • Pelvis, Spine, Chest, Neck, Head
  • Shoulders, Upper Arms, Forearms, Hands (L/R)
  • Upper Legs, Lower Legs, Feet (L/R)

Metadata per Channel:

  • label: Flattened bone and component (e.g., "Pelvis_pos_x")
  • unit: "meters" for position, "quaternion" for rotation
  • type: "position" or "rotation"
  • id: Channel index

7. Raw Data Stream#

Stream Info:

  • Name: TS_RawData
  • Type: RawData
  • Source ID: {source_id}_raw
  • Sample Rate: 100 Hz
  • Format: cf_double64 (64-bit float)
  • Channel Count: 280 channels (20 sensors × 14 channels/sensor)

Description: Streams raw IMU (Inertial Measurement Unit) sensor data from Teslasuit sensors, including accelerometer, gyroscope, and orientation data. More about biomechnical data in Teslasuit you find here

Channel Structure: For each sensor in RawData dataclass (excluding timestamp), 14 channels:

  1. {sensor}_boneId - Integer bone identifier
  2. {sensor}_q6_w - Quaternion W component
  3. {sensor}_q6_x - Quaternion X component
  4. {sensor}_q6_y - Quaternion Y component
  5. {sensor}_q6_z - Quaternion Z component
  6. {sensor}_accel_x - Acceleration X (raw units)
  7. {sensor}_accel_y - Acceleration Y
  8. {sensor}_accel_z - Acceleration Z
  9. {sensor}_gyro_x - Gyroscope X (degrees/s or raw units)
  10. {sensor}_gyro_y - Gyroscope Y
  11. {sensor}_gyro_z - Gyroscope Z
  12. {sensor}_linear_accel_x - Linear acceleration X (gravity removed)
  13. {sensor}_linear_accel_y - Linear acceleration Y
  14. {sensor}_linear_accel_z - Linear acceleration Z

Metadata per Channel:

  • label: Flattened sensor and component (e.g., "LeftThigh_accel_x")
  • unit: "id", "quaternion", "raw", "deg/s", or "m/s^2" (depending on data type)
  • type: "boneId", "quaternion", "accel", "gyro", or "linear_accel"
  • id: Channel index

Walking FES-Specific Streams#

The following stream is not part of RapidKit. It is provided by the Walking FES example application (examples/walking_fes/).

8. ML Model-Based Step Detector (Walking FES example only)#

Stream Info:

  • Name: ModelBasedStepDetector
  • Type: StepDetection
  • Source: examples/walking_fes/ (PyTorch ML model, not part of RapidKit)
  • Sample Rate: 100 Hz
  • Format: cf_float32 (32-bit float)
  • Channel Count: 2

Description: A PyTorch-based step detector that analyzes IMU data from 8 body sensors with a 30-sample rolling window. Outputs binary foot contact states after temporal smoothing and a 0.6 classification threshold.

Channels:

  1. left_contact — Left foot contact (0.0 / 1.0)
  2. right_contact — Right foot contact (0.0 / 1.0)

Data Flow Summary#

Teslasuit Hardware
        ↓  (WiFi via Teslasuit Control Center)
SuitHandler  (fes_framework/io/suit_handler.py)
        ↓  (raw ctypes frames)
DataStreamer  (fes_framework/io/data_streamer.py)
        ↓  (populated dataclasses)
    ┌───────────────────────────────────────────────────────┐
    │ BiomechanicalData  ProcessedData  StepDetectorData    │
    │ RawData  EmsData  ControlMessage  UtilityMessage      │
    └──────────────────────┬────────────────────────────────┘
               LSLStreamer (7 framework streams)
               Lab Streaming Layer Network
         External Applications (LabRecorder, MATLAB, Python, etc.)

LabRecorder#

All 8 streams are automatically discoverable in LabRecorder. Simply:

  1. Open LabRecorder
  2. Click "Update" to scan for streams
  3. Select desired streams
  4. Click "Record" to save to XDF format

Technical Notes#

Timestamp Handling#

  • Streams use pylsl.local_clock() for timestamping
  • Some dataclasses provide their own timestamps (biomechanical, skeleton, raw)
  • All timestamps are in LSL's global time domain for synchronization

Performance Considerations#

  • Total bandwidth: ~398 KB/s (569 channels, mixed float32/double64 formats)
  • Stream sizes:
    • Raw Data: 280 channels, 219 KB/s (largest)
    • Bone Position: 140 channels, 109 KB/s
    • Control Message: 80 channels, 31 KB/s
    • EMS Parameters: 32 channels, 13 KB/s
    • Biomechanical: 29 channels, 23 KB/s
    • Utility Message: 6 channels, 2 KB/s (smallest)
    • Step Detectors: 2 channels, 1 KB/s total

Data Types#

  • cf_float32: 32-bit float (4 bytes per sample) - Most streams
  • cf_double64: 64-bit float (8 bytes per sample) - Biomechanical, Skeleton, Raw
  • cf_int32: 32-bit integer (not currently used)

Troubleshooting#

Stream Not Appearing#

  • Ensure lsl_enabled=True was passed to ClosedLoopEngine or orchestrator.launch()
  • Ensure the backend engine is running
  • Check firewall settings (LSL uses UDP multicast)
  • Verify network connectivity if using remote streams

High Latency#

  • Check system CPU usage
  • Reduce number of active streams
  • Increase LSL buffer sizes

Data Discontinuities#

  • Check for Teslasuit connection issues
  • Verify model buffer warmup completed (30 samples)
  • Monitor for dropped samples in LSL inlet

See also#

External references#