Skip to content

Commit 1ffe531

Browse files
committed
[#1323] downlinkHandling: refine module docs and add release note snippet
1 parent 42a7062 commit 1ffe531

2 files changed

Lines changed: 60 additions & 12 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- Added :ref:`downlinkHandling` with a validated configuration interface (setters/getters), finite-value guards, and bounded outputs to prevent non-physical downlink rates.
2+
- Added :ref:`DownlinkHandlingMsgPayload` diagnostics and dedicated unit-test coverage for equation parity, receiver-path selection, storage-limited behavior, and invalid-input handling.
3+
- Improved storage-target selection robustness across connected storage status messages and aligned module documentation with implemented behavior and validation interface.

src/simulation/communication/downlinkHandling/downlinkHandling.rst

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ The module extends ``DataNodeBase`` and runs once per simulation step.
6767
The per-step sequence is:
6868

6969
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).
70+
2. Select one storage target (largest finite partition across all connected storage units; use ``storageLevel`` only when a message has no partition vector).
7171
3. Select receiver path (forced receiver index or auto mode).
7272
4. Convert selected CNR and overlap bandwidth into :math:`C/N_0`.
7373
5. Convert :math:`C/N_0` and requested bit rate into :math:`E_b/N_0`.
@@ -104,11 +104,31 @@ Configurable Parameters
104104
- 0
105105
- -
106106
- Receiver selection: 0=auto, 1=use receiver path 1, 2=use receiver path 2.
107+
* - ``removalPolicy``
108+
- ``REMOVE_ATTEMPTED`` (0)
109+
- -
110+
- Storage removal mode: ``REMOVE_ATTEMPTED`` removes delivered+drop-limited bits, ``REMOVE_DELIVERED_ONLY`` removes only successfully delivered bits.
107111
* - ``requireFullPacket``
108112
- ``True``
109113
- bool
110114
- If ``True``, downlink waits until selected storage has at least one full packet.
111115

116+
Configuration Interface and Validation
117+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
118+
119+
The module exposes validated setters in C++/Python:
120+
121+
- ``setBitRateRequest(bitRateRequest)`` with :math:`bitRateRequest \ge 0`
122+
- ``setPacketSizeBits(packetSizeBits)`` with :math:`packetSizeBits > 0`
123+
- ``setMaxRetransmissions(maxRetransmissions)`` with :math:`maxRetransmissions \ge 1`
124+
- ``setReceiverAntenna(receiverAntenna)`` with ``receiverAntenna in {0,1,2}``
125+
- ``setRemovalPolicy(removalPolicy)`` with ``removalPolicy in {0,1}``
126+
- ``setRequireFullPacket(requireFullPacket)``
127+
128+
If a setter receives an invalid value, the module rejects it and keeps the last valid value.
129+
The Python wrapper also maps ``bitRateRequest``, ``packetSizeBits``, ``maxRetransmissions``,
130+
``receiverAntenna``, ``removalPolicy``, and ``requireFullPacket`` to these validated setter/getter paths.
131+
112132
Receiver Selection and CNR1/CNR2 Usage
113133
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
114134
The module uses receiver-specific fields from :ref:`LinkBudgetMsgPayload`:
@@ -222,11 +242,21 @@ Final rates:
222242
.. math::
223243
224244
R_{\mathrm{attempt}} = s\,R_{\mathrm{attempt,pot}}, \quad
225-
R_{\mathrm{remove}} = s\,R_{\mathrm{remove,pot}}, \quad
245+
R_{\mathrm{remove,modeled}} = s\,R_{\mathrm{remove,pot}}, \quad
226246
R_{\mathrm{delivered}} = s\,R_{\mathrm{delivered,pot}}, \quad
227247
R_{\mathrm{dropped}} = s\,R_{\mathrm{dropped,pot}}
228248
229-
The value written to storage through ``nodeDataOutMsg`` is:
249+
Actual storage removal follows ``removalPolicy``:
250+
251+
.. math::
252+
253+
R_{\mathrm{remove}} =
254+
\begin{cases}
255+
R_{\mathrm{remove,modeled}}, & \text{REMOVE\_ATTEMPTED} \\
256+
R_{\mathrm{delivered}}, & \text{REMOVE\_DELIVERED\_ONLY}
257+
\end{cases}
258+
259+
The value written to storage through ``nodeDataOutMsg`` is then:
230260

231261
.. math::
232262
@@ -236,7 +266,7 @@ Output Diagnostics
236266
------------------
237267
The custom output :ref:`DownlinkHandlingMsgPayload` reports:
238268

239-
- link/selection state (``linkActive``, ``receiverIndex``, antenna names)
269+
- link/selection state (``linkActive``, ``receiverIndex``, antenna names, ``removalPolicy``)
240270
- physical-layer quality terms (CNR, :math:`C/N_0`, :math:`E_b/N_0`, BER, PER)
241271
- ARQ reliability terms (success/drop probabilities, expected attempts)
242272
- rate terms (attempted, removed, delivered, dropped)
@@ -252,6 +282,12 @@ Typical chain:
252282
3. :ref:`downlinkHandling` converts link quality to effective data transfer and storage removal.
253283
4. Storage modules consume ``nodeDataOutMsg`` and reduce onboard buffered data.
254284

285+
.. warning::
286+
287+
Also important integration note:
288+
Do not run ``spaceToGroundTransmitter`` and ``downlinkHandling`` as competing downlink removers
289+
on the same storage partitions. Pick one downlink path.
290+
255291
This separation is useful for fault modeling: upstream RF degradation (pointing, frequency mismatch,
256292
atmospheric attenuation, receive-state changes) naturally propagates into BER/PER and delivered data.
257293

@@ -263,7 +299,9 @@ Assumptions and Current Limits
263299
- Any bit error fails the packet.
264300
- ARQ is expectation-based, not packet-by-packet Monte Carlo.
265301
- 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.
302+
- ``REMOVE_DELIVERED_ONLY`` preserves dropped/undelivered bits onboard, but the module still uses an expected-rate ARQ model instead of explicit packet ACK/NACK timelines.
303+
- Storage target selection prioritizes per-partition values. ``storageLevel`` is only used as fallback for messages that do not provide ``storedData`` entries.
304+
- ``nodeDataOutMsg`` identifies storage by ``dataName`` only. If multiple linked storage units reuse the selected partition name, downlinkHandling forces removal to zero for that step to avoid ambiguous multi-unit draining. For multi-storage use, keep partition names globally unique across linked storage units.
267305

268306
Unit Test Coverage
269307
------------------
@@ -276,22 +314,29 @@ The tests verify:
276314
- equation parity versus a Python-equivalent BER/PER/ARQ model
277315
- zero-flow behavior for invalid link inputs
278316
- retry-cap effects on drop probability and removal/delivery behavior
317+
- removal-policy behavior (``REMOVE_ATTEMPTED`` vs ``REMOVE_DELIVERED_ONLY``)
279318
- storage-limited rate capping and drain behavior
280319
- automatic receiver selection from antenna RX states and CNR values
320+
- duplicate-storage input rejection
321+
- storage-target selection across multiple storage status messages
322+
- ambiguous duplicate partition-name behavior across multiple storage status messages
323+
324+
User Guide
325+
----------
281326

282-
Usage Snippet
283-
-------------
327+
Basic setup example:
284328

285329
.. code-block:: python
286330
287331
from Basilisk.simulation import downlinkHandling, simpleStorageUnit
288332
289333
dlh = downlinkHandling.DownlinkHandling()
290-
dlh.bitRateRequest = 1.0e5 # bit/s
291-
dlh.packetSizeBits = 1024.0 # bit
292-
dlh.maxRetransmissions = 8
293-
dlh.receiverAntenna = 0 # auto-select valid RX path with highest CNR
294-
dlh.requireFullPacket = True
334+
dlh.setBitRateRequest(1.0e5) # [bit/s]
335+
dlh.setPacketSizeBits(1024.0) # [bit]
336+
dlh.setMaxRetransmissions(8) # [-]
337+
dlh.setReceiverAntenna(0) # [-] auto-select valid RX path with highest CNR
338+
dlh.setRemovalPolicy(0) # [-] 0=REMOVE_ATTEMPTED, 1=REMOVE_DELIVERED_ONLY
339+
dlh.setRequireFullPacket(True) # [-]
295340
296341
storage = simpleStorageUnit.SimpleStorageUnit()
297342
storage.storageCapacity = int(8e9)

0 commit comments

Comments
 (0)