OFDM-Sense is a Joint Communication and Sensing (JCAS) research platform developed as the 2025/26 URI ELECOMP Capstone project under Dr. Guoyi Xu. It implements an OFDM transceiver on a USRP X310 software-defined radio (SDR) to explore the use of OFDM waveforms for simultaneous wireless communication and device localization via time-difference-of-arrival (TDOA).
Our paper, "2D Localization Leveraging OFDM Signals," has been accepted for publication in the 2026 IEEE ORSS proceedings.
O'Malley Sherlock*, Royaljohn Southamavong*, and Guoyi Xu, "2D Localization Leveraging OFDM Signals," in 2026 IEEE ORSS, 2026. (to appear)
A link will be added once available.
- Publication
- How it Works
- Prerequisites
- Installation
- Configuration
- Workflow
- Localization Experiments
- Simulation
- Project Structure
A transmitter sends an OFDM packet (preamble + data symbols) from a USRP X310. One or more receivers capture the signal. The receiver pipeline:
- Synchronization Schmidl-Cox algorithm detects packet start and estimates coarse CFO
- Channel estimation pilot symbols estimate frequency-domain channel response
- Equalization & demodulation 16-QAM symbols are recovered and evaluated (EVM, BER, SER)
- Delay estimation matched filter + sub-sample interpolation measures propagation delay
- Localization TDOA across multiple receivers feeds a least-squares multilateration solver
- USRP X310
- External 10 MHz reference clock (shared across all devices for synchronization)
- 10 GbE connection per USRP
- Python >= 3.8
- UHD (USRP Hardware Driver) required to build the C++ control binary
- CMake >= 3.8 and a C++14 compiler
git clone https://github.com/osherlock1/OFDM-Sense.git
cd OFDM-Sensemkdir build && cd build
cmake ..
make
cd ..This produces build/TXRX_FROM_FILE, which the Python scripts call via subprocess.
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtpytestCopy and edit this file to match your hardware setup:
build_path: "./build/TXRX_FROM_FILE"
tx_addr: "addr0=192.168.30.2,addr1=192.168.40.2"
rx_addr: "addr0=192.168.30.2,addr1=192.168.40.2"
subdev: "A:0 B:0"
tx_channel_idx: "1"
rx_channel_idx: "0,1,2"
tx_rate: 100e6
rx_rate: 100e6
tx_freq: 60e6
rx_freq: 60e6
tx_gain: 0
rx_gain: 0
ref: "external" # external 10 MHz reference clockUpdate tx_addr / rx_addr to match your USRP IP addresses. The ref: "external" field requires a shared 10 MHz clock source connected to all devices.
# Generate a synthetic OFDM packet with noise
python scripts/generate_packet.py --n_symb 30 --snr 20
# Unpack and evaluate
python scripts/unpack_rx.py --sim --plot# 1. Generate the transmit packet
python scripts/generate_packet.py --n_symb 30
# 2. Verify the USRP is reachable (sends a sine wave and checks CFO)
python scripts/test_sin_wave.py
# 3. Run the transfer
python scripts/run_transfer.py
# 4. Unpack and evaluate the received signal
python scripts/unpack_rx.py --plotSee scripts/experiment_scripts/README.md for a full tutorial. The short version:
# 1. Edit EXPERIMENT_NAME, ROAMING_DEVICES, FIXED_DEVICES at the top of collect_raw_data.py
# 2. Collect data (prompts for device positions)
python scripts/experiment_scripts/collect_raw_data.py --runs 5 --experiments_dir ./experiments
# 3. Process raw .dat files into CSV
python scripts/experiment_scripts/process_experiment.py --experiment_pth ./experiments/my_experiment
# 4. Run multilateration
python scripts/localization/multilateration.py --experiment ./experiments/my_experiment --devices RX3ch1 --anchor ANCHORch0Run a Monte Carlo TDOA localization simulation without any hardware:
python scripts/simulation/monte_carlo.py --sigma-ns 0.1 --trials 1000The simulation uses an interactive drag-and-drop UI to reposition TX and RX nodes and recompute localization error in real time.
OFDM-Sense/
├── src/ofdm/ # Installable Python library
│ ├── core/ # Waveform, preamble, payload construction
│ ├── channel/ # Channel estimation, CFO correction, delay
│ ├── modulation/ # 16-QAM
│ ├── processing/ # RX pipeline, batch processing
│ ├── simulation/ # TDOA geometry, solver, Monte Carlo
│ ├── utils/ # USRP config, data generation, evaluation
│ ├── viz/ # Plotting utilities
│ └── config.py # OFDMConfig dataclass (N=256, CP=64, Fs=100MHz)
├── scripts/ # Runnable entry-point scripts
│ ├── experiment_scripts/ # Data collection and processing workflows
│ ├── localization/ # Multilateration
│ ├── simulation/ # Monte Carlo simulation
│ ├── delay/ # Delay estimation and calibration
│ └── image_demo/ # Image transmission demo
├── usrp_control_files/ # C++ UHD driver source
├── tests/ # pytest test suite
├── configs/ # YAML hardware configuration
├── data_files/ # Reference packet data
├── notebooks/ # Analysis notebooks
└── CMakeLists.txt # C++ build system
