How to End-to-End Develop and Validate AI Models for L1 Receivers Using Sionna, the Aerial Framework, AODT, and cuBB?

Hi all,

I am currently investigating how to train and validate AI models for L1 Neural Receiver algorithms using frameworks such as Sionna, the Aerial Framework, AODT, and cuBB. The end-to-end development workflow is illustrated below.

This diagram outlines the closed-loop pipeline for AI-native L1 reception on the NVIDIA AI Aerial platform, comprising three interconnected stages:

Develop / Train: Algorithm research and model training occur here. Sionna PHY generates differentiable synthetic training data using statistical channel models (e.g., CDL/UMa). The pyAerial notebook leverages this data with PyTorch to train neural networks — such as a neural channel estimator or LLRNet soft de-mapper — and outputs trained weights as saved_models/. The Aerial Framework then compiles JAX-based algorithms via MLIR-TensorRT into deployable .trtengine files.

Simulate / Assess: Handled by the Aerial Omniverse Digital Twin (AODT). The saved_models/ are loaded into AODT Mode 3 Example 2, where inference runs over a physically accurate, site-specific ray-traced channel. Simulation outputs — including ground-truth CFRs, BLERs, throughputs, and scheduling metrics — are stored in ClickHouse and can be fed back to Stage ① to enrich or replace the statistical Sionna channel model.

Deploy: The production environment runs on Aerial CUDA-Accelerated RAN. cuBB/cuPHY executes the L1 pipeline in real time. The Aerial Data Lake captures live over-the-air (OTA) I/Q samples from O-RUs, which pyAerial processes into training datasets — specifically (equalized symbols, LLR) pairs — enabling continuous retraining of models such as LLRNet, thus closing the loop back to Stage ①.

  • The dashed blue arrow represents the documented OTA feedback path, with complete code available in the llrnet_dataset_generation notebook.

  • The dashed green arrow from AODT to Stage ① is conceptually documented but requires custom implementation.

  • The dashed gray arrow from .trtengine to cuBB currently has no documented end-to-end path.

I have the following questions:

  1. Is the diagram accurate? Are there any conceptual inaccuracies or misrepresentations that should be corrected?

  2. AODT v1.1 included ML example notebooks (e.g., for neural channel estimation), but these are absent in v1.4.1. Does this imply that ML functionality has been deprecated, or is it simply undocumented in the latest release?

  3. The official documentation only shows examples for neural channel estimation (solid green arrow to AODT, gray dashed arrow to cuBB). If I wish to train AI models for all three blocks — channel estimation, equalizer, and soft de-mapping — what is the recommended approach? Are there any missing documents, hidden examples, or unpublished workflows I should be aware of?

  4. Is it possible to train AI models using OTA data beyond the LLRNet case? While cuBB documentation confirms OTA-based training only for the LLRNet soft de-mapper, it remains unclear whether similar OTA-driven training is feasible for the channel estimator or equalizer — and if so, what pathway exists to use OTA I/Q data for these components?

  5. Can AODT directly output performance metrics such as Normalized Mean Square Error (NMSE), Symbol Error Rate (SER), or Error Vector Magnitude (EVM)? If not, what is the recommended method to compute them from the available data (e.g., CFRs, I/Q samples)?

Any insights, clarifications, or suggestions would be greatly appreciated.

Thanks!

Regarding the second question, I configured the following parameters in the configuration file src_be/components/common/config_ran.json:

"Simulation pattern": 3,
"pyaerial pusch enabled": 1,
"pyaerial pusch channel estimation": "ML",
"pusch channel estimation": "ML"

However, the AODT (v1.4.0) frontend is generating the following error log:

2026-04-02 12:24:27  [Error] [aodt.common.utils] [error] Problem initializing RAN controller: BECtrl:579: Error Loading PUSCH ML models in Python.
2026-04-02 12:24:27  [Error] [aodt.common.utils] Recommend checking your scenario settings and GPU memory usage on compute node.
2026-04-02 12:24:27  [Error] [aodt.common.utils] 
2026-04-02 12:24:27  [Error] [aodt.common.utils] Location: sim_handler.handler_play_sim:1576
2026-04-02 12:24:27  [Error] [aodt.common.utils] [error] handler_play_sim returned -1
2026-04-02 12:24:27  [Error] [aodt.common.utils] 
2026-04-02 12:24:27  [Error] [aodt.common.utils] Location: sim_entrypoint.handle_start_sim_request_sim:658

Could this error be caused by an incorrectly set models_folder path in backend/aodt_sim/build/channel_estimator_install/config_est.ini?

For reference, the model files I generated are located at:
aodt_sim/external/cuBB/pyaerial/notebooks/channel_estimation/saved_models_prbs=48_interp=2/ch=UMa_n_iter=500_batchsize=32_model=48PRBs/
and include the following files:
'model_SNR=0.0.path', 'model_SNR=-10.0.path', 'model_SNR=10.0.path',
'model_SNR=20.0.path', 'model_SNR=30.0.path', 'model_SNR=40.0.path'.

This is a really helpful breakdown of the end-to-end pipeline, especially the closed-loop between Sionna, AODT, and cuBB.

I’ve recently started working with Sionna and exploring how simulation outputs (like BER vs SNR, channel behavior, etc.) can be made more interpretable from a developer perspective.

Currently experimenting with building a lightweight visualization layer on top of Sionna outputs to better understand how these stages interact.

This discussion definitely helps in connecting the training → simulation → deployment flow more clearly.

1 Like