aerial-isac-srs-iq
收藏资源简介:
# Aerial ISAC SRS I/Q Raw uplink **Sounding Reference Signal (SRS) I/Q** captured on the [NVIDIA Aerial](https://developer.nvidia.com/industries/telecommunications/ai-aerial) 5G testbed, paired with a synchronized video and camera-derived ground truth for two pedestrians and a car moving through the sensing area. <div align="center"> <img src="assets/isac_rd_demo.webp" alt="Camera, Range-Doppler map, and ground-truth tracks" width="100%"><br> <em>The labeled span in real time: camera view, Range-Doppler map, and range/velocity tracks. Also available as <a href="https://huggingface.co/datasets/nvidia/aerial-isac-srs-iq/resolve/main/assets/isac_rd_demo.mp4">isac_rd_demo.mp4</a>.</em> </div> ## Dataset Description: This dataset provides synchronized multi-modal recordings designed for Integrated Sensing and Communication (ISAC) research. It comprises uplink Sounding Reference Signal (SRS) I/Q data captured by a private 5G base station, a synchronized video of the capture, and labels for the moving targets. Recorded in an outdoor parking lot environment, the scene features two walking pedestrians and a moving vehicle. This collection serves as a reference and evaluation tool rather than a training dataset and is not intended for individual identification. The capture is *bistatic and UE-collaborative*: a commercial UE transmits SRS, which is received by a spatially separated O-RU. The targets carry no radio of their own and are detected from the changes they create in the RF environment between the UE transmitter and the O-RU receiver. **Repository structure** ``` data/aerial-isac-srs-iq-001/ ├── srs_iq.trace 9.9 GiB raw SRS I/Q, E3 replay trace format ├── video.mp4 41 MiB synchronized camera view ├── ground_truth.json 239 KiB labels, grouped by processing window ├── ground_truth.jsonl 211 KiB the same labels, one row per object ├── image_labels.json 1.0 MiB camera detections per video frame, in pixels ├── video_sync.json 781 KiB video frame <-> SRS record map └── metadata.json 3.6 KiB machine-readable run summary assets/ figures used by this page ``` This dataset is ready for commercial or non-commercial uses. ## Dataset Owner(s): NVIDIA Corporation ## Dataset Creation Date: 2026-07-16 ## Version: 1.0.0 Previous Version(s): N/A ## License/Terms of Use: Creative Commons BY 4.0. See the [LICENSE](LICENSE) file for the full terms. ## Intended Usage: Developing and benchmarking ISAC receiver algorithms: SRS channel estimation, clutter suppression, Range-Doppler and power-delay-profile processing, detection and tracking, bistatic localization, and multi-modal fusion of the radio and the camera. It also gives simulated ISAC scenes a measured counterpart. Not intended for identifying individuals. ## Dataset Characterization **Data Collection Method** Hybrid: Automatic/Sensors/Manually Collected **Labeling Method** Hybrid: Automated, Manually-Labelled Radio and video were recorded simultaneously on an NVIDIA campus parking area. The transmitter is an unmodified Samsung S22 handset sounding the uplink exactly as any commercial phone would; the receiver is a WNC 4T4R O-RU feeding NVIDIA Aerial CUDA-Accelerated RAN L1, with OpenAirInterface running L2/L3. The SRS I/Q is tapped inside L1 and written to the trace through the E3 agent, so these are the same samples the physical layer used to serve the call. Ground truth comes from an iPhone 14 Pro recording the scene. | Acquisition | | |---|---| | Waveform | 5G NR uplink SRS, band n48 at 3.62499 GHz, 97.92 MHz (272 PRB, 30 kHz SCS) | | Capture | 33,148 SRS records over 84.985 s, one every 2.5 ms | | Hardware | Samsung S22 UE, WNC 4T4R O-RU, NVIDIA GH200 server, single cell | | Platform | NVIDIA Aerial Testbed 1.1: Aerial CUDA-Accelerated RAN 26-1.2 L1, OpenAirInterface L2/L3 | | Geometry | Bistatic, UE-collaborative, 5.79 m baseline, targets 7.5 m to 33 m from the radios | | Motion | Labels span -3.1 to 4.5 m/s, against a maximum unambiguous velocity of 8.29 m/s | | Video | 1280x720 at 59.96 fps, 84.2 s, faces and plates blurred, burned-in timestamp and NVIDIA watermark, no audio | Labels are camera-derived, not radar-derived, so they are independent of any sensing algorithm benchmarked against them. An open-source YOLO detector and tracker was run over the video, image coordinates were projected onto the ground plane through a homography of the manually surveyed quad, and every target class was checked by hand. Two open-source models were used as internal tools only, and neither their code nor their weights is redistributed here: Ultralytics YOLO11-small for person and vehicle detection ([AGPL-3.0](https://github.com/ultralytics/ultralytics)), and the YOLOv9-based plate detector shipped with [open-image-models](https://github.com/ankandrew/open-image-models) (MIT) for the blurring pass. What is published is their numeric output: bounding boxes, class names and track indices. ## Dataset Format Modality: Radio I/Q samples, Video, Structured labels (JSON/JSONL) Format: Custom NVIDIA binary trace format, MP4 (H.264), JSON, JSONL Per-file sizes and roles are listed under Repository structure above; the trace layout is specified in Trace format below. ## Dataset Quantification Record Count: 33,148 SRS records (9.9 GiB of complex fp16 I/Q); 5,048 video frames; 569 object instances across 472 label windows; 4,108 camera detections across 3,495 frames; 2 pedestrians and 1 car Feature Count: Labels include target classification, track ID, bistatic range, radial velocity, frame number, SRS record range, ground position, image position, detector confidence, and a reference tracker estimate Total Data Storage: ~10.7 GB ## Getting started ```bash pip install -U "huggingface_hub[cli]" hf download nvidia/aerial-isac-srs-iq --repo-type dataset --local-dir aerial-isac-srs-iq ``` The labels are plain JSON and need no dependencies. Every example here, and in the sections that follow, abbreviates the run directory as `RUN`: ```python import json RUN = "data/aerial-isac-srs-iq-001" gt = json.load(open(f"{RUN}/ground_truth.json")) print(gt[100]) ``` ```python {'window_time_s': 1784243578.1545, 'objects': [{'track_id': 11, 'class_id': 0, 'class_name': 'person', 'range_m': 49.83346599516128, 'velocity_mps': 1.6525783001212782, 'world_xy': [0.5905, 22.4658], 'confidence': 0.7365, 'track_peak_range_m': 51.065499481495834, 'track_peak_velocity_mps': 1.7394326530687545}], 'srs_record_range': [7750, 7789], 'frame_number': 1295} ``` Reading the I/Q needs only NumPy and Python's `struct` module. The record framing is specified under Trace format below: ```python import struct import numpy as np SLOT = struct.Struct("<QQHHHHHBBHH") # 32 B slot header UE = struct.Struct("<HffffBfffBBBBBBBBHBBHHIHHHII") # 65 B per UE with open(f"{RUN}/srs_iq.trace", "rb") as f: assert f.read(4) == b"E3RT" f.seek(16) # past the file header while (hdr := f.read(8)): tag, _, payload_len = struct.unpack("<HHI", hdr) rec = f.read(payload_len) if tag != 2: # 2 = SRS record continue slot = SLOT.unpack_from(rec) n_rx_ant, n_ues = slot[6], slot[9] off = SLOT.size + n_ues * UE.size # IQ blob follows the UE blocks iq_len, = struct.unpack_from("<I", rec, off) iq = np.frombuffer(rec, "<f2", iq_len // 2, off + 4).astype(np.float32) grid = iq.view(np.complex64).reshape(n_rx_ant, -1, 3276) # [4, 6, 3276] break ``` A Range-Doppler map follows from despreading each grid with the SRS sequence given below, stacking the resulting channel estimates over a window of slots, and taking a 2-D FFT across subcarriers and slots. ## Scene and geometry The run was recorded outdoors in an open parking area, with a public road running behind it. The UE transmits from one side, the O-RU receives 5.79 m away, and targets walk and drive through a marked 5.79 x 25.0 m ground quad that defines the label world frame. <div align="center"> <img src="assets/testbed_setup.jpg" alt="O-RU receiver and UE transmitter deployed on site" width="100%"><br> <em>The two radios as deployed.</em> </div> <div align="center"> <img src="assets/testbed_geometry.png" alt="Testbed geometry, plan view to scale" width="100%"><br> <em>Plan view to scale. Gray curves are iso-contours of monostatic-equivalent range.</em> </div> | Quantity | Value | |---|---| | UE (transmitter) | (0.00, -7.43, 1.50) m | | O-RU (receiver) | (5.79, -7.43, 1.43) m | | Baseline | 5.7904 m | | Marked quad | 5.79 m wide x 25.0 m deep, origin at the near-left corner | | World frame | x along the near edge, y into depth, targets at z = 0 | ### Range convention Delay is referenced to the direct UE to O-RU path, so the range axis of an RD map measures excess path length, not target distance. The published `range_m` carries one further constant offset that aligns the labels with the processed RD peak: ``` range_m = R_tx + R_rx - baseline - 4.0 ``` The monostatic-equivalent range often plotted instead is `(R_tx + R_rx - baseline) / 2`, which approaches true target range only as the baseline shrinks. Recomputing the left-hand side from the published `world_xy`, with the antennas at their surveyed heights and targets at z = 0, recovers the offset as 4.105 m with a one-sigma spread of 0.384 m, the spread being label timing and homography error. ## Ground truth `ground_truth.json` is a list of processing windows, each 40 SRS records (100 ms) long: | Field | Level | Meaning | |---|---|---| | `window_time_s` | window | Absolute radio-clock time of the window, seconds | | `srs_record_range` | window | First and last SRS record index, inclusive | | `frame_number` | window | Video frame holding the window's last record | | `track_id` | object | Tracker identity, stable across windows | | `class_id`, `class_name` | object | COCO class: 0 person, 2 car | | `range_m` | object | Bistatic excess range, see convention above | | `velocity_mps` | object | Bistatic radial velocity, positive receding | | `world_xy` | object | Ground position in the quad frame, meters. `null` for 14 objects the detector missed | | `confidence` | object | Detector confidence, `null` wherever `world_xy` is | | `track_peak_range_m`, `track_peak_velocity_mps` | object | Reference radio measurement | `ground_truth.jsonl` holds the same labels flattened to one row per object, with `world_xy` split into `world_x_m` and `world_y_m`, so the dataset viewer can render them. Use whichever shape suits you. ### Reference measurement The `track_peak_*` fields are not ground truth but a reference result: the RD peak NVIDIA's own tracker reported for that window, published as a baseline to compare a receiver against. Present for 554 of the 569 objects, `null` elsewhere, and within 2.00 m RMS of the camera truth. ### Per-frame detections The windows above group the camera detections the labels are built from. `image_labels.json` publishes those detections ungrouped, one entry per video frame, 4,108 objects over 3,495 frames, each with `image_xy`, the target's pixel position in the video. That is what marks the targets on the camera panel of the demo above. ### Label coverage Labels cover the interval in which the targets are present: | | Labeled span | Full capture | |---|---|---| | SRS records | 2750 to 27439 | 0 to 33147 | | Video frames | 545 to 4240 | 0 to 5047 | | Trace time | 8.64 to 70.27 s | 0 to 84.985 s | The rest of the capture is valid radio and video data, simply without labels. Inside that span, labels are exhaustive for targets within the marked quad and in camera frame. Other scatterers, such as traffic on the road behind the lot, still produce genuine returns in the RD map, so an unlabeled return is not necessarily a false alarm. ### Accuracy and limitations This is a single run of a single outdoor scene with three targets, published as a reference capture. It is sized for evaluating and comparing receivers rather than for training, and results on it describe this geometry, band, and clutter environment. Label positions come from a homography of a hand-surveyed quad, and the residual against the published `range_m` has a one-sigma spread of 0.384 m, with individual objects further out, so scoring a receiver against them is meaningful only to that scale. Fourteen of the 569 objects carry a `null` `world_xy` and `confidence` where the detector missed a target the tracker still followed, and 15 carry no `track_peak_*` reference. Consumers should expect those nulls rather than assume every field is populated. ## Video synchronization The camera and the radio ran on unsynchronized clocks, offset by 37.0266 s. The timestamp burned into the video comes from the camera clock and **must not** be used to align with the trace. `video_sync.json` is the authoritative map: for each video frame it lists the SRS records that fall inside it. ```python sync = json.load(open(f"{RUN}/video_sync.json")) sync["video_info"]["video_clock_offset_s"] # 37.0266 sync["frames"][0]["srs_record_list"] # frame 541 -> records 2758..2765 ``` Frames from 541 to 4257 are mapped, bracketing the labeled span. The video itself covers the whole capture. ## Trace format `srs_iq.trace` is an E3 replay trace: a 16-byte file header followed by length-prefixed records. Every record is an SRS record holding a slot header, one UE metrics block, and the raw I/Q blob for the cell. The format is documented in [`trace_format.md`](https://github.com/NVIDIA/aerial-cuda-accelerated-ran/blob/main/cuPHY-CP/e3agent-standalone/docs/trace_format.md) and defined byte-for-byte by [`replay_format.hpp`](https://github.com/NVIDIA/aerial-cuda-accelerated-ran/blob/main/cuPHY-CP/e3agent-standalone/include/replay_format.hpp). Each I/Q blob is 314,496 bytes holding a `[4 antenna, 6 symbol, 3276 subcarrier]` grid. Subcarrier is the fastest-varying axis, so the samples run antenna by antenna, then symbol by symbol, and within a symbol consecutive subcarriers follow each other directly as interleaved pairs, `I0 Q0 I1 Q1 ...`. Each value is a 16-bit float carried in an int16 word. The grid is sized for a full 273 PRB carrier while the cell sounds 272, and SRS sits in buffer symbol 0 of every record in this run. Within the NR slot that symbol is index 12. Two small per-UE blobs follow, a 4,352-byte front-end channel estimate and a 1,088-byte per-RB SNR vector. A receiver that estimates the channel from the raw I/Q needs neither. The trace can also be replayed in real time into a dApp with the [E3 Agent Standalone](https://github.com/NVIDIA/aerial-cuda-accelerated-ran/tree/main/cuPHY-CP/e3agent-standalone). ### SRS pilot Despreading the grid into a channel estimate needs the sequence the UE transmitted: | Parameter | Value | |---|---| | SRS config index (C_SRS) | 61 | | Sequence ID | 40 | | Comb size | 2 | | Comb offset | 0 | | Cyclic shift | 0 | | Band start subcarrier | 0 | That gives 1632 pilot tones on the even subcarriers from 0 to 3262, which measure about 25 dB above the unoccupied ones. The transmitted sequence is the low-PAPR sequence of 3GPP TS 38.211 §6.4.1.4, built from the parameters above. ## Contributing This project is currently not accepting contributions. ## Citation If you use this dataset in your research, please cite it: ```bibtex @misc{nvidia2026aerialisacsrsiq, title = {{Aerial ISAC SRS I/Q}}, author = {{NVIDIA Corporation}}, year = {2026}, note = {Version 1.0.0}, howpublished = {\url{https://huggingface.co/datasets/nvidia/aerial-isac-srs-iq}} } ``` The dApp framework and the testbed the capture was recorded on are described in reference [1] below. ## Reference(s): [1] D. Villa, M. Belgiovine, N. Hedberg, M. Polese, C. Dick, and T. Melodia, "Programmable and GPU-Accelerated Edge Inference for Real-Time ISAC on NVIDIA Aerial Testbed," arXiv:2512.06493 \[cs.NI\], 2026. [arXiv PDF](https://arxiv.org/pdf/2512.06493) [2] NVIDIA Corporation, "Aerial Sample Apps." [GitHub repo](https://github.com/NVIDIA/aerial-sample-apps) [3] NVIDIA Corporation, "Aerial CUDA-Accelerated RAN." [GitHub repo](https://github.com/NVIDIA/aerial-cuda-accelerated-ran) [4] NVIDIA Corporation, "Aerial Testbed." [NVIDIA Docs](https://docs.nvidia.com/aerial/testbed/latest/index.html) ## Ethical Considerations: Recorded on private NVIDIA premises. Faces and vehicle plates are blurred in the released video, and only the blurred video is published. The video carries no audio track. Labels carry no identity beyond a per-run tracker index and a COCO class. The site photographs are stripped of camera metadata, including the GPS coordinates the originals carried. The trace contains no personal data; the 5G identifiers it carries, cell ID 51 and RNTI 10814, are ephemeral radio-layer values scoped to this capture. NVIDIA believes Trustworthy AI is a shared responsibility and we have established policies and practices to enable development for a wide array of AI applications. Developers should work with their internal developer teams to ensure this dataset meets requirements for the relevant industry and use case and addresses unforeseen product misuse. Please report quality, risk, security vulnerabilities or NVIDIA AI Concerns [here](https://www.nvidia.com/en-us/support/submit-security-vulnerability/).



