File size: 5,580 Bytes
53ec232 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | ---
license: cc-by-nc-4.0
tags:
- emg
- semg
- biosignals
- musculoskeletal
- motor-control
- robotics
- pytorch-lightning
- regression
library_name: pytorch
pipeline_tag: other
---
# emg2tendon β pretrained models
Seq2seq regression from surface EMG to **musculoskeletal tendon controls**:
**16-channel sEMG @ 2 kHz β 39-channel MyoHand tendon control β [0, 1]**, over
2-second windows (`T = 4000`). Trained on the full **emg2pose** dataset
(25,253 recordings, 193 subjects, ~370 h), with tendon targets produced by a
QForce inverse-dynamics pipeline through the MyoSuite **MyoHand** model.
Reference implementation + eval code: **https://github.com/sagarverma/emg2tendon**
Project page: **https://emg2tendon.github.io**
Paper: *emg2tendon: From sEMG Signals to Tendon Control in Musculoskeletal Hands*, Sagar Verma, RSS 2025.
## Files
| File | Model | Params | val tendon RMSE | open-loop pose (deg) |
|---|---|--:|--:|--:|
| `tds.ckpt` | TDS (time-depth-separable conv) | 0.10 M | 0.310 | 15.1β16.2 |
| `sensingdynamics.ckpt` | SensingDynamics | 0.56 M | 0.308 | 15.1β16.2 |
| `neuropose.ckpt` | NeuroPose | 7.15 M | 0.308 | 15.1β16.2 |
| `cldm.ckpt` | Conditional Latent Diffusion (self-contained: both VAEs + U-Net) | 7.01 M | 0.440 | 16.8β17.6 |
| `emg_stats.npz` | per-channel EMG mean/std β **required for inference** | β | β | β |
Checkpoints are PyTorch-Lightning `.ckpt` files (`state_dict` +
`hyper_parameters`), loaded by the wrappers in the GitHub repo
(`RegressionModule` for the three baselines, `CLDMModule` for CLDM).
### `ablations/` β improvement-campaign checkpoints
Trained on an **8,000-recording subset** for speed, to ablate a modernized
training recipe (window-sampling fix, velocity + smoothness loss, EMG
augmentation, pose-sensitivity-weighted tendon loss, temporal architectures):
| File | Description | Params | val tendon RMSE | Ξ vs reference |
|---|---|--:|--:|--:|
| `tds_old.ckpt` | TDS, original recipe (reference) | 0.10 M | 0.3105 | β |
| `tds_new.ckpt` | TDS, new recipe + sensitivity weighting | 0.10 M | 0.3090 | β0.5% |
| `tds_new_nosens.ckpt` | TDS, new recipe, no sensitivity weighting | 0.10 M | 0.3089 | β0.5% |
| `tcn_new.ckpt` | TCN (~2 s receptive field) | 1.57 M | 0.3057 | β1.5% |
| `gru_new.ckpt` | GRU velocity-decode (best) | 1.17 M | 0.3049 | β1.8% |
> **Use `ablations/emg_stats.npz` with these** β the normalization statistics
> were computed over the 8k subset and differ from the full-25k statistics at
> the root.
## Usage
```bash
git clone https://github.com/sagarverma/emg2tendon && cd emg2tendon
pip install torch pytorch-lightning hydra-core diffusers "numpy==1.26.4"
python - <<'PY'
from huggingface_hub import snapshot_download
print(snapshot_download("Micropilot/emg2tendon"))
PY
```
Then run the shipped eval / render entrypoints:
```bash
# pose-space evaluation (per-step + open-loop rollout through MyoHand)
python scripts/evaluate_pose.py --model tds --checkpoint tds.ckpt \
--index index.json --stats_cache emg_stats.npz
# side-by-side MuJoCo video (reference vs achieved pose)
MUJOCO_GL=egl python scripts/render_model.py --model tds --checkpoint tds.ckpt \
--emg emg/<base>.npy --pose pose/<base>.npy --index index.json \
--stats_cache emg_stats.npz --out out.mp4
```
Inference contract: EMG is per-channel standardized with the shipped
`mean`/`std` (`(emg - mean) / std`, guarding `std < 1e-8`); tendon output stays
in native `[0, 1]` space and is never normalized. Tensors are channel-first
(`[N, C, T]`) at the module boundary β see `CONTRACT.md` in the code repo.
## Evaluation
Protocol: the three held-out emg2pose generalization conditions (unseen **user**,
unseen **stage**, **user+stage**), 200 recordings per condition. Predicted
tendon controls are forward-simulated through MyoHand and the achieved pose is
compared to the emg2pose ground truth, both **per-step** and in a **0.5 s
open-loop rollout**.
| Model | per-step (deg) | open-loop 0.5 s (deg) |
|---|--:|--:|
| *ground-truth tendon (ID ceiling)* | *0.11* | *~14.0* |
| TDS / SensingDynamics / NeuroPose | ~0.09 | **15.1β16.2** |
| CLDM | ~0.11 | 16.8β17.6 |
The inverse-dynamics step itself is near-exact (0.109Β° MAE per-step over all
25,253 recordings), so per-step numbers sit at the ID ceiling for every model.
### Limitations
- **The open-loop ceiling is ~14Β°**: even perfect tendon controls drift under
MyoHand muscle dynamics. The baselines are already within ~1β2Β° of it, so
there is little headroom for a better EMGβtendon model to improve open-loop
pose β these baselines are near-optimal for this metric, not the bottleneck.
- **`cldm.ckpt` is undertrained** (diffusion stage cut short for compute
budget) and underperforms the regression baselines here β the opposite of the
paper's ranking. Treat it as a starting point, not a faithful CLDM result.
- Trained only on emg2pose (wrist-worn 16-ch sEMG band, right/left hand, seated
desk-scale gestures). No claims outside that distribution.
- Ablation checkpoints use an 8k subset and are not directly comparable to the
root full-25k checkpoints.
## License
`cc-by-nc-4.0`, inherited from the **emg2pose** dataset these models are trained
on (Meta, CC BY-NC 4.0). Non-commercial use only.
## Citation
```bibtex
@inproceedings{verma2025emg2tendon,
title = {{emg2tendon: From sEMG Signals to Tendon Control in Musculoskeletal Hands}},
author = {{Sagar Verma}},
year = 2025,
booktitle = {Robotics: Science and Systems}
}
```
|