Implementation Design Hints
This page gives implementation hints for the final project. You will not receive a complete final-project codebase. Instead, use the previous labs as references and build your own system around a clean structure.
Recommended Code Structure
Recommended starting structure:
final_project/
README.md
src/
collect.py
combine_datasets.py
extract_features.py
train.py
evaluate.py
realtime_demo.py
sensors/
base_reader.py
imu_reader.py
uwb_reader.py
mmwave_reader.py
wifi_reader.py
rfid_reader.py
data/
raw/
processed/
models/
results/
figures/
Good references from previous labs:
| Prior lab | Useful idea to reuse |
|---|---|
| IMU lab | Serial streaming, motion windows, smoothing, wearable placement |
| WiFi lab | Multi-device setup, CSI stream parsing, environment sensitivity |
| UWB lab | Trial-based collection, dataset folders, training and realtime evaluation |
| mmWave lab | Background subtraction, range profile features, point-cloud features |
Data Collection Design
The most important part of the final project is not the classifier. It is collecting data in a way that makes the classification problem meaningful.
Use a coordinator-based design:
start all sensor streams
record trial_start event timestamp
record trial_end event timestamp
ask whether to accept or reject the trial
save all raw data and event markers
segment the trials offline
The coordinator should own the official experiment clock. Use time.monotonic() in Python for timestamps. Do not try to make every sensor physically start at the exact same instant. Instead, start all sensors first, timestamp every sample on the laptop, and use event markers to cut the data into trials.
Recommended Data Model
Each collection session should create one folder:
data/raw/session_20260722_153012/
session_metadata.json
events.csv
trials.csv
imu.csv
uwb.csv
mmwave.csv
wifi.csv
Example events.csv:
time_s,event,trial_id,gesture,collector,notes
0.000,session_start,,,,
6.231,trial_start,student01_pull_001,pull,student01,
9.231,trial_end,student01_pull_001,pull,student01,
Example sensor file:
time_s,sensor,ax,ay,az,gx,gy,gz
6.245,imu,0.01,-0.02,0.98,0.1,0.2,-0.1
6.266,imu,0.02,-0.01,0.99,0.0,0.3,-0.2
After collection, compute trial-relative time offline:
trial_data = sensor_data[
(sensor_data["time_s"] >= trial_start_time) &
(sensor_data["time_s"] <= trial_end_time)
].copy()
trial_data["t_trial_s"] = trial_data["time_s"] - trial_start_time
Sensor Reader Interface
Each sensor reader should hide sensor-specific details from collect.py.
Suggested interface:
class SensorReader:
def start(self, session_dir, session_t0):
...
def stop(self):
...
def close(self):
...
Each reader writes timestamped samples using the same session clock:
t = time.monotonic() - session_t0
Then collect.py can treat IMU, UWB, mmWave, WiFi, and RFID streams in the same way.
Gesture Protocols
For the required system, use a standard 3-second gesture action window. This keeps data collection, feature extraction, and realtime evaluation simple.
Default trial timing:
1 s prepare
1 s rest baseline
3 s gesture action
1 s cooldown
This works only if the gesture timing is controlled. For one-shot gestures, perform the action once near the center of the 3-second action window. For repeated gestures, repeat naturally throughout the 3-second action window.
Discrete One-Shot Gestures
Examples:
- Pull
- Push
- Left
- Right
- Clockwise
- Anti-clockwise
Collect these as separate trials. Do not continuously repeat pull/push for a long recording, because the transitions may blend together and confuse the model.
Continuous or Periodic Gestures
Examples:
- Clapping
- One-Arm Boxing
- Two-Arm Boxing
- Bye-Bye
- Making Fist and Open
- Palm Up-Down
For these gestures, repeat the motion naturally during the 3-second action window. If your group wants to collect longer continuous recordings, you must be careful during evaluation: split train/test by full recording or by collector, not by overlapping windows from the same recording.
Example Config File
You can use a config file so you can change sensors, gestures, and durations without editing code.
Example configs/imu_uwb.yaml:
session_name: imu_uwb_gesture_test
sensors:
- imu
- uwb
timing:
duration: 3.0
collection:
trials_per_gesture: 8
require_accept: true
gestures:
pull:
type: discrete
push:
type: discrete
clapping:
type: periodic
...
ports:
imu: /dev/cu.usbserial-IMU
uwb_controller: /dev/cu.usbmodemCONTROLLER
uwb_controlee: /dev/cu.usbmodemCONTROLEE
Windows groups can use COM ports in the same file:
ports:
imu: COM5
uwb_controller: COM7
uwb_controlee: COM8
Desired Command-Line Workflow
Your exact commands may differ, but your project should support a similar workflow.
Check that selected sensors can stream and save:
python src/collect.py --config configs/imu_uwb.yaml --smoke-test --duration 10
Collect a small two-gesture dataset first:
python src/collect.py \
--config configs/imu_uwb.yaml \
--collector student01 \
--gestures pull,push \
--trials 3
Collect the main dataset:
python src/collect.py \
--config configs/imu_uwb.yaml \
--collector student01 \
--gestures pull,push,left,right,clapping,t_arm \
--trials 8
Combine datasets from group members:
python src/combine_datasets.py \
data/raw/session_student01 \
data/raw/session_student02 \
data/raw/session_student03 \
data/raw/session_student04 \
--output data/processed/combined_group_dataset
Extract features:
python src/extract_features.py \
data/processed/combined_group_dataset \
--window-s 3.0 \
--output data/processed/features_3s.csv
Train and evaluate:
python src/train.py data/processed/features_3s.csv --classifier random_forest
python src/evaluate.py models/random_forest_YYYYMMDD_HHMMSS.joblib --split by_collector
Run a realtime demo:
python src/realtime_demo.py \
--config configs/imu_uwb.yaml \
--model models/random_forest_YYYYMMDD_HHMMSS.joblib \
--window-s 3.0 \
--vote-window 5
Development Roadmap
Build the system step by step.
- Start one sensor and save raw data.
- Start two sensors at the same time and save both streams.
- Add
events.csvand verify trial markers. - Implement one discrete gesture, such as
pull. - Collect two gestures and train a first classifier.
- Add the second sensor features.
- Compare single-sensor baseline vs fused model.
- Add more gestures.
- Add realtime prediction with majority voting.
- Prepare the poster and demo.