Configuration¶
One dataclass, NRConfig, configures every module: numerology, carrier and TDD pattern, MAC timing, HARQ and RLC, the PHY tables, the radio and cell layout, and the application fields. Do not add a second config class; new options become NRConfig fields.
from isaac_net import NRConfig, make_engine
from isaac_net.core import multicell, netslot_compat
cfg = NRConfig(mu=1, bandwidth_mhz=20, tdd_pattern="DDDSU", n_harq=16, mcs_table=2, dl=True)
print(cfg.summary()) # 51 PRB in 13 RBGs, 200 slots per 100 ms step, ...
cfg2 = cfg.with_(bler_target=0.01) # modified copy
net = make_engine("L2", E, R, "cuda", cfg)
Presets¶
Each preset returns an NRConfig and takes keyword overrides, for example netslot_compat(n_harq=4).
| Preset | What it is |
|---|---|
netslot_compat() |
the geometry and timing of the legacy slot-level model with the 3GPP PHY: one HARQ process, 50 PRBs in 5 subbands of 10, DDDSU |
lena_like() (alias lena_match) |
the ns-3 5G-LENA reference scenario as far as the model allows; needs the locally generated 5G-LENA BLER tables |
lena_validation() |
lena_like() in the geometry of the 5G-LENA validation sweep (fading off, whole-band UE power, per-UE link budgets) |
lena_match_v2(), lena_validation_v2() |
the same two with 5G-LENA's MAC behavior under load (per-RBG PF, TDMA UL retransmissions, the SR / BSR grant pipeline and the RLC tail stall; load gap), which matches 5G-LENA in loaded cells too |
srsran_like(), oai_like() |
uplink latency fitted to public srsRAN and OAI measurements (see Public-data calibration) |
multicell(n) |
a hexagonal cluster of n cells at 100 m spacing, thermal noise, same-slot interference, uplink power control and A3 handover; runs on L2 (up to 7 cells) and on L2-legacy |
Strict mode¶
Every level reads only some fields, listed by fields_read_by(level). The prototype levels read the application fields and their own parameters, because their radio and MAC are fixed, while L2 reads the frame, NR, link and radio fields. A field that a level ignores is ignored silently by default. NRConfig.unused_fields(level) returns the fields that are set away from their defaults and that the level ignores, and make_engine(..., strict=True) raises a ValueError naming them:
cfg = NRConfig(mcs_table=2, l0_loss=0.1)
cfg.unused_fields("L0") # ['mcs_table']
make_engine("L0", E, R, "cpu", cfg, strict=True) # ValueError: level L0 ignores these config fields: mcs_table
Independently of strict mode, the prototype levels, the surrogates and the bounds refuse a config whose frame_buffer, timeout_steps or control_step_ms differ from their compiled constants (16, 20 and 100 ms), and single-cell levels refuse n_cells > 1.
All fields¶
The tables below are generated from isaac_net/core/config.py when the docs are built. "Read by" names the engines that read the field: the application fields are read by every level, and "L2-legacy multi-cell" is L2-legacy with a non-legacy cell setting such as multicell(n). Configurability discusses the modelling choices behind many of them.
Numerology and carrier¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
mu |
1 |
L2, L2-legacy multi-cell | SCS = 15 * 2^mu kHz, mu in |
bandwidth_mhz |
20 |
L2 | |
n_prb |
None |
L2 | override of the 38.101 N_RB (e.g. 50 to match LENA RbOverhead=0.1) |
rbg_size |
None |
L2 | override of the 38.214 RBG size (subband = RBG) |
rbg_config |
1 |
L2 | 38.214 RBG configuration 1 or 2 |
Duplexing (TDD pattern, or FDD with a paired DL carrier)¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
duplex |
"tdd" |
L2 | "tdd": tdd_pattern below; "fdd": the UL carrier is all-U and a paired DL carrier is all-D, so every slot carries both (the TDD fields are unused) |
dl_n_prb |
None |
L2 | fdd: PRBs of the DL carrier (override); None = from dl_bandwidth_mhz |
dl_bandwidth_mhz |
None |
L2 | fdd: DL carrier bandwidth (38.101 N_RB at scs_khz); None = the UL carrier |
tdd_pattern |
"DDDSU" |
L2, L2-legacy multi-cell | one letter per slot, D / S / U, repeated |
special_split |
(10, 2, 2) |
L2, L2-legacy multi-cell | S slot symbols (DL, guard, UL) |
special_dl_data |
True |
L2 | S slot DL symbols carry PDSCH |
special_ul_data |
False |
L2, L2-legacy multi-cell | S slot UL symbols carry PUSCH (LENA: no) |
dl_ctrl_symbols |
1 |
L2 | PDCCH symbols at the start of D / S slots |
ul_data_symbols |
12 |
L2, L2-legacy multi-cell | PUSCH symbols in a U slot (14 - PUCCH - SRS) |
ul_mini_slot_symbols |
None |
L2 | mini-slot (type B) grants, NR engine: None = one scheduling occasion per slot; 2, 4 or 7 = every UL data slot is split into occasions of that many symbols (occasion_symbols), each its own grant, TB and decode (docs/configurability.md "Mini-slot grants") |
mini_slot_dl |
False |
L2 | split the DL data slots into occasions of ul_mini_slot_symbols too |
dmrs_re_per_prb |
12 |
L2 | N_DMRS^PRB in the 38.214 TBS formula (1 DMRS symbol, type 1) |
overhead_re_per_prb |
0 |
L2 | N_oh^PRB (xOverhead) |
MAC timing (slots)¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
k1 |
2 |
L2 | PDSCH -> HARQ-ACK (minimum; ACK goes to next UL-capable slot) |
k2 |
2 |
L2 | UL DCI -> PUSCH |
gnb_proc_slots |
1 |
L2 | gNB decode / scheduling latency |
sr_period_slots |
5 |
L2 | SR opportunity: first UL-capable slot of every period window |
sr_grant_delay_slots |
None |
L2 | SR -> first PUSCH; default gnb_proc + k2 |
ul_harq_rtt_slots |
None |
L2 | PUSCH -> earliest retx; default gnb_proc + k2 |
cqi_period_slots |
10 |
L2 | DL CQI report period (reports ride the next UL-capable slot) |
proactive_grant |
"off" |
L2 | "off" | "every_ul_slot" | "per_period": UL grant without SR at the first UL data slot of each TDD period (OAI-like); unused grants are not modelled |
proc_offset_ms |
0.0 |
L2 | fixed stack processing delay added to every frame completion |
HARQ / RLC¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
n_harq |
16 |
L2 | HARQ processes per UE per direction (1 = head-of-line mode) |
max_harq_tx |
4 |
L2 | transmissions per TB including the first (LENA maxHarqReTx=3) |
harq_combining |
"cc" |
L2 | "cc" (chase: add linear effective SINR), "ir_lena" (EESM over all tx + equivalent MCS at R/ntx, 5G-LENA NrEesmIr), "none" |
harq_fail |
"rlc_am" |
L2 | "rlc_am": resend after rlc_retx_slots, "drop": RLC UM loss |
rlc_retx_slots |
50 |
L2 | |
discard |
"purge" |
L2 | "purge": drop queued frames older than timeout (legacy NetSlot); "none": never purge; "pdcp_arrival": drop ARRIVING frames while the head-of-line frame is older than timeout (5G-LENA UM PDCP discard) |
PHY abstraction / link adaptation¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
mcs_table |
1 |
L2 | 38.214 Table 5.1.3.1-1 (64QAM) or -2 (256QAM) |
eff_sinr |
"eesm" |
L2 | "eesm" or "mean_db" (legacy NetSlot) |
bler_source |
"pdsch" |
L2 | "pdsch": Sionna PDSCH curves both directions; "lena": 5G-LENA EESM tables (local extraction); "sionna_label": audit only |
tbs_mode |
"38214" |
L2 | "38214" exact TBS, or "lena": floor((12-ref_sc)RBsymQmR/8) - CRC |
lena_ref_sc_per_rb |
1 |
L2 | NrAmc NumRefScPerRb (only for tbs_mode="lena") |
bler_target |
0.1 |
L2 | |
ul_mcs_max |
None |
L2 | MCS index cap (public-data calibration: bench open-source UL SE ~2.4-3) |
dl_mcs_max |
None |
L2 | |
cqi_table |
"mcs" |
L2 | DL CQI: "mcs" = the UE reports the highest MCS meeting the BLER target per RBG; "38214" = 4-bit CQI of TS 38.214 Table 5.2.2.1-2 (-3 with mcs_table=2), mapped to the highest MCS whose spectral efficiency is <= the CQI's |
olla |
True |
L2 | |
olla_up_db |
0.05 |
L2 | down step = up * (1 - target) / target |
scheduler |
"pf" |
L2 | "pf" proportional fair (metric from pf_metric), "pf_wideband" (= pf with pf_metric="wideband"), "maxci" (max rate, no fairness), "rr" (round robin: the robot served longest ago first, channel-blind), "qos" (5G-LENA NrMacSchedulerOfdmaQos: PF weighted by the 5QI priority and the delay budget of the queued message classes, docs/configurability.md) |
pf_metric |
"subband" |
L2 | "subband" (frequency-selective) or "wideband" (5G-LENA OFDMA PF) |
pf_window |
100.0 |
L2 | EWMA window in scheduled slots of that direction |
retx_priority |
True |
L2 |
SU-MIMO rank model (NR engine; docs/configurability.md "MIMO rank"); n_layers_max = 1 = one layer, bitwise¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
n_layers_max |
1 |
L2 | 1 or 2: largest rank of a TB; the rank is chosen per new TB at link adaptation |
rank_rule |
"sinr_los" |
L2 | rank 2 when "sinr": wideband SINR >= rank_sinr_min_db; "los": Rician K of the link < rank_k_max_db (NLOS = K 0, rich scattering); "sinr_los": both |
rank_sinr_min_db |
10.0 |
L2 | wideband link-adaptation SINR (per PRB, linear mean over the RBGs) for rank 2 |
rank_k_max_db |
3.0 |
L2 | K (dB) below which a link counts as rich scattering (no Rician K: K = 0) |
rank_layer_penalty_db |
3.0 |
L2 | per-layer SINR = SINR - 10 log10(rank) - this (inter-layer interference) |
ul_mimo |
False |
L2 | rank 2 in the UL (needs two UE antennas) |
dl_mimo |
True |
L2 | rank 2 in the DL (needs dl=True) |
Scheduler="qos" (read only then): message class c = clamp(priority, 0, qos_classes - 1) per message¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
qos_classes |
2 |
L2 | Q message classes (class 0 = highest priority) |
qos_priority |
(10, 70) |
L2 | 3GPP priority level P per class (1..99, lower = more important); the default is 5QI 5 (IMS signalling) vs 5QI 7 (voice / video / gaming) |
qos_pdb_ms |
(math.inf, math.inf) |
L2 | packet delay budget per class (ms); finite = delay-critical class (5G-LENA DC-GBR) with the delay-budget factor, inf = factor 1 |
qos_gamma |
1.0 |
L2 | rate exponent of the QoS metric (5G-LENA m_alpha) |
5G-LENA MAC behavior under load (docs/fidelity-load-gap.md); defaults = the engine before these switches¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
pf_update |
"slot" |
L2 | "slot": PF metric fixed within a slot, average updated with the served bytes; "rbg": 5G-LENA OFDMA PF, the winner's average is updated with its granted bytes after every RBG (RBGs spread over backlogged UEs) |
pf_avg_idle |
"decay" |
L2 | "decay": every UE's PF average moves every data slot; "freeze": only UEs with new data to schedule update it (5G-LENA active list) |
ul_retx_sched |
"ofdma" |
L2 | "ofdma": UL retx share the slot with new data; "tdma": one UL retx per slot (oldest NACK first) on every data symbol, nothing else in its slot |
ul_amc_alloc |
"current" |
L2 | UL MCS for the PRBs of the current grant, or "previous": for the PRBs of the UE's previous PUSCH (5G-LENA NrAmc), TB sized for the current one |
ul_grant_model |
"lumped" |
L2 | "lumped": SR -> grant after sr_grant_delay_slots, BSR = exact buffer; "bsr": 5G-LENA pipeline (SR bootstrap grant, 38.321 short-BSR levels rounded up with a report delay, padded over-grants, RLC tail stall); makes sr_grant_delay_slots and proactive_grant unused |
sr_boot_slots |
6 |
L2 | bsr: SR -> first PUSCH slot the bootstrap grant may use |
sr_boot_bytes |
17 |
L2 | bsr: bootstrap grant after an SR (5G-LENA srGrantSize 12 + 2 RLC + 3 MAC) |
bsr_delay_slots |
10 |
L2 | bsr: PUSCH carrying a BSR -> first PUSCH scheduled with it (2 UL slots) |
bsr_hdr_bytes |
8 |
L2 | bsr: UE adds short BSR (5) + MAC subheader (3) to the reported buffer |
bsr_est_hdr_bytes |
5 |
L2 | bsr: scheduler adds RLC (2) + MAC subheader (3) to the reported buffer |
rlc_tail_bytes |
16 |
L2 | bsr: RLC header residue the draining TB leaves behind (0 = no tail stall) |
rlc_tail_timer_ms |
10.0 |
L2 | bsr: RLC buffer-status timer that reports the residue |
Radio model inside the engine¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
snr_ref_prbs |
10 |
L2, L2-legacy multi-cell | input UL SNR = full UE power over this many PRBs |
ul_power |
"allocated" |
L2 | "allocated": UE power split over its grant; "whole_band": fixed PSD |
phr_cap |
True |
L2 | UL power-headroom cap on RBGs per UE (NetSlot; 5G-LENA has none) |
phr_min_db |
3.0 |
L2 | cap rule: per-PRB SNR (at the snr_ref_prbs split) >= this |
fading |
True |
L2 | |
fading_rho_per_ms |
0.93 ** (1 / 2.5) |
L2 | AR(1) per-subband Rayleigh; 0.93 per 2.5 ms (35 Hz) |
ue_speed_mps |
None |
L2 | set: fading_rho_per_ms = J0(2 pi f_D 2.5 ms)^(1/2.5), f_D = v f_c / c |
carrier_ghz |
3.5 |
L2 | carrier for the Doppler of ue_speed_mps (3 m/s at 3.5 GHz = 35 Hz) and of the tr38901 path loss |
fading_doppler |
"global" |
L2 | "global": one rho for all robots; "per_robot": rho from each robot's own speed (velocity input or consecutive poses), NR engine with pose input |
doppler_min_speed_mps |
0.0 |
L2 | per_robot: speed floor (0 = a still robot's fading is frozen) |
fading_rician |
False |
L2 | Rician fast fading (NR engine, docs/channels.md): per subband |sqrt(K/(K+1)) e^{j phi} + sqrt(1/(K+1)) h|^2, h the AR(1) Rayleigh state |
rician_k_db |
None |
L2 | fading_rician: fixed K (dB) for every link; None = K from the LOS state |
rician_k_from_los |
True |
L2 | K log-normal per link (TR 38.901 Table 7.5-6, tr38901_scenario) where the radio reports LOS and no blockage, else K = 0; False (or no LOS state): K = 0 |
rician_k_ramp_slots |
4 |
L2 | K moves linearly to a new target over this many slots (0 = at once) |
fading_freq_corr |
False |
L2 | frequency-correlated fading across the subbands (NR engine, docs/channels.md "Frequency-selective fading"): the AR(1) innovation becomes L z with L the Cholesky factor of the subband correlation of a delay spread |
fading_delay_spread_ns |
None |
L2 | fixed rms delay spread (ns) of every link; None = per-link draw |
fading_ds_from_los |
True |
L2 | per-link log-normal DS (TR 38.901 Table 7.5-6 lgDS of tr38901_scenario), the LOS or NLOS value by the radio's LOS state (NLOS while there is none) |
fading_pdp |
"exponential" |
L2 | power-delay profile behind the correlation (exponential only) |
fading_ds_grid |
(3.0, 3000.0, 16) |
L2 | per-link DS: (min ns, max ns, points) log grid of precomputed L |
inf_hall_volume_m3 |
None |
L2 | InF lgDS hall volume V and total surface S (walls + floor + ceiling); |
inf_hall_surface_m2 |
None |
L2 | None = the Table 7.8-7 hall of the scenario (V/S = 4.0 or 4.55) |
inf_lg_ds |
None |
L2 | InF: direct mean lgDS = log10(DS / 1 s) for LOS and NLOS (overrides V/S) |
dl_snr_offset_db |
10.0 |
L2 | step(): default DL per-PRB SNR = UL input SNR + offset |
Link budget for step_rx() (shared with multicell/: pathgain + interference in, SINR out)¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
noise_model |
"fixed" |
L2, L2-legacy multi-cell | "fixed": ni_fixed_dbm over snr_ref_prbs PRBs; "thermal": -174 dBm/Hz + NF |
ni_fixed_dbm |
-90.0 |
L2 | noise + interference floor over snr_ref_prbs PRBs (legacy NetSlot) |
gnb_nf_db |
5.0 |
L2, L2-legacy multi-cell | |
ue_nf_db |
9.0 |
L2 | |
ue_tx_dbm |
23.0 |
L2, L2-legacy multi-cell | |
gnb_tx_dbm |
43.0 |
L2 | DL total power, spread evenly over all PRBs |
Overheads¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
tb_overhead_bytes |
0 |
L2 | MAC subheaders / MAC CEs / RLC header per TB |
pkt_payload_bytes |
1400 |
L2 | application frame split into packets of this payload |
pkt_overhead_bytes |
0 |
L2 | per-packet bytes on the air (frame header, UDP/IP, PDCP, RLC SDU hdr) |
Radio (radio.py: large-scale gain per robot-cell link; the MAC takes SNR / pathgain inputs)¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
pl_const_db |
40.0 |
L2, L2-legacy multi-cell | PL = pl_const_db + 10 pathloss_exp log10(d), d >= 1 m |
pathloss_exp |
3.5 |
L2, L2-legacy multi-cell | |
shadow_sigma_db |
6.0 |
L2, L2-legacy multi-cell | one spatially correlated field per (env, cell), sum of plane waves |
shadow_modes |
8 |
L2, L2-legacy multi-cell | plane waves per field (every channel model's fields) |
shadow_dcorr_m |
10.3 |
L2, L2-legacy multi-cell | 1/e decorrelation distance of the log_distance shadowing (10.3 = the legacy 20-60 m wavelength band, bitwise; POWDER fit: 20-40 m) |
shadow_acf |
"sos" |
L2, L2-legacy multi-cell | "sos": legacy band scaled to shadow_dcorr_m; "exp": exp(-r / shadow_dcorr_m) |
shadow_white_frac |
0.0 |
L2, L2-legacy multi-cell | share of the shadowing variance in a component decorrelated within |
shadow_white_dcorr_m |
1.0 |
L2, L2-legacy multi-cell | this distance (exp ACF); POWDER: about 0.5 of the variance |
Channel model (radio.py; see docs/channels.md)¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
channel |
"log_distance" |
L2, L2-legacy multi-cell | "log_distance" (above) | "tr38901" | "radio_map"; "tr38901_inf_sh" etc. is shorthand for channel="tr38901", tr38901_scenario="InF-SH" |
tr38901_scenario |
"InF-SH" |
L2 | RMa, UMa, UMi, InH (mixed office), InF-SL, InF-DL, InF-SH, InF-DH |
tr38901_los |
"stochastic" |
L2 | "stochastic" (Table 7.4.2-1, spatially consistent) | "los" | "nlos" |
gnb_height_m |
None |
L2, L2-legacy multi-cell | None: the scenario default (tr38901), else 2-D geometry (other models) |
ue_height_m |
1.5 |
L2, L2-legacy multi-cell | robot antenna height (tr38901 and blockage) |
o2i_indoor_frac |
0.0 |
L2 | tr38901 UMa / UMi / RMa: share of robots indoors (O2I penetration) |
o2i_model |
"low" |
L2 | "low" | "high" (Table 7.4.3-2; RMa allows only "low") |
inf_clutter_density |
None |
L2 | InF r, d_clutter, h_c; None = Table 7.8-7 values of the scenario |
inf_clutter_size_m |
None |
L2 | |
inf_clutter_height_m |
None |
L2 | |
radio_map_path |
None |
L2 | channel="radio_map": .npz / .pt with gain_db [C,H,W] and bounds (x0,y0,x1,y1); "synthetic" = the shipped 2-cell test map |
blockage |
False |
L2, L2-legacy multi-cell | add-on to every channel: other robots are spheres that block the link |
blockage_radius_m |
0.3 |
L2 | |
blockage_loss_db |
20.0 |
L2 | extra loss on a link blocked by at least one robot body |
Obstacles and NLOS (channels/los.py, channels/blockage.py; see docs/obstacles.md)¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
los_source |
"stochastic" |
L2, L2-legacy multi-cell | LOS state: "stochastic" (tr38901 Pr_LOS, today) | "map" (radio map los_prob) | "raycast" (radio map obstacle_z height map) | "callback" (a blocked_fn, RadioMC.set_los_callback); map / raycast read radio_map_path |
los_raycast_samples |
32 |
L2 | raycast: samples along each robot-gNB segment |
los_diffraction |
False |
L2 | raycast: ITU-R P.526 knife-edge loss from the clearance (LOS -> NLOS ramp) |
los_soft |
False |
L2 | tr38901 with los_source="stochastic": Sec. 7.6.3.3 soft LOS blend |
nlos_extra_loss_db |
0.0 |
L2 | log_distance with a geometric LOS state: extra loss on NLOS links |
blockage_model |
"sphere" |
L2 | blockage=True: "sphere" (above) | "screen" (38.901 model B, robots and step(blockers=) as screens) | "stochastic" (38.901 model A) |
blocker_size_m |
((0.6, 1.5), (0.3, 1.7), (4.8, 1.4)) |
L2 | screen (w, h) m per class: robot, human, vehicle (Table 7.6.4.2-5 for human and vehicle) |
blockage_max_db |
40.0 |
L2 | screen / stochastic: cap of the summed blockage loss per link |
Cells: layout, uplink interference and power control, association and handover¶
Default: one gNB at the origin with the fixed noise floor, which is the legacy NetSlot geometry. multicell() gives the multi-cell preset. n_cells > 1 runs on level "L2" (NR engine, UL and DL interference) and on "L2-legacy" (NetSlotMC, UL only). TTT and interruption are in ms: NetSlotMC counts them in UL slots (ttt_slots, ho_int_slots), the NR engine in slots of slot_ms.
| Field | Default | Read by | Meaning |
|---|---|---|---|
n_cells |
1 |
L2, L2-legacy multi-cell | 1..7 |
cell_layout |
"custom" |
L2, L2-legacy multi-cell | "hex" | "grid" | "custom" |
cell_positions_m |
((0.0, 0.0),) |
L2, L2-legacy multi-cell | custom: one (x, y) per cell, env-local metres |
cell_isd_m |
100.0 |
L2, L2-legacy multi-cell | hex inter-site distance (>= 100 m: see multicell()) |
cell_center_m |
(75.0, 75.0) |
L2, L2-legacy multi-cell | hex: cluster centroid |
cell_arena_m |
150.0 |
L2, L2-legacy multi-cell | grid: square arena tiled by ceil(sqrt(C)) columns |
gnb_antenna |
"isotropic" |
L2, L2-legacy multi-cell | gNB antenna: "isotropic" (0 dBi) | "sector": TR 38.901 Table 7.3-1 element (65 deg HPBW, 30 dB front-back), added to every link (channels/antenna.py) |
cell_azimuth_deg |
None |
L2 | sector: boresight azimuth per cell (deg, from +x toward +y); None = 30, 150, 270 cycled over the cells (the 3-sector site convention) |
cell_tilt_deg |
0.0 |
L2 | sector: downtilt (deg below the horizon), one value or one per cell |
gnb_antenna_gain_dbi |
8.0 |
L2 | sector: maximum element gain G_E,max (Table 7.3-1) |
ul_interference |
True |
L2, L2-legacy multi-cell | thermal noise only: add same-slot other-cell UL interference |
dl_interference |
True |
L2 | thermal noise only: same for the DL (NR engine) |
li_alpha |
1.0 |
L2, L2-legacy multi-cell | link adaptation uses an EWMA of the measured N+I; 1 = previous slot |
ul_pc |
None |
L2, L2-legacy multi-cell | UL open-loop fractional power control P = min(Pmax - split, P0 + alpha PL) per subband; None = ON when n_cells > 1, OFF for one cell (legacy) |
ul_pc_p0_dbm |
-88.0 |
L2, L2-legacy multi-cell | per subband (10 PRB); about 15 dB SNR per subband at alpha = 1 |
ul_pc_alpha |
1.0 |
L2, L2-legacy multi-cell | |
ul_tpc |
False |
L2 | UL closed-loop power control (TS 38.213 Sec. 7.1.1) on top of ul_pc: per-robot TPC offset from the gNB's PUSCH SINR measurement (NR engine; needs ul_pc on) |
ul_tpc_mode |
"accumulate" |
L2 | "accumulate": f += step, clamped; "absolute": f = step |
ul_tpc_target_db |
None |
L2 | target PUSCH SINR per PRB at the gNB; None = the 10 % BLER SINR of the middle MCS of mcs_table (MCS 14: 6.3 dB table 1, 12.8 dB table 2, pdsch) |
ul_tpc_steps_db |
None |
L2 | command set (dB); None = (-1, 0, 1, 3) accumulate, (-4, -1, 1, 4) absolute (38.213 Table 7.1.1-1) |
ul_tpc_delay_slots |
None |
L2 | PUSCH -> its command takes effect; None = k2 |
ul_tpc_range_db |
20.0 |
L2 | |f| clamp (accumulated offset within the UE power range) |
a3_offset_db |
0.0 |
L2, L2-legacy multi-cell | A3: neighbour > serving + offset + hysteresis ... |
a3_hyst_db |
3.0 |
L2, L2-legacy multi-cell | |
a3_ttt_ms |
300.0 |
L2, L2-legacy multi-cell | ... held for the time-to-trigger |
ho_interruption_ms |
40.0 |
L2, L2-legacy multi-cell | robot cannot be scheduled after a handover |
ho_rlc |
"carry" |
L2, L2-legacy multi-cell | "carry": lossless, queued frames continue at the target; "flush": dropped |
a3_min_target_rsrp_dbm |
None |
L2, L2-legacy multi-cell | A3 target admission (5G-LENA MinTargetRsrpDbm): a neighbour whose RSRP (gNB EPRE + path gain, dBm per subcarrier) is below it is not a target; also the floor of the RLF cell search. None = no floor |
rlf |
False |
L2 | |
rlf_qout_db |
-8.0 |
L2 | out-of-sync SINR (TS 38.133 Qout: 10% hypothetical PDCCH BLER, about -8 dB) |
rlf_qin_db |
-6.0 |
L2 | in-sync SINR (TS 38.133 Qin: 2% hypothetical PDCCH BLER, about -6 dB) |
n310 |
1 |
L2 | TS 38.331 N310 / N311 (network-configured; n1 is the smallest value) |
n311 |
1 |
L2 | |
t310_ms |
1000.0 |
L2 | TS 38.331 T310 (network-configured, ms0 to ms6000) |
t311_ms |
3000.0 |
L2 | TS 38.331 T311 (network-configured, ms1000 to ms30000) |
reest_delay_ms |
40.0 |
L2 | cell found -> service at that cell (random access and RRC re-establishment) |
rlf_rlc |
None |
L2 | on RLF: "carry" (PDCP AM recovery) or "flush"; None = follow ho_rlc |
Access state machine (core/access.py, level "L2"): RACH / connection setup and connected-mode DRX¶
Off by default (every robot always connected and awake, the engine before these fields, bitwise).
| Field | Default | Read by | Meaning |
|---|---|---|---|
rach |
False |
L2 | contention-based random access (TS 38.321 Sec. 5.1) before a robot is served |
rach_occasion_slots |
20 |
L2 | RACH occasion (RO) period; ROs at the first UL-capable slot of every period window (a multiple of the TDD period; 20 slots = 10 ms at mu = 1) |
rach_preambles |
64 |
L2 | contention-based preambles per cell and RO (TS 38.211: 64 per cell) |
rach_rar_window_slots |
10 |
L2 | preamble -> RAR (the RAR is taken at the end of ra-ResponseWindow) |
rach_msg3_slots |
10 |
L2 | RAR -> contention resolution (Msg3 on PUSCH, Msg4); then the robot is served |
rach_backoff_ms |
20.0 |
L2 | backoff after a collision: uniform in [0, rach_backoff_ms] (38.321 Sec. 5.1.4, backoff indicator; 20 ms = BI index 2 of Table 7.2-1) |
rach_max_attempts |
10 |
L2 | preambleTransMax; a procedure that reaches it fails and restarts |
rach_initial |
"connected" |
L2 | state after a reset: "connected" (as without RACH) or "idle" (power-on) |
rach_release_after_ms |
None |
L2 | RRC release to idle after this inactivity; None = never |
drx |
False |
L2 | connected-mode DRX (TS 38.321 Sec. 5.7) |
drx_inactivity_ms |
100.0 |
L2 | drx-InactivityTimer: awake this long after the last scheduling activity |
drx_cycle_ms |
160.0 |
L2 | drx-LongCycle |
drx_on_ms |
10.0 |
L2 | drx-onDurationTimer |
drx_short_cycle_ms |
None |
L2 | drx-ShortCycle; None = no short cycle |
drx_short_cycles |
2 |
L2 | drx-ShortCycleTimer in short cycles |
drx_start_offset_ms |
0.0 |
L2 | drx-StartOffset (on-durations start at slot offset mod cycle) |
drx_ul_wake |
"sr" |
L2 | UL data while dormant: "sr" wakes the robot at once (a pending SR is Active Time, 38.321 Sec. 5.7), "on_duration" waits for the next on-duration |
Directions and application¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
ul |
True |
L2 | |
dl |
False |
L2 | |
control_step_ms |
100.0 |
every level | |
frame_buffer |
16 |
every level | frames per robot per direction |
timeout_steps |
20 |
every level | application deadline in control steps |
msg_sizes |
(4000.0, 30000.0) # bytes of traffic classes 1, 2, ... (Requests.send = class index) |
every level | bytes of traffic classes 1, 2, ... (Requests.send = class index) |
traffic |
None |
L2 | traffic models run inside the step (traffic.TrafficModel), level L2 only; None = policy messages only. A model or a list is turned into a tuple |
Delay levels (make_engine fills the level params from these when params is None)¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
l0_delay_median_steps |
0.05 |
L0 | L0: i.i.d. lognormal delay, median in control steps |
l0_delay_log_sigma |
0.5 |
L0 | L0: sigma of the log delay |
l0_loss |
0.0 |
L0 | L0: i.i.d. loss probability |
dr_delay_median_steps |
(0.05, 10.0) |
L0DR | L0DR: per-env median delay range, log-uniform at every reset |
dr_delay_log_sigma |
(0.2, 1.2) |
L0DR | L0DR: per-env sigma of the log delay, uniform |
dr_loss |
(0.0, 0.2) |
L0DR | L0DR: per-env loss probability, uniform |
l1_eta |
0.9 |
L1 | L1: goodput factor on 0.75 log2(1 + SNR) (all backends, triton included) |
Randomness and prototype timing¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
seed |
None |
every level | engine seed (make_engine(seed=...) overrides it); None = drawn from the global torch RNG at construction |
rng |
"engine" |
every level | every level (the NR engine too): "engine" = every draw from the engine's counter-based streams keyed by (seed, env, episode, call), so a policy's use of the global RNG never changes the network; "global" = the earlier behavior (stepping draws from the global torch RNG) |
proto_ul_slots_per_step |
None |
every level | prototype levels (L1, L2-legacy, QA): UL slots per control step; None = control_step_ms / 2.5 ms (the legacy DDDSU UL spacing) |
Edge-computing loop (core/edge.py): make_engine wraps any level in EdgeLoop when set¶
| Field | Default | Read by | Meaning |
|---|---|---|---|
edge |
None |
every level | |
background |
None |
every level | core.background.BackgroundConfig: non-robot UEs sharing each cell |
energy |
None |
every level | core.energy.EnergyConfig: per-robot radio energy and battery |
wifi |
None |
no engine yet | WifiConfig (core/wifi/config.py) for level "WIFI"; None = WifiConfig() |
fidelity |
None |
no engine yet | adaptive / mixed fidelity: a core.adaptive.FidelityConfig for make_adaptive |
Class and functions¶
NRConfig
dataclass
¶
NRConfig(mu: int = 1, bandwidth_mhz: int = 20, n_prb: int | None = None, rbg_size: int | None = None, rbg_config: int = 1, duplex: str = 'tdd', dl_n_prb: int | None = None, dl_bandwidth_mhz: int | None = None, tdd_pattern: str = 'DDDSU', special_split: tuple = (10, 2, 2), special_dl_data: bool = True, special_ul_data: bool = False, dl_ctrl_symbols: int = 1, ul_data_symbols: int = 12, ul_mini_slot_symbols: int | None = None, mini_slot_dl: bool = False, dmrs_re_per_prb: int = 12, overhead_re_per_prb: int = 0, k1: int = 2, k2: int = 2, gnb_proc_slots: int = 1, sr_period_slots: int = 5, sr_grant_delay_slots: int | None = None, ul_harq_rtt_slots: int | None = None, cqi_period_slots: int = 10, proactive_grant: str = 'off', proc_offset_ms: float = 0.0, n_harq: int = 16, max_harq_tx: int = 4, harq_combining: str = 'cc', harq_fail: str = 'rlc_am', rlc_retx_slots: int = 50, discard: str = 'purge', mcs_table: int = 1, eff_sinr: str = 'eesm', bler_source: str = 'pdsch', tbs_mode: str = '38214', lena_ref_sc_per_rb: int = 1, bler_target: float = 0.1, ul_mcs_max: int | None = None, dl_mcs_max: int | None = None, cqi_table: str = 'mcs', olla: bool = True, olla_up_db: float = 0.05, scheduler: str = 'pf', pf_metric: str = 'subband', pf_window: float = 100.0, retx_priority: bool = True, n_layers_max: int = 1, rank_rule: str = 'sinr_los', rank_sinr_min_db: float = 10.0, rank_k_max_db: float = 3.0, rank_layer_penalty_db: float = 3.0, ul_mimo: bool = False, dl_mimo: bool = True, qos_classes: int = 2, qos_priority: tuple = (10, 70), qos_pdb_ms: tuple = (math.inf, math.inf), qos_gamma: float = 1.0, pf_update: str = 'slot', pf_avg_idle: str = 'decay', ul_retx_sched: str = 'ofdma', ul_amc_alloc: str = 'current', ul_grant_model: str = 'lumped', sr_boot_slots: int = 6, sr_boot_bytes: int = 17, bsr_delay_slots: int = 10, bsr_hdr_bytes: int = 8, bsr_est_hdr_bytes: int = 5, rlc_tail_bytes: int = 16, rlc_tail_timer_ms: float = 10.0, snr_ref_prbs: int = 10, ul_power: str = 'allocated', phr_cap: bool = True, phr_min_db: float = 3.0, fading: bool = True, fading_rho_per_ms: float = 0.93 ** (1 / 2.5), ue_speed_mps: float | None = None, carrier_ghz: float = 3.5, fading_doppler: str = 'global', doppler_min_speed_mps: float = 0.0, fading_rician: bool = False, rician_k_db: float | None = None, rician_k_from_los: bool = True, rician_k_ramp_slots: int = 4, fading_freq_corr: bool = False, fading_delay_spread_ns: float | None = None, fading_ds_from_los: bool = True, fading_pdp: str = 'exponential', fading_ds_grid: tuple = (3.0, 3000.0, 16), inf_hall_volume_m3: float | None = None, inf_hall_surface_m2: float | None = None, inf_lg_ds: float | None = None, dl_snr_offset_db: float = 10.0, noise_model: str = 'fixed', ni_fixed_dbm: float = -90.0, gnb_nf_db: float = 5.0, ue_nf_db: float = 9.0, ue_tx_dbm: float = 23.0, gnb_tx_dbm: float = 43.0, tb_overhead_bytes: int = 0, pkt_payload_bytes: int = 1400, pkt_overhead_bytes: int = 0, pl_const_db: float = 40.0, pathloss_exp: float = 3.5, shadow_sigma_db: float = 6.0, shadow_modes: int = 8, shadow_dcorr_m: float = 10.3, shadow_acf: str = 'sos', shadow_white_frac: float = 0.0, shadow_white_dcorr_m: float = 1.0, channel: str = 'log_distance', tr38901_scenario: str = 'InF-SH', tr38901_los: str = 'stochastic', gnb_height_m: float | None = None, ue_height_m: float = 1.5, o2i_indoor_frac: float = 0.0, o2i_model: str = 'low', inf_clutter_density: float | None = None, inf_clutter_size_m: float | None = None, inf_clutter_height_m: float | None = None, radio_map_path: str | None = None, blockage: bool = False, blockage_radius_m: float = 0.3, blockage_loss_db: float = 20.0, los_source: str = 'stochastic', los_raycast_samples: int = 32, los_diffraction: bool = False, los_soft: bool = False, nlos_extra_loss_db: float = 0.0, blockage_model: str = 'sphere', blocker_size_m: tuple = ((0.6, 1.5), (0.3, 1.7), (4.8, 1.4)), blockage_max_db: float = 40.0, n_cells: int = 1, cell_layout: str = 'custom', cell_positions_m: tuple = ((0.0, 0.0),), cell_isd_m: float = 100.0, cell_center_m: tuple = (75.0, 75.0), cell_arena_m: float = 150.0, gnb_antenna: str = 'isotropic', cell_azimuth_deg: tuple | None = None, cell_tilt_deg: float | tuple = 0.0, gnb_antenna_gain_dbi: float = 8.0, ul_interference: bool = True, dl_interference: bool = True, li_alpha: float = 1.0, ul_pc: bool | None = None, ul_pc_p0_dbm: float = -88.0, ul_pc_alpha: float = 1.0, ul_tpc: bool = False, ul_tpc_mode: str = 'accumulate', ul_tpc_target_db: float | None = None, ul_tpc_steps_db: tuple | None = None, ul_tpc_delay_slots: int | None = None, ul_tpc_range_db: float = 20.0, a3_offset_db: float = 0.0, a3_hyst_db: float = 3.0, a3_ttt_ms: float = 300.0, ho_interruption_ms: float = 40.0, ho_rlc: str = 'carry', a3_min_target_rsrp_dbm: float | None = None, rlf: bool = False, rlf_qout_db: float = -8.0, rlf_qin_db: float = -6.0, n310: int = 1, n311: int = 1, t310_ms: float = 1000.0, t311_ms: float = 3000.0, reest_delay_ms: float = 40.0, rlf_rlc: str | None = None, rach: bool = False, rach_occasion_slots: int = 20, rach_preambles: int = 64, rach_rar_window_slots: int = 10, rach_msg3_slots: int = 10, rach_backoff_ms: float = 20.0, rach_max_attempts: int = 10, rach_initial: str = 'connected', rach_release_after_ms: float | None = None, drx: bool = False, drx_inactivity_ms: float = 100.0, drx_cycle_ms: float = 160.0, drx_on_ms: float = 10.0, drx_short_cycle_ms: float | None = None, drx_short_cycles: int = 2, drx_start_offset_ms: float = 0.0, drx_ul_wake: str = 'sr', ul: bool = True, dl: bool = False, control_step_ms: float = 100.0, frame_buffer: int = 16, timeout_steps: int = 20, msg_sizes: tuple = (4000.0, 30000.0), traffic: tuple | None = None, l0_delay_median_steps: float = 0.05, l0_delay_log_sigma: float = 0.5, l0_loss: float = 0.0, dr_delay_median_steps: tuple = (0.05, 10.0), dr_delay_log_sigma: tuple = (0.2, 1.2), dr_loss: tuple = (0.0, 0.2), l1_eta: float = 0.9, seed: int | None = None, rng: str = 'engine', proto_ul_slots_per_step: int | None = None, edge: EdgeConfig | None = None, background: object = None, energy: object = None, wifi: object | None = None, fidelity: object = None)
The one configuration of every isaac_net module: numerology, carrier and TDD pattern, MAC timing, HARQ
and RLC, PHY tables and link adaptation, radio and cell layout, and the application fields.
Every field has a default, so NRConfig() is a complete configuration (one cell, DDDSU at 30 kHz, 20 MHz).
The presets (netslot_compat, lena_like, lena_validation, srsran_like, oai_like, multicell) return an
NRConfig and take keyword overrides; cfg.with_(**changes) returns a modified copy. Derived quantities
(nprb, rbg, slots_per_step, ...) are properties computed from the fields. Each level reads only some fields
(fields_read_by); unused_fields(level) lists the non-default fields a level ignores, and
make_engine(..., strict=True) raises on them (strict=False, the default, warns once per config).
The scenario presets of core/scenarios.py (warehouse_private_5g, factory_inf, outdoor_campus, urllc_control) also
return an NRConfig. cfg.describe(level) prints a one-page summary, cfg.diff(other) lists the differing fields.
nprb
property
¶
PRBs of the carrier: n_prb if set, else TS 38.101-1 N_RB for bandwidth_mhz at scs_khz.
rbg
property
¶
RBG size in PRBs (one subband): rbg_size if set, else the TS 38.214 value for nprb.
subband_prbs
property
¶
PRBs per RBG (the last RBG may be smaller, 38.214 Sec. 5.1.2.2.1).
ul_slots_per_step
property
¶
Slots per control step that carry uplink data symbols.
dl_slots_per_step
property
¶
Slots per control step that carry downlink data symbols.
sr_delay
property
¶
Slots from a scheduling request to the first PUSCH: sr_grant_delay_slots, default gnb_proc_slots + k2.
ul_rtt
property
¶
Slots from a PUSCH to its earliest retransmission: ul_harq_rtt_slots, default gnb_proc_slots + k2.
subband_noise_dbm
property
¶
Noise per snr_ref_prbs-PRB subband at the gNB (fixed: ni_fixed_dbm; thermal: -174 dBm/Hz + NF).
ul_pc_on
property
¶
Whether uplink fractional power control is on: ul_pc, or by default on exactly when n_cells > 1.
ul_slot_ms
property
¶
UL slot spacing of the multi-cell legacy engine NetSlotMC: control_step_ms / proto_slots_per_step (2.5 ms
by default). Converts the handover times to NetSlotMC's slots. The NR engine counts them in slot_ms
instead (CellAssociation(slot_ms=...)), so its values do not depend on this.
ho_int_slots
property
¶
Handover interruption ho_interruption_ms in NetSlotMC's UL slots (ul_slot_ms).
summary
¶
One-line human-readable summary of the frame structure, HARQ, PHY and scheduler settings.
with_
¶
A copy of this config with the given fields replaced (dataclasses.replace). An explicit
fading_rho_per_ms clears an inherited ue_speed_mps, which would otherwise recompute it.
unused_fields
¶
Fields set away from their defaults that make_engine(level, ..., self) ignores (make_engine warns once per
config with UnusedFieldsWarning, raises with strict=True, and stays silent with strict=None).
is_legacy_cell
¶
One gNB at the origin with the fixed -90 dBm noise floor: the geometry of the prototype levels.
gnb_xy
¶
gNB positions (env-local metres). hex: centre site then the first ring at 0, 60, ..., 300 deg,
first n_cells sites, centroid at cell_center_m (C = 3: equilateral triangle, C = 7: full cluster).
grid: centres of a ceil(sqrt(C))-column tiling of the arena. custom: cell_positions_m.
slot_symbols
¶
(dl_data_symbols, ul_data_symbols) of the slot at pattern position pos. FDD: every slot is a full D slot
on the DL carrier and a full U slot on the UL carrier.
ul_capable
¶
Slot carries UL symbols (PUCCH for SR / HARQ-ACK / CQI) even if no PUSCH data (FDD: every slot).
noise_dbm_per_prb
¶
Noise PSD per PRB (dBm). fixed: ni_fixed_dbm spread over snr_ref_prbs PRBs.
fields_read_by
¶
NRConfig fields that the engine make_engine(level, ..., cfg) actually reads. Without cfg: the fields a level
may read under some configuration (whole groups); with cfg: only those its switches make it read (DL fields only
with dl=True, handover and interference fields only with several cells, the noise fields of the noise model, the
fields of the selected channel model, blockage and fading fields only when on, lena_ref_sc_per_rb only with
tbs_mode="lena", the closed-loop TPC fields only with ul_tpc, cqi_table only with dl, the antenna pattern fields only
with gnb_antenna="sector").
netslot_compat
¶
Closest NRConfig to the legacy NetSlot (netsim.py L2): single HARQ process with head-of-line
blocking, DDDSU at mu=1, 50 PRB in 5 subbands of 10 PRB, 12 data symbols without DMRS
overhead, SR -> grant 2 UL slots, HARQ RTT 4 UL slots, 10 extra UL slots after exhaustion,
OLLA on, per-subband PF, legacy mean-dB effective SINR. PHY stays 3GPP MCS/TBS/BLER.
lena_like
¶
Matches the ns3ref 5G-LENA v5.1 scenario (netslot-ref.cc) as far as the model allows:
50 PRB (RbOverhead 0.1) in 5 RBGs of 10 PRB, DDDSU, 13 UL data symbols (SRS off), 16 HARQ
processes, max 4 tx, retx at the next UL slot, RLC UM loss on HARQ exhaustion, no OLLA, no PHR
cap, wideband PF, 5G-LENA EESM tables + NrEesmIr combining + LENA TB size (bler_source="lena"
needs the local extraction; pass bler_source="pdsch", tbs_mode="38214", harq_combining="cc" to
run without it), PDCP discard of arriving SDUs, thermal noise with gNB NF 18.44 dB (= -90 dBm
per 10 PRB). Overheads are first estimates to calibrate against ns3ref (18 B frame header +
28 B UDP/IP + 2 B PDCP + 2 B RLC per 1400 B packet, 6 B MAC per TB).
lena_validation
¶
lena_like() in the ns3ref validation geometry (ns3ref_report 5.1 / 5.5): fading off, UE power
over the whole band, thermal noise NF 7 dB (-101.44 dBm per 10-PRB subband), per-UE link budgets
fed directly (tools/lena_replay.py), frames every 100 ms in phase.
srsran_like
¶
Fitted to srsRAN UL one-way delay (Zenodo 13754300, calib/params_latency.json 'srs'): SR period
20 ms, SR -> grant 1 UL slot, HARQ RTT 4 UL slots, BLER target 0.5%, processing offset 2.5 ms, no
proactive grants (W1 1.25 ms, KS 0.12 on the fit set). UL MCS capped at 15 (SE 2.41) for the
measured bench UL SE ceiling of about 2.4-3 (calib/params_link.json). The slot counts follow the mu and
tdd_pattern of the call (fit: mu=1, DDDSU).
oai_like
¶
Fitted to OAI UL one-way delay, 5/10-slot TDD periods (params_latency.json 'oai'): proactive UL
grant once per TDD period, BLER target 0.5%, processing offset 2.25 ms (OAI 20-slot periods need
about 7.25 ms), SR period 20 ms / SR -> grant 10 UL slots (irrelevant with proactive grants),
HARQ RTT 4 UL slots; UL MCS capped at 15 (bench OAI UL SE ceiling median 2.36). The slot counts follow the
mu and tdd_pattern of the call (fit: mu=1, DDDSU).
multicell
¶
Multi-cell preset (merged from multicell/): netslot_compat() MAC and PHY, a hex cluster of n_cells gNBs
at 100 m inter-site distance centred in the 150 m arena, thermal noise (NF 5 dB: -103.4 dBm per 10-PRB
subband) with same-slot UL interference, UL fractional power control (P0 -88 dBm per subband, alpha 1),
A3 handover (3 dB hysteresis, 300 ms TTT, 40 ms interruption) and lossless RLC carry-over.
Without power control, full-power robots near their own gNB dominate the interference and three cells
at 60 m ISD carry less than one (multicell_report); keep ul_pc on or the ISD at 100 m or more.
Runs on level "L2" (NR engine, this MAC with 3GPP MCS/TBS/BLER) and on "L2-legacy" (NetSlotMC).
fading_rho_from_speed
¶
AR(1) fading correlation per ms for a UE speed: the Jakes correlation J0(2 pi f_D anchor) over one legacy
UL slot spacing (2.5 ms), spread geometrically over its milliseconds. f_D = v f_c / c. 3 m/s at 3.5 GHz gives
0.9697 per ms (J0 = 0.926 per 2.5 ms), close to the default 0.93 per 2.5 ms. Monotone non-increasing in speed:
from the first zero of J0 on (2 pi f_D anchor >= 2.405, about 13.1 m/s at 3.5 GHz) consecutive 2.5 ms samples
are treated as uncorrelated (rho = 0), and the oscillating tail of J0 past that zero is not used.
rbg_size_38214
¶
RBG size P in PRBs for a bandwidth part of n_prb PRBs (TS 38.214 Table 5.1.2.2.1-1, configuration 1 or 2).