SDP: Sensing Data Protocol for Scalable Wireless Sensing
Published and maintained by SDP8.org โ the official platform for reproducible wireless sensing.
๐ Citation
If you use SDP in your research, please cite:
@ARTICLE{11652923,
author={Zhang, Di and Huang, Jiawei and Cui, Yuanhao and Cao, Xiaowen and Han, Tony Xiao and Jing, Xiaojun},
journal={IEEE Transactions on Mobile Computing},
title={SDP: A Unified Protocol and Benchmarking Framework for Reproducible Wi-Fi Sensing},
year={2026},
volume={},
number={},
pages={1-14},
keywords={Wireless fidelity;Modeling;Frequency;Protocols;Training;Streams;Accuracy;Measurement;Tensors;Antennas;Benchmark;canonical representation;channel state information (CSI);integrated sensing and communications (ISAC);reproducibility;wireless sensing},
doi={10.1109/TMC.2026.3723025}}
๐ What's New in v0.5.2
- Modular algorithm pipeline -- freely compose preprocessing steps with
AlgorithmStepandexecute_algorithm_steps() - Pluggable readers -- bring your own file-format reader via
register_reader()andpipeline(..., reader=)(CLI--reader) - Per-dataset pipeline presets --
widar,gait,xrf55,elderAL,ztevia--algorithm-preset - Compatibility & stability fixes -- clearer errors when an algorithm doesn't support a dataset, checkpoint always saved, Python 3.9 fix, XRF55 subset split fix
๐ฏ What is SDP?
SDP is a protocol-level abstraction and unified benchmark for reproducible wireless sensing.
โ ๏ธ SDP is not a new neural network, but a standardized protocol that unifies CSI representations for fair comparison.
๐ Why Choose WSDP?
| Capability | WSDP | SenseFi (2023) | CSIKit |
|---|---|---|---|
| Built-in Models | 19 (MLPโMamba/GNN) | 11 (MLPโViT) | โ |
| Preprocessing Algorithms | 26+ (Wavelet, STC, etc.) | โ | Basic |
| Datasets | 5 | 4 | โ |
| Pluggable Architecture | โ Registry | โ | โ |
| Protocol Abstraction | โ Unique | โ | โ |
| Training Pipeline | โ | โ | โ |
| CLI | โ Full | Basic | โ |
Verified from official GitHub repos on 2026-03-17.
๐ง Model Zoo (19 Models, Baseline โ SOTA)
| Category | Models | Use Case |
|---|---|---|
| Baseline | MLP, CNN1D, CNN2D, LSTM | Quick experiments, comparisons |
| Mainstream | ResNet1D, ResNet2D, BiLSTM+Attn, EfficientNet | Production use |
| SOTA | ViT, Mamba, GNN, CSIModel | Cutting-edge research |
| Specialized | THAT, CSITime, PA_CSI | Task-specific architectures |
| Lightweight | WiFlexFormer, AttentionGRU | Efficient deployment |
| Cross-Domain | EI, FewSense | Domain adaptation & few-shot |
from wsdp.models import create_model, list_models
model = create_model("ResNet1D", num_classes=10, input_shape=(20, 30, 3))
โ ๏ธ Baseline Model Architecture Note
Baseline models (MLP, CNN1D, CNN2D, LSTM) use a Spatial Encoder (Conv2d-based) to compress the
(F, A)antenna dimension before temporal processing. This prevents parameter explosion from direct(T, F, A)flattening. SeeCHANGELOG.mdfor details.
๐งช Algorithm Library (26+ Algorithms in 7 Categories)
| Category | Algorithms | Count |
|---|---|---|
| Denoising | Wavelet, Butterworth, Savitzky-Golay, Bandpass, Hampel | 5 |
| Phase Calibration | Linear, Polynomial, STC, Robust | 4 |
| Amplitude | Z-Score, Min-Max, IQR Outlier, AGC Compensation | 4 |
| Interpolation | Linear, Cubic, Nearest, Anti-alias Decimate | 4 |
| Features | Doppler, Entropy, CSI Ratio, Tensor, Conjugate Multiply, PCA Fusion | 6 |
| Detection | Variance, Change Point | 2 |
| Composition | Pipeline presets, YAML config | - |
from wsdp.algorithms import denoise, calibrate, normalize
denoised = denoise(csi, method='butterworth', order=5, cutoff=0.3)
calibrated = calibrate(csi, method='stc')
See Model Guide and Algorithm Guide.
๐ฏ What is SDP? (Cont.)
The Problem
Wireless sensing research often suffers from:
- โ Hardware-specific CSI formats
- โ Inconsistent preprocessing pipelines
- โ Unstable training results
- โ Large performance variance across random seeds
Result: Models cannot be fairly compared.
The Solution
SDP solves this at the protocol level, not the model level:
| Feature | Raw CSI | Other Tools | SDP |
|---|---|---|---|
| Standardized Format | โ Hardware-specific | โ ๏ธ Partial | โ Unified CSIFrame |
| Multi-Dataset Support | โ Manual parsing | โ ๏ธ 2-3 datasets | โ 5 datasets built-in |
| Preprocessing | โ DIY | โ ๏ธ Basic only | โ Wavelet + Phase Calib |
| Reproducibility | โ Random | โ ๏ธ Varies | โ 5-seed standard |
| Deep Learning | โ From scratch | โ ๏ธ Limited | โ CNN+Transformer |
| CLI Interface | โ None | โ ๏ธ Partial | โ Full CLI support |
SDP projects raw CSI into a fixed canonical frequency grid (K=30), ensuring cross-hardware comparability.
Performance Highlights
| Metric | Result |
|---|---|
| Accuracy | SOTA on 5 datasets |
| Reproducibility | 5-seed evaluation standard |
| Stability | Low variance across runs |
Figure 1: Accuracy comparison across datasets
Figure 2: Reproducibility and stability analysis
Figure 3: Ablation study results
๐ Quick Start (3 Steps, 5 Minutes)
Step 1: Install (30 seconds)
pip install wsdp
Verify installation:
wsdp --version
Step 2: Download Dataset (2 minutes)
๐ Required: Create a free account at SDP8.org โ your account credentials are needed for dataset downloads.
๐ VPN is recommended for downloading datasets.
Option A: From CLI (Recommended for testing)
All datasets hosted on SDP8.org:
# elderAL = smallest dataset, fastest for testing
# Use your SDP8.org email/password:
wsdp download elderAL ./data --email you@example.com --password yourpassword
# Or use a JWT token (from SDP8.org dashboard):
wsdp download elderAL ./data --token YOUR_JWT_TOKEN
# Download larger datasets:
# wsdp download widar ./data
# wsdp download gait ./data
# wsdp download xrf55 ./data
# wsdp download zte ./data --email you@example.com --password yourpassword
# โ ๏ธ zte requires applying for access on the SDP platform first
Option B: From SDP8.org Web Interface
Log in at sdp8.org and download datasets manually.
Required Dataset Structure:
data/
โโโ elderAL/ # Dataset name
โ โโโ action0_static_new/ # Activity folder
โ โ โโโ user0_position1_activity0/ # Sample folder
โ โ โ โโโ sample1.csv
โ โ โ โโโ ...
โ โ โโโ ...
โ โโโ action1_walk_new/
โ โโโ ...
โโโ widar/
โ
โโโ gait/
โ
โโโ xrf55/
โ โโโ WIFI/
โ โโโ sample.npy
โโโ zte/
Step 3: Train & Evaluate (2 minutes)
๐ Python API (Recommended for research):
Create train.py:
from wsdp import pipeline
# Minimal call - uses default hyperparameters
pipeline("./data/elderAL", "./output", "elderAL")
# Or with custom hyperparameters
pipeline(
input_path="./data/elderAL",
output_folder="./output",
dataset="elderAL",
learning_rate=1e-3,
num_epochs=50,
batch_size=64,
)
Run:
python train.py
๐ป CLI (Quick & Simple):
# Basic training
wsdp run ./data/elderAL ./output elderAL
# With hyperparameter override
wsdp run ./data/elderAL ./output elderAL --lr 0.001 --epochs 50 --batch-size 64
# With hyperparameter config file (YAML, top-level key = dataset name)
wsdp run ./data/elderAL ./output elderAL --config my_config.yaml
# Swap the model: a registered model name, or your own .py file
wsdp run ./data/elderAL ./output elderAL --model THAT
wsdp run ./data/elderAL ./output elderAL -m custom_model.py
# Custom preprocessing: algorithm config (YAML/JSON) or a preset
wsdp run ./data/elderAL ./output elderAL --algorithm-config my_algorithms.yaml
wsdp run ./data/elderAL ./output elderAL --algorithm-preset high_quality
๐ What You Get:
After training, check ./output/ (one set of files per random seed, 5 seeds by default):
output/
โโโ best_checkpoint_<seed>.pth # Best model checkpoint for each seed
โโโ training_history_<seed>.csv # Per-epoch loss & accuracy for each seed
โโโ cm_rs_<seed>.png # Confusion matrix for each seed
Mean and variance of Top-1 accuracy across seeds are printed to the console at the end.
โ If you see these files, SDP is working correctly!
๐ Supported Datasets
| Dataset | Format | Subcarriers | Complex | Scenarios | Size |
|---|---|---|---|---|---|
| Widar | .dat (bfee) | 30 | โ | Gesture recognition | ~2GB |
| Gait | .dat (bfee, Intel IWL5300) | 30 | โ | Gait recognition | ~1GB |
| XRF55 | .npy | 30 | โ | Human activity | ~3GB |
| ElderAL | .csv | varies | โ | Elderly activity | ~500MB |
| ZTE | .csv | 512 | โ | CSI with I/Q | ~4GB |
More datasets coming soon!
๐ฌ Research & Customization
๐ง Plug in Your Own Model
Step 1: Create custom_model.py:
import torch
import torch.nn as nn
class YourCustomModel(nn.Module):
def __init__(self, num_classes=6):
super().__init__()
# Your architecture here
# Input shape: (Batch, Timestamp, Frequency, Antenna)
def forward(self, x):
# Your forward pass
return output
# Required: expose model class
model = YourCustomModel
Step 2: Run with your model:
wsdp run ./data/elderAL ./output elderAL -m custom_model.py
๐ Use Your Own Dataset
Labels and split groups are parsed from filenames, so name your files after
one of the built-in dataset conventions (e.g. XRF55 user_action_trial) and pass
that dataset name. If your files use a custom format, register a reader for it:
from wsdp import pipeline
from wsdp.readers import BaseReader, register_reader
class MyReader(BaseReader):
def sniff(self, file_path): return file_path.endswith(".myfmt")
def read_file(self, file_path): ... # parse the file into CSIData
register_reader("my_format", MyReader)
# Filenames follow the XRF55 convention -> dataset="xrf55" + custom reader for the format
pipeline("./data/my_dataset", "./output", "xrf55", reader="my_format")
End-to-end example: examples/scripts/custom_reader_algorithm.py.
๐บ๏ธ Codebase Map
Want to go deeper? Here's where to modify:
| Directory | Purpose | What to Modify |
|---|---|---|
models/ |
Architectures | Define or compare model architectures |
algorithms/ |
Signal Processing | Denoising, calibration, etc. |
datasets/ |
Dataset Wrappers | Add new dataset loaders |
readers/ |
File Readers | Add new format parsers |
structure/ |
Data Structures | Modify CSIFrame format |
processors/ |
Protocol Logic | Adjust canonical projection |
๐ Pluggable Algorithm Architecture
WSDP features a Registry Pattern that makes algorithms pluggable:
from wsdp.algorithms import denoise, calibrate, register_algorithm
# Unified API โ switch methods with one parameter
denoised = denoise(csi, method='butterworth', order=5)
calibrated = calibrate(csi, method='stc')
# Register your own algorithm
def my_denoise(csi, **kwargs):
return my_custom_filter(csi)
register_algorithm('denoise', 'my_method', my_denoise)
result = denoise(csi, method='my_method') # Works like built-in!
You can try this in examples/getting_started.ipynb or just in your custom pipeline!
Configuration file support:
# examples/configs/algorithms_config.yaml
denoise:
method: butterworth
params:
order: 5
cutoff: 0.3
calibrate:
method: stc
normalize:
method: z-score
from wsdp.algorithms import load_config, execute_pipeline
config = load_config('examples/configs/algorithms_config.yaml')
processed = execute_pipeline(csi, config)
Or:
pipeline(
"./data/elderAL",
"./output",
"elderAL",
algorithm_config_file='./examples/configs/algorithms_config.yaml',
)
Pipeline presets:
from wsdp.algorithms import apply_preset, execute_pipeline
# Choose a preset for your use case
steps = apply_preset('high_quality') # or 'fast', 'robust', etc.
processed = execute_pipeline(csi, steps)
Modular pipeline (compose or skip steps freely):
from wsdp.algorithms import AlgorithmStep
from wsdp.processors import ModularProcessor
steps = [
AlgorithmStep(category="denoise", method="wavelet", params={"level": 2}),
AlgorithmStep(category="normalize", method="z-score"), # calibration skipped
]
data, labels, groups = ModularProcessor(steps).process(csi_data_list, dataset="xrf55")
Config-file form: examples/configs/modular_pipeline.yaml.
๐ Algorithm Library
| Category | Algorithm | Key Function | Reference |
|---|---|---|---|
| Denoising | Wavelet | wavelet_denoise_csi() |
Donoho & Johnstone, 1994 |
| Butterworth | butterworth_denoise() |
Butterworth, 1930 | |
| Savitzky-Golay | savgol_denoise() |
Savitzky & Golay, 1964 | |
| Bandpass | bandpass_filter() |
Standard DSP | |
| Hampel | hampel_filter() |
Hampel, 1974 | |
| Phase Calibration | Linear | phase_calibration() |
Halperin et al., 2010 |
| Polynomial | polynomial_calibration() |
Extension of linear | |
| STC | stc_calibration() |
Xie et al., IEEE TWC 2019 | |
| Robust | robust_phase_sanitization() |
Wang et al., ICPADS 2012 | |
| Normalization | Z-Score | normalize_amplitude() |
Standard statistical |
| Min-Max | normalize_amplitude() |
Standard statistical | |
| AGC Compensation | agc_compensate() |
AGC gain correction | |
| Interpolation | Linear/Cubic/Nearest | interpolate_grid() |
de Boor, 1978 |
| Anti-alias Decimate | decimate() |
Anti-alias downsampling | |
| Features | Doppler | doppler_spectrum() |
Ali et al., MobiCom 2015 |
| Entropy | entropy_features() |
Shannon, 1948 | |
| CSI Ratio | csi_ratio() |
Halperin et al., 2011 | |
| Tensor Decomposition | tensor_decomposition() |
Kolda & Bader, SIAM 2009 | |
| Conjugate Multiply | conjugate_multiply() |
Antenna pair correlation | |
| PCA Fusion | pca_fusion() |
Dimensionality reduction | |
| Detection | Activity | detect_activity() |
Zhou et al., 2013 |
| Change Point | change_point_detection() |
Adams & MacKay, 2007 |
Built-in Presets:
| Preset | Denoise | Calibrate | Use Case |
|---|---|---|---|
high_quality |
Butterworth (order=5) | STC | Maximum accuracy |
fast |
Savitzky-Golay | Linear | Speed-optimized |
robust |
Wavelet | Robust | Noisy environments |
gesture_recognition |
Butterworth (order=4) | STC | Gesture tasks |
activity_detection |
Savitzky-Golay | Polynomial | HAR tasks |
localization |
Wavelet | Robust | Localization tasks |
Per-dataset presets (
widar,gait,xrf55,elderAL,zte) are also available; they currently mirror the legacy default chain (linear calibration
- wavelet denoise).
๐งช Understanding SDP (10-Min Deep Dive)
The SDP Pipeline
Raw CSI
โ
[Deterministic Sanitization]
- Phase calibration
- Wavelet denoising
โ
[Canonical Tensor Construction]
- K=30 frequency grid
- Standardized shape
โ
[Deep Learning Model]
โ
Prediction
Canonical Tensor Format
After sanitization, SDP constructs a Canonical CSI Tensor:
$$X \in \mathbb{C}^{A \times K \times T}$$
Where:
- $A$ = Number of antennas
- $K$ = 30 (fixed frequency grid)
- $T$ = Time samples
This ensures cross-hardware comparability.
Why Deterministic?
Raw CSI contains hardware distortions:
- Phase offsets
- Sampling time offsets
- Noise fluctuations
SDP enforces deterministic calibration and denoising, guaranteeing:
- โ Same raw CSI โ Same cleaned tensor
- โ Reproducibility is enforced, not optional
๐ Documentation & Resources
๐ Tutorials (Recommended Order)
| # | Resource | What You'll Learn |
|---|---|---|
| 1 | Quickstart Notebook | 5-min intro โ registry exploration & processor customization |
| 2 | Getting Started Notebook | Algorithm deep-dive โ phase calibration & denoising with step-by-step visualizations |
| 3 | Full Tutorial Notebook |
End-to-end workflow โ install โ preprocess โ train โ evaluate โ CLI |
๐ User Guide
| Resource | Description |
|---|---|
| Installation | Setup & environment configuration |
| Quickstart Guide | First steps with WSDP |
| Algorithm Guide | How to choose and chain preprocessing algorithms |
| Python API | Programmatic usage in detail |
| CLI Reference | Command-line interface usage |
| Configuration | YAML config files & pipeline presets |
๐ Reference
| Resource | Description |
|---|---|
| Full Documentation Site | Complete MkDocs documentation |
| API Reference | All public APIs |
| Dataset Overview | Format details & download guide for all 5 datasets |
| Model Guide | All 19 models with architecture details |
| Leaderboard | Benchmark comparison across models & datasets |
| Changelog | Version history |
| Contributing | Development guide & PR process |
๐บ๏ธ Roadmap
- v0.1 - Initial protocol design
- v0.2 - 5 datasets support, CLI tool
- v0.3 - More datasets (WiFi-HAR, CSI-HAR, etc.)
- v0.4 - 19 models, 26+ algorithms, leaderboard, CI/CD, scientific bug fixes
- v0.5 - PyPI official release, online demo platform
- v1.0 - Full protocol standardization
Want a specific dataset? Open an issue and let us know!
๐ค Contributing
We welcome contributions! See CONTRIBUTING.md for:
- Development setup
- Coding guidelines
- Pull request process
๐ License
MIT License - see LICENSE file.
Made with โค๏ธ by the WSDP Team
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wsdp-0.5.2.tar.gz.
File metadata
- Download URL: wsdp-0.5.2.tar.gz
- Upload date:
- Size: 108.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
438a4b279b4e90695b2635e995eff2d2826f744226741b597bea8580dc7bb78a
|
|
| MD5 |
68f20b4ac1490da9ebdfcc87f5c2ca6f
|
|
| BLAKE2b-256 |
7c91227cfdfcdddf84489a152142e5ce27577026b4abc10fd2f8c66cbe6f04a3
|
File details
Details for the file wsdp-0.5.2-py3-none-any.whl.
File metadata
- Download URL: wsdp-0.5.2-py3-none-any.whl
- Upload date:
- Size: 118.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60843a40ab367bfd1c0281ee0d9cbfc5d945992006837d68d6bf32bfe3a0cb63
|
|
| MD5 |
1087a90ecea9f7c1122c2baca0a8be23
|
|
| BLAKE2b-256 |
2bb8825e8404ebb16bf6952def8be4aa237b7c3a70457796f1f699926458c1e8
|