Python Setup
cd wearable_har_v2
# Create virtual environment
uv venv .venv --python 3.12
# Install all dependencies
uv pip install -r requirements.txt
# Verify
.venv/bin/python -c "
from host.protocol import crc32, ACTIVITY_LABELS, PKT_STM32_SIZE
assert crc32(b'123456789') == 0xCBF43926, 'CRC32 check failed'
assert PKT_STM32_SIZE == 214, f'expected 214, got {PKT_STM32_SIZE}'
assert len(ACTIVITY_LABELS) == 11, f'expected 11 labels, got {len(ACTIVITY_LABELS)}'
print('OK — protocol module loaded, CRC verified,', len(ACTIVITY_LABELS), 'activity classes')
"
Dependencies
| Package |
Purpose |
numpy |
Numeric array operations |
torch |
PyTorch: model training + TorchScript inference |
pyserial |
Serial port access (CDC) |
h5py |
HDF5 recording format |
streamlit |
Dashboard UI |
scikit-learn |
LOSO cross-validation splits |
mkdocs-material |
Documentation site (dev dependency) |
wireviz |
Wiring diagram generation (dev dependency) |
diagrams |
Architecture diagram generation (dev dependency) |
Module overview
| Module |
Import |
Purpose |
protocol.py |
from host.protocol import ... |
Packet constants, CRC32, labels |
serial_reader.py |
from host.serial_reader import SerialReader |
Magic sync, CRC validate, parse |
feature_extraction.py |
from host.feature_extraction import FeatureExtractor |
2 s windows → 328-dim vectors |
data_recorder.py |
from host.data_recorder import DataRecorder |
HDF5 recording |
train_model.py |
python -m host.train_model ... |
BiLSTM-CNN training + export |
live_inference.py |
from host.live_inference import LiveClassifier |
TorchScript inference |
dashboard.py |
streamlit run host/dashboard.py |
Dashboard UI |
Quick verification (no hardware)
# Feature extractor correctness
.venv/bin/python -c "
from host.feature_extraction import FeatureExtractor
from host.serial_reader import SensorFrame, IMUData
ext = FeatureExtractor()
f = SensorFrame()
for i in range(6):
f.imus[i] = IMUData(q_w=1.0, az=9.81)
for _ in range(199):
ext.add_frame(f)
feats = ext.add_frame(f) # fills 200th frame → 2s window
print(f'Feature dim: {feats.shape[0]} (expected 328)')
assert feats.shape == (328,), f'FAIL: {feats.shape}'
print('OK')
"
# Train on synthetic data (2 epochs, smoke test)
.venv/bin/python -m host.train_model --synthetic --epochs 2 --output /tmp/test_model.pt
Directory layout after setup
wearable_har_v2/
├── .venv/
├── host/
│ ├── protocol.py
│ ├── serial_reader.py
│ ├── feature_extraction.py
│ ├── data_recorder.py
│ ├── train_model.py
│ ├── live_inference.py
│ └── dashboard.py
├── models/ # created after training
├── recordings/ # created after recording
├── tests/
└── docs/