Myoelectric signals from your forearm drive a robot arm that shuttles surgical instruments into an autoclave with deterministic, safe motion primitives.
Kapture.2025-09-29.at.12.32.14.mp4
- Modular Python package (
musclemate/) with clean separation of hardware adapters, gesture decoding, control logic, and simulated EMG feeds. - Command line interface (
control.cli) for live runs or scripted demosโno need to touch application code. - Configuration via dataclasses with sensible defaults for thresholds, waypoints, speeds, and loop timing.
- Test suite (
tests/) covering gesture decoding logic and scripted EMG playback. - Packaging metadata (
pyproject.toml) forpip install .deployment.
โโโ control/
โ โโโ __init__.py
โ โโโ cli.py # CLI entry point
โ โโโ config.py # Dataclass configs and timing
โ โโโ gesture.py # Debounce + hysteresis + intent decoding
โ โโโ runner.py # Main loop orchestrator
โ โโโ state_machine.py # Finite-state workflow for sterilization
โ โโโ utils.py # Shared helpers (clamp, etc.)
โโโ hardware/
โ โโโ __init__.py
โ โโโ arm.py # Arm interface + QArm stub
โ โโโ emg.py # EMG reader protocol + static source
โโโ sim/
โ โโโ __init__.py
โ โโโ emg_profiles.py # Scripted EMG scenarios for demos and tests
โโโ tests/ # Pytest-based unit tests
โโโ pyproject.toml # Packaging metadata
- Flex a muscle โ two EMG channels capture the activity.
- Signal cleaning yields a smooth strength value (the envelope).
- Dual thresholds with hysteresis decide on/off to avoid chatter.
- Debounce, cooldown, and long-press logic produce stable intents.
- The robot executes a safe sequence: select bin โ approach โ grip โ lift โ autoclave โ place โ close โ home.
Thatโs the loop: muscle โ intent โ motion until the instrument is safely sterilized.
git clone https://github.com/chaffybird56/MuscleMate.git
cd MuscleMate
python -m venv .venv && source .venv/bin/activate # optional but recommended
pip install .python -m control.cli --demo
# or simply: musclemate --demo # after installing the console script- Uses a deterministic EMG script to exercise the full sterilization cycle.
- Logs intents/state transitions while the stub arm tracks pose updates.
Replace QArmStub and StaticEMGSource with your Quanser QArm / biosignal bindings by subclassing the ArmInterface and EMGReader protocols in hardware.
| Parameter | Location | Purpose |
|---|---|---|
Thresholds |
control.config |
EMG on/off thresholds, debounce, cooldown, long-press abort |
Waypoints |
control.config |
Bin/autoclave/home coordinates |
Speeds |
control.config |
Motion profile speeds & gripper dwell |
Sampling |
control.config |
Runtime and loop rate defaults |
Override values at runtime with CLI flags, e.g.:
python -m control.cli --emg-on 0.7 --cooldown 0.4 --loop-rate 60- Acquire EMG from two channels โ normalize to
[0, 1]. - Deadband + hysteresis debounce the raw signal into stable "pressed" states.
- Gesture mapping converts channel patterns into
Intentenums (start, grip, toggle door, abort). - Finite-state machine (
State) ensures safe, sequential motion primitives:
IDLE โ SELECT_BIN โ APPROACH โ GRIP โ LIFT โ TRANSIT
โ OPEN_AUTOCLAVE โ PLACE โ CLOSE_AUTOCLAVE โ HOME
- Safety: Long-press on channel 2 issues an ABORT, homing the arm immediately.
Let
Rectify and low-pass filter to obtain a smooth envelope
-
$f_c$ : 3โ6โฏHz cutoff keeps the envelope slow and stable. - Intuition: a moving average of the absolute EMG suppresses spikes.
From a rest segment, compute baseline
- Different electrodes, different baselinesโz-scores compare apples to apples.
Use on/off thresholds
- Once โon,โ the signal must fall below
$\theta_{\text{off}}$ to turn offโno flicker at the boundary.
-
Debounce: require
$c_i[n] = 1$ for$T_d$ seconds โ$N_d = \lceil T_d / (1/f_s) \rceil$ consecutive samples. -
Cooldown: ignore new gestures for
$T_c$ seconds after accepting an intent.
If channel 2 stays active for
| Symbol | Meaning | Typical |
|---|---|---|
| EMG sampling rate | 200โ1000โฏHz | |
| Envelope cutoff | 3โ6โฏHz | |
| On threshold (z-score) | 0.65โ0.9 | |
| Off threshold (z-score) | 0.30โ0.5 | |
| Debounce time | 0.10โ0.20โฏs | |
| Cooldown | 0.30โ0.40โฏs | |
| Long-press (abort) | โ 1.2โฏs |
Calibration tip: Take a rest recording, set
pip install pytest
pytestUnit tests validate gesture decoding (debounce, cooldown, long-press) and deterministic EMG playback. Extend with hardware-in-the-loop tests as you integrate real sensors.
- Connect your EMG acquisition and arm bindings.
- Run
python -m control.cli --loop-rate 60 --runtime 30to exercise the loop at control-rate. - Monitor logs for state transitions; abort safely with a long press.
- Add assertions around
ControllerEventstreams to automate pass/fail checks.
- Reliable pick/place of mock instruments into the autoclave (sim + hardware).
- Long-press abort always returns to home.
- Stable control thanks to the envelope, hysteresis, and debounce stages.
Limitations. EMG varies day-to-day; revisit thresholds periodically. The autoclave door dwell is simulated in the stub implementation. Expanding the gesture set will require additional channels or a classifier.
- Add new intents by expanding
Intentand updating the transition logic instate_machine.py. - Integrate real EMG hardware by implementing
EMGReader. - Plug in motion planning or collision checking in
SterilizationController.move_to. - Log or stream
ControllerEventinstances via the optional sink inrun_controller.
- Extend the
Intentenum and FSM transitions for new gestures. - Wire up your EMG backend through
EMGReader. - Enhance
SterilizationController.move_towith planners or collision avoidance. - Attach a telemetry sink to
run_controllerfor logging or streaming events.
- EMG โ Electromyography; electrical activity from muscles.
- Envelope โ Smoothed strength signal after rectification + low-pass filtering.
- Hysteresis โ Using two thresholds to avoid flicker around the setpoint.
- Debounce โ Minimum press duration to confirm state changes.
- Cooldown โ Timeout to prevent rapid re-triggering.
- Waypoint โ Predefined robot pose used to build motion sequences.
MIT โ see LICENSE.