1- .. _downlinkHandling :
2-
31.. Warning ::
42
5- ** [BETA] ** :ref : `downlinkHandling ` is a beta module in an initial public release. This module might be
3+ :beta : `downlinkHandling ` is a beta module in an initial public release. This module might be
64 subject to changes in future releases.
75
86Executive Summary
97-----------------
10- This document describes how the :ref: `downlinkHandling ` module operates within the Basilisk simulation framework.
11- The module maps radio link quality from :ref: `linkBudget ` into communication reliability and effective telemetry throughput.
12- It then converts this throughput into a data sink request that removes data from onboard storage.
8+ This document describes how the downlinkHandling module maps radio link quality into realistic
9+ data transfer outcomes.
10+
11+ At each simulation step, the module:
12+
13+ - reads link quality from :ref: `linkBudget `
14+ - converts CNR into BER and packet error rate
15+ - applies retry-limited ARQ reliability
16+ - removes data from onboard storage at the resulting effective rate
17+ - publishes detailed diagnostics for analysis and fault studies
18+
19+ The module is designed to sit between RF-link modeling (:ref: `simpleAntenna `, :ref: `linkBudget `)
20+ and onboard data-buffer dynamics (:ref: `DataStorageStatusMsgPayload `, :ref: `DataNodeUsageMsgPayload `).
1321
14- In short, the module provides:
22+ System Role and Data Flow
23+ -------------------------
1524
16- - Link-quality to BER/PER conversion for a configurable bit rate and packet size.
17- - Retry-limited delivery modeling (ARQ-style retransmissions).
18- - Effective throughput estimates (attempted, removed, delivered, dropped).
19- - Tight coupling to Basilisk storage units through :ref: `DataNodeUsageMsgPayload `.
25+ .. _downlinkhandling-figure-flow :
26+ .. figure :: /../../src/simulation/communication/downlinkHandling/_Documentation/Images/DownlinkHandlingFlow.svg
27+ :width: 90%
28+ :align: center
29+ :alt: downlinkHandling integration flow with simpleAntenna, linkBudget, and storage
30+
31+ Figure 1: Integration flow and message-level role of downlinkHandling.
2032
2133Message Connection Descriptions
2234-------------------------------
2335The following table lists all module input and output messages.
24- The module message connections are set by the user from Python.
36+ The message connection is set by the user from Python.
2537
2638.. list-table :: Module I/O Messages
27- :widths: 24 22 34 20
39+ :widths: 22 22 36 20
2840 :header-rows: 1
2941
3042 * - Msg Variable Name
3143 - Msg Type
3244 - Description
3345 - Note
34- * - linkBudgetInMsg
46+ * - `` linkBudgetInMsg ``
3547 - :ref: `LinkBudgetMsgPayload `
36- - Link-quality input from :ref: `linkBudget ` (CNR, overlap bandwidth, frequency, antenna states ).
37- - Required
38- * - storageUnitInMsgs (via ``addStorageUnitToDownlink ``)
48+ - Link-quality input from :ref: `linkBudget ` (receiver states, `` CNR1 ``, `` CNR2 ``, overlap bandwidth ).
49+ - Required for non-zero downlink
50+ * - `` storageUnitInMsgs `` (via ``addStorageUnitToDownlink ``)
3951 - :ref: `DataStorageStatusMsgPayload `
40- - Storage state input used to determine available data and selected partition name .
52+ - Storage state input (partition names, partition bits, total storage level) .
4153 - Required for actual data removal
42- * - nodeDataOutMsg
54+ * - `` nodeDataOutMsg ``
4355 - :ref: `DataNodeUsageMsgPayload `
44- - Data-node output where negative baud rate removes data from storage.
45- - Output (inherited from `` DataNodeBase ``)
46- * - downlinkOutMsg
56+ - Data-node output inherited from `` DataNodeBase ``. Negative baud rate removes bits from storage.
57+ - Output
58+ * - `` downlinkOutMsg ``
4759 - :ref: `DownlinkHandlingMsgPayload `
48- - Detailed diagnostics (BER/PER, retry probabilities , rates, cumulative counters) .
60+ - Diagnostics output with link metrics, reliability metrics , rates, and cumulative counters.
4961 - Output
5062
5163Detailed Module Description
5264---------------------------
53- The module extends ``DataNodeBase `` and executes once per simulation step.
54- At each step it:
55-
56- 1. Reads ``LinkBudgetMsgPayload `` and storage status messages.
57- 2. Selects the receive path (forced receiver index or auto-select).
58- 3. Converts CNR and overlap bandwidth to :math: `C/N_0 `.
59- 4. Converts :math: `C/N_0 ` and requested bit rate to :math: `E_b/N_0 `.
60- 5. Computes BER and packet error rate (PER).
61- 6. Applies retry limit to estimate packet delivery/drop probabilities.
62- 7. Converts reliability into effective source-data outflow from storage.
63- 8. Writes both standard data-node output and a detailed diagnostics output.
65+ The module extends ``DataNodeBase `` and runs once per simulation step.
66+
67+ The per-step sequence is:
68+
69+ 1. Read ``LinkBudgetMsgPayload `` and all connected storage status messages.
70+ 2. Select one storage partition (largest currently available data in the most recently connected storage unit).
71+ 3. Select receiver path (forced receiver index or auto mode).
72+ 4. Convert selected CNR and overlap bandwidth into :math: `C/N_0 `.
73+ 5. Convert :math: `C/N_0 ` and requested bit rate into :math: `E_b/N_0 `.
74+ 6. Compute BER and PER.
75+ 7. Apply retry-limited ARQ model to obtain success/drop probability and expected attempts.
76+ 8. Compute attempted, removed, delivered, and dropped rates.
77+ 9. Apply packet gating and storage saturation.
78+ 10. Write ``nodeDataOutMsg `` and ``downlinkOutMsg ``.
6479
6580Configurable Parameters
6681^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,148 +91,196 @@ Configurable Parameters
7691 * - ``bitRateRequest ``
7792 - 0.0
7893 - bit/s
79- - Requested raw channel bit rate :math: `R_b`.
94+ - Requested raw channel bit rate :math: `R_b`. If :math: `R_b \le 0 `, throughput is zero.
8095 * - ``packetSizeBits ``
8196 - 256.0
8297 - bit
83- - Packet length :math: `L` used for BER-to-PER conversion.
98+ - Packet length :math: `L` for BER-to-PER conversion.
8499 * - ``maxRetransmissions ``
85100 - 10
86101 - -
87- - Retry cap used in truncated ARQ probability model.
102+ - Retry cap used in the ARQ model. Current implementation enforces :math: `N \ge 1 ` and treats :math: `N` as maximum transmission attempts .
88103 * - ``receiverAntenna ``
89104 - 0
90105 - -
91- - Receiver selection: 0=auto, 1=use antenna1 CNR , 2=use antenna2 CNR .
106+ - Receiver selection: 0=auto, 1=use receiver path 1 , 2=use receiver path 2 .
92107 * - ``requireFullPacket ``
93- - True
108+ - `` True ``
94109 - bool
95- - If enabled , downlink only starts when at least one full packet exists in storage .
110+ - If `` True `` , downlink waits until selected storage has at least one full packet.
96111
97- Receiver Path Selection
98- ^^^^^^^^^^^^^^^^^^^^^^^
99- The module uses antenna state information from ``LinkBudgetMsgPayload ``:
112+ Receiver Selection and CNR1/CNR2 Usage
113+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
114+ The module uses receiver-specific fields from :ref: `LinkBudgetMsgPayload `:
115+
116+ - ``CNR1 `` corresponds to receiver path 1
117+ - ``CNR2 `` corresponds to receiver path 2
118+
119+ These are not duplicates. They represent two possible receiving directions/modes in the bidirectional
120+ link-budget result.
121+
122+ Selection behavior:
123+
124+ - ``receiverAntenna = 1 ``: use path 1 (only if antenna state 1 is RX or RXTX)
125+ - ``receiverAntenna = 2 ``: use path 2 (only if antenna state 2 is RX or RXTX)
126+ - ``receiverAntenna = 0 ``: auto-select valid RX path with higher CNR
127+
128+ If no valid receiver path exists, the link is treated as inactive for that step.
129+
130+ Reliability and Throughput Model
131+ --------------------------------
100132
101- - ``ANTENNA_RX `` and ``ANTENNA_RXTX `` are treated as valid receiver states.
102- - For ``receiverAntenna = 0 `` (auto), the module chooses the valid receiver path with highest CNR.
103- - If no valid receiver path exists, the link is treated as inactive for this step.
133+ .. _downlinkhandling-figure-model :
134+ .. figure :: /../../src/simulation/communication/downlinkHandling/_Documentation/Images/DownlinkHandlingReliabilityChain.svg
135+ :width: 95%
136+ :align: center
137+ :alt: CNR to BER to PER to ARQ to effective throughput chain
104138
105- BER/PER and Throughput Model
106- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
139+ Figure 2: Computation chain from RF link quality to storage removal and delivered data rates.
107140
108- For valid inputs (:math: `\mathrm {CNR} > 0 `, overlap bandwidth :math: `>0 `, :math: `R_b>0 `, packet size :math: `>0 `):
141+ For valid inputs (linked/written link budget, selected CNR :math: `>0 `, overlap bandwidth :math: `>0 `,
142+ :math: `R_b>0 `, packet size :math: `>0 `):
109143
110144.. math ::
111145
112- \mathrm {CNR}_{dB} = 10 \log _{10 }(\mathrm {CNR})
146+ \mathrm {CNR}_{dB} = 10 \log _{10 }(\mathrm {CNR})
113147
114148.. math ::
115149
116- \frac {C}{N_0 }\,[dBHz] = \mathrm {CNR}_{dB} + 10 \log _{10 }(B_\mathrm {overlap})
150+ \frac {C}{N_0 }\,[dBHz] = \mathrm {CNR}_{dB} + 10 \log _{10 }(B_{ \mathrm {overlap} })
117151
118152.. math ::
119153
120154 \frac {E_b}{N_0 }\,[dB] = \frac {C}{N_0 }[dBHz] - 10 \log _{10 }(R_b)
121155
122- The current BER model is BPSK over AWGN:
156+ Current BER model ( BPSK over AWGN) :
123157
124158.. math ::
125159
126- \mathrm {BER} = Q\left (\sqrt {2 E_b/N_0 }\right ) = \frac {1 }{2 }\,\mathrm {erfc}\left (\sqrt {E_b/N_0 }\right )
160+ \mathrm {BER} = Q\left (\sqrt {2 E_b/N_0 }\right )
161+ = \frac {1 }{2 }\,\mathrm {erfc}\left (\sqrt {E_b/N_0 }\right )
127162
128163 Packet error model (independent bit errors, any bit error fails packet):
129164
130165.. math ::
131166
132167 \mathrm {PER} = 1 - (1 -\mathrm {BER})^L
133168
134- Retry-limited completion/drop model:
169+ Let :math: `N= \max ( 1 , \texttt {maxRetransmissions})`. Retry-limited ARQ model:
135170
136171.. math ::
137172
138- P_\mathrm {drop} = \mathrm {PER}^{N}
173+ P_{ \mathrm {drop} } = \mathrm {PER}^{N}
139174
140175.. math ::
141176
142- P_\mathrm {success} = 1 - P_\mathrm {drop}
177+ P_{ \mathrm {success}} = 1 - P_{ \mathrm {drop} }
143178
144- where :math: `N` is `` maxRetransmissions ``.
179+ Expected attempts per source packet (truncated geometric expectation):
145180
146- Expected attempts per source packet (truncated geometric form):
181+ .. math ::
182+
183+ \mathbb {E}[A] =
184+ \begin {cases}
185+ \dfrac {P_{\mathrm {success}}}{1 -\mathrm {PER}}, & \mathrm {PER}<1 \\
186+ N, & \mathrm {PER}=1
187+ \end {cases}
188+
189+ Unscaled rates:
147190
148191.. math ::
149192
150- \mathbb {E}[A] = \frac {P_\mathrm {success}}{1 -\mathrm {PER}}
193+ R_{\mathrm {attempt,pot}} = R_b
194+
195+ .. math ::
151196
152- Rate mapping:
197+ R_{ \mathrm {remove,pot}} = \frac {R_{ \mathrm {attempt,pot}}}{ \mathbb {E}[A]}
153198
154199.. math ::
155200
156- R_\mathrm {attempt} = R_b
201+ R_{ \mathrm {delivered,pot}} = R_{ \mathrm {remove,pot}} \, P_{ \mathrm {success}}
157202
158203.. math ::
159204
160- R_\mathrm {remove} = \frac {R_\mathrm {attempt}}{\mathbb {E}[A]}
205+ R_{\mathrm {dropped,pot}} = R_{\mathrm {remove,pot}} - R_{\mathrm {delivered,pot}}
206+
207+ Storage and packet gating scale factor:
161208
162209.. math ::
163210
164- R_\mathrm {delivered} = R_\mathrm {remove}\, P_\mathrm {success}
211+ s = \mathrm {clamp}\!\left (
212+ \frac {B_{\mathrm {available}}/\Delta t}{R_{\mathrm {remove,pot}}},
213+ 0 , 1 \right )
214+
215+ with additional logic:
216+
217+ - if ``requireFullPacket `` is ``True ``, enforce :math: `B_{\mathrm {available}} \ge L`
218+ - if :math: `\Delta t \le 0 ` or :math: `R_{\mathrm {remove,pot}} \le 0 `, set :math: `s=0 `
219+
220+ Final rates:
165221
166222.. math ::
167223
168- R_\mathrm {dropped} = R_\mathrm {remove} - R_\mathrm {delivered}
224+ R_{\mathrm {attempt}} = s\, R_{\mathrm {attempt,pot}}, \quad
225+ R_{\mathrm {remove}} = s\, R_{\mathrm {remove,pot}}, \quad
226+ R_{\mathrm {delivered}} = s\, R_{\mathrm {delivered,pot}}, \quad
227+ R_{\mathrm {dropped}} = s\, R_{\mathrm {dropped,pot}}
228+
229+ The value written to storage through ``nodeDataOutMsg `` is:
169230
170- The module then applies storage/time-step saturation so removed data in a step never exceeds available bits.
171- The final storage removal is written as negative baud rate to ``nodeDataOutMsg ``.
231+ .. math ::
172232
173- Output Diagnostics Message
174- ^^^^^^^^^^^^^^^^^^^^^^^^^^
175- The custom output message :ref: `DownlinkHandlingMsgPayload ` includes:
233+ \texttt {nodeDataOutMsg.baudRate} = -R_{\mathrm {remove}}
176234
177- - Link state and selected receiver path.
178- - CNR, :math: `C/N_0 `, :math: `E_b/N_0 `, BER, PER.
179- - Packet success/drop probabilities and expected attempts.
180- - Attempted/removal/delivered/dropped rates.
181- - Available and estimated remaining bits for selected data partition.
182- - Cumulative attempted/removed/delivered/dropped bit counters.
235+ Output Diagnostics
236+ ------------------
237+ The custom output :ref: `DownlinkHandlingMsgPayload ` reports:
238+
239+ - link/selection state (``linkActive ``, ``receiverIndex ``, antenna names)
240+ - physical-layer quality terms (CNR, :math: `C/N_0 `, :math: `E_b/N_0 `, BER, PER)
241+ - ARQ reliability terms (success/drop probabilities, expected attempts)
242+ - rate terms (attempted, removed, delivered, dropped)
243+ - storage terms (available and estimated remaining bits)
244+ - cumulative counters (attempted/removed/delivered/dropped bits)
183245
184246Integration with simpleAntenna and linkBudget
185247----------------------------------------------
186- Typical communication chain:
248+ Typical chain:
187249
188- 1. Two :ref: `simpleAntenna ` modules compute antenna-level properties and output :ref: ` AntennaLogMsgPayload ` .
189- 2. :ref: `linkBudget ` consumes both antenna logs and computes CNR and overlap bandwidth in :ref: ` LinkBudgetMsgPayload ` .
190- 3. :ref: `downlinkHandling ` consumes :ref: ` LinkBudgetMsgPayload ` and storage status to produce effective downlink throughput .
191- 4. Storage units consume ``nodeDataOutMsg `` and decrement onboard data.
250+ 1. :ref: `simpleAntenna ` modules compute antenna logs .
251+ 2. :ref: `linkBudget ` computes overlap bandwidth and CNR per receiver path .
252+ 3. :ref: `downlinkHandling ` converts link quality to effective data transfer and storage removal .
253+ 4. Storage modules consume ``nodeDataOutMsg `` and reduce onboard buffered data.
192254
193- This separation lets RF/pointing/frequency effects propagate naturally through CNR into BER/PER and finally into delivered data.
255+ This separation is useful for fault modeling: upstream RF degradation (pointing, frequency mismatch,
256+ atmospheric attenuation, receive-state changes) naturally propagates into BER/PER and delivered data.
194257
195- Module Assumptions and Limitations
196- ----------------------------------
258+ Assumptions and Current Limits
259+ ------------------------------
197260
198- - BER model is currently analytic BPSK/AWGN.
199- - Bit errors are assumed independent.
200- - Packet failure occurs if any bit is wrong .
201- - Retry model is expectation-based ( not packet-by-packet Monte Carlo simulation) .
202- - No explicit ACK latency, framing overhead, coding gain , or adaptive modulation/ coding.
203- - If no valid receiver or invalid link inputs exist, output rates are zero for that step .
261+ - BER model is analytic BPSK/AWGN.
262+ - Bit errors are independent.
263+ - Any bit error fails the packet .
264+ - ARQ is expectation-based, not packet-by-packet Monte Carlo.
265+ - No explicit ACK latency, coding gain, framing overhead , or adaptive coding/modulation .
266+ - Storage partition selection currently targets the largest partition in the latest connected storage unit .
204267
205268Unit Test Coverage
206269------------------
207- The module unit test is located at :
270+ Test file :
208271
209272``src/simulation/communication/downlinkHandling/_UnitTest/test_downlinkHandling.py ``
210273
211- The test suite verifies :
274+ The tests verify :
212275
213- - Numerical parity with the Python-equivalent BER/PER/ARQ equations.
214- - Zero -flow behavior when link quality is invalid.
215- - Retry -cap effects on drop probability and storage removal behavior.
216- - Storage -limited behavior and remaining-data estimates.
217- - Automatic receiver-path selection from link-budget antenna states.
276+ - equation parity versus a Python-equivalent BER/PER/ARQ model
277+ - zero -flow behavior for invalid link inputs
278+ - retry -cap effects on drop probability and removal/delivery behavior
279+ - storage -limited rate capping and drain behavior
280+ - automatic receiver selection from antenna RX states and CNR values
218281
219- User Guide Snippet
220- ------------------
282+ Usage Snippet
283+ -------------
221284
222285.. code-block :: python
223286
@@ -227,15 +290,13 @@ User Guide Snippet
227290 dlh.bitRateRequest = 1.0e5 # bit/s
228291 dlh.packetSizeBits = 1024.0 # bit
229292 dlh.maxRetransmissions = 8
230- dlh.receiverAntenna = 0 # auto
293+ dlh.receiverAntenna = 0 # auto-select valid RX path with highest CNR
231294 dlh.requireFullPacket = True
232295
233296 storage = simpleStorageUnit.SimpleStorageUnit()
234297 storage.storageCapacity = int (8e9 )
235-
236- # storage consumes downlink node output (negative baud removes data)
237298 storage.addDataNodeToModel(dlh.nodeDataOutMsg)
238299 dlh.addStorageUnitToDownlink(storage.storageUnitDataOutMsg)
239300
240- # linkBudgetOutMsg would be connected from linkBudget module
301+ # linkBudgetOutPayload is produced by the linkBudget module:
241302 # dlh.linkBudgetInMsg.subscribeTo(linkBudgetModule.linkBudgetOutPayload)
0 commit comments