iridium wideband: matched filter on by default (~17x IDA yield)#172
Conversation
Round 2 of the Iridium sensitivity campaign (vs gr-iridium A/B). The ~50x yield gap is the per-burst demod's acquisition, not detection. Adding a root-raised-cosine matched filter (matched to Iridium's RRC transmit pulse, gr-iridium-style, alpha 0.4) to the wideband extract path lifts CRC-OK IDA yield ~17x on the real benchmark capture (10 -> 171 over 300s; 35% of gr-iridium's 484, up from ~2%). It is opt-in (XNG_IRIDIUM_RC_ALPHA=0.4) for now: the strict UW-cost/timing acquisition still drops some *clean* high-SNR bursts after filtering (it was tuned for unfiltered input), which regresses the synthetic/fixture wideband tests. Default off keeps those green. Round 3 re-tunes the demod for matched-filtered input, then makes it default. Also adds env tuning knobs for the campaign (defaults preserve current behavior): XNG_IRIDIUM_UWCOST, XNG_IRIDIUM_GATE, XNG_IRIDIUM_DEDUP_BINS, XNG_IRIDIUM_THRESHOLD, XNG_IRIDIUM_RC_ALPHA. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…7x IDA) Round 4 of the sensitivity campaign. The RRC matched filter (Round 2) lifts CRC-OK IDA yield ~17x on real captures but slightly raises the UW-acquisition cost on *clean* high-SNR bursts, which regressed the fixture tests when it was applied unconditionally. Fix: in the wideband extract path, demodulate the *unfiltered* burst first and fall back to the matched-filtered burst only when the clean path finds nothing. Strong bursts decode unfiltered (bit-exact, no MF penalty); weak bursts the clean path misses get the matched filter's few-dB lift above the acquisition gate. Net: no regression on strong bursts, big gain on weak ones — so the matched filter is now ON BY DEFAULT (XNG_IRIDIUM_RC_ALPHA=0 disables it). Measured on the real benchmark capture: ~10 -> 171 CRC-OK IDA over 300s (35% of gr-iridium's 484, up from ~2%); full iridium + workspace test suites green. Live soak (Airspy R2) showed IDA climb 2.8 -> ~18/min after enabling it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughTwo Iridium mode crates receive configurable tuning parameters sourced from environment variables. ChangesIridium Configurable Parameters and Matched-Filter
Sequence Diagram(s)sequenceDiagram
participant Env as Env Vars
participant IridiumWideband as IridiumWideband::new
participant extract as extract()
participant matched_filter as matched_filter()
participant demod_channel as demod_channel()
participant IridiumDemod as IridiumDemod
IridiumWideband->>Env: XNG_IRIDIUM_DET, XNG_IRIDIUM_DEDUP, XNG_IRIDIUM_RC_ALPHA
Env-->>IridiumWideband: det_threshold, dedup_bins, mf_taps
Note over IridiumWideband: hot-bin check uses det_threshold<br/>dedup uses dedup_bins
extract->>demod_channel: raw channel samples + freq_offset
demod_channel->>IridiumDemod: seed with 20th-pct noise estimate
IridiumDemod-->>demod_channel: Option<Burst>
demod_channel-->>extract: None
alt mf_taps non-empty
extract->>matched_filter: channel samples + mf_taps
matched_filter-->>extract: filtered samples
extract->>demod_channel: filtered samples + freq_offset
demod_channel-->>extract: Option<Burst>
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test.parsed`:
- Around line 1-2: The file test.parsed at the repository root is diagnostic
output from a failed parse that was accidentally committed. Remove this file
from the repository by deleting it. Alternatively, if test.parsed is generated
during test runs as a diagnostic artifact, add it to the .gitignore file instead
to prevent future accidental commits. The proper location for test fixtures and
data is crates/xng-mode-iridium/tests/data/ with appropriate documentation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a87301a3-3c52-4972-a51b-9d6ffb94ce77
📒 Files selected for processing (3)
crates/xng-mode-iridium/src/demod.rscrates/xng-mode-iridium/src/wideband.rstest.parsed
| ERR: ERR:Message: Couldn't parse: fft_burst_tagger :info: set_min_output_buffer on block 2 to 65536 | ||
| RAW: p-1601421246-e000 000000599.9996 1622000000 100% -17.36|-080.05|32.12 179 DL <001100000011000011110011> 0100000000000011 0000000000000101 0000000000111100 0000000001000100 0000001100110000 0000010101010000 0011111111000000 0100000001000011 0000001100000101 0000010100111100 0011110001000100 0100011100110011 0011010101010101 0110111111111111 1000000000000011 0100000000000110 0000000000111001 0000000001111000 0000001101110100 0000011001100000 0011101010010000 0111111110000011 010000 ERR:IridiumMessage: unknown Iridium message type |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if test.parsed is referenced in tests or documentation
rg -l 'test\.parsed' --type rust --type md
# Check if there's a gitignore entry for similar files
cat .gitignore 2>/dev/null | grep -i 'parsed\|test\.' || echo "No matching gitignore entries"
# Check if this file pattern appears elsewhere
fd -e parsedRepository: airframesio/xng
Length of output: 101
🏁 Script executed:
#!/bin/bash
# Find the exact location of test.parsed
find . -name 'test.parsed' -type f
# Check the directory structure around it
if [ -f test.parsed ]; then
ls -la test.parsed
head -n 5 test.parsed
fi
# Look for test infrastructure/fixtures directories
fd -t d 'test|fixture|spec' | head -20
# Check if there's a tests directory and what's in it
if [ -d tests ]; then
ls -la tests/ | head -20
fi
# Check for test configuration files
fd -e toml -e yaml -e yml | grep -i test || trueRepository: airframesio/xng
Length of output: 1024
🏁 Script executed:
#!/bin/bash
# Check the iridium test directory since the file contains Iridium message data
if [ -d crates/xng-mode-iridium/tests ]; then
ls -la crates/xng-mode-iridium/tests/
echo "---"
# Look for any references to "test.parsed" in iridium tests
grep -r 'test\.parsed' crates/xng-mode-iridium/ 2>/dev/null || echo "No references found"
fi
# Check git status and history for this file
echo "=== Git info for test.parsed ==="
git log --oneline test.parsed 2>/dev/null | head -5 || echo "No git history"
git status test.parsed 2>/dev/null || echo "Not in git"
# Check if there are other fixture files or expected output files
fd -e txt -e out -e expected -e fixture | grep -i testRepository: airframesio/xng
Length of output: 804
🏁 Script executed:
#!/bin/bash
# Check what's in the data directory
echo "=== Contents of crates/xng-mode-iridium/tests/data ==="
ls -la crates/xng-mode-iridium/tests/data/
# Look for fixture/test data files with similar patterns
echo "=== Looking for similar test data files ==="
find crates/xng-mode-iridium/tests -type f | head -20
# Check if test.parsed at root is related to iridium by searching for usage in test files
echo "=== Checking test files for parsing or expected output patterns ==="
grep -r "\.parsed\|test_.*output\|expected.*message" crates/xng-mode-iridium/tests/*.rs 2>/dev/null | head -10
# Check the commit that added test.parsed to understand context
git show 614269f --stat 2>/dev/null | head -20Repository: airframesio/xng
Length of output: 1974
🏁 Script executed:
#!/bin/bash
# Check if there's any reference to "test.parsed" in all source files
echo "=== All references to test.parsed or similar patterns ==="
grep -r "test\.parsed\|\.parsed" --include="*.rs" --include="*.toml" --include="*.md" . 2>/dev/null | head -20
# Look at the iridium test data README to understand the test setup
echo "=== Test data README ==="
cat crates/xng-mode-iridium/tests/data/README.md
# Check if there's documentation in the root or main crates about test outputs
echo "=== Root level test-related files ==="
ls -la | grep -i test
# Check Cargo.toml for test configuration
echo "=== Cargo.toml in xng-mode-iridium ==="
head -30 crates/xng-mode-iridium/Cargo.tomlRepository: airframesio/xng
Length of output: 1555
Remove accidentally committed test output file.
test.parsed is diagnostic parse failure output at the repository root with no documentation, no references in tests or source code, and no gitignore entry. It does not belong in the repository. The project maintains proper test fixtures in crates/xng-mode-iridium/tests/data/ with documentation (see README.md); this file should either be deleted or added to .gitignore if it's generated during test runs.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test.parsed` around lines 1 - 2, The file test.parsed at the repository root
is diagnostic output from a failed parse that was accidentally committed. Remove
this file from the repository by deleting it. Alternatively, if test.parsed is
generated during test runs as a diagnostic artifact, add it to the .gitignore
file instead to prevent future accidental commits. The proper location for test
fixtures and data is crates/xng-mode-iridium/tests/data/ with appropriate
documentation.
Round 2+4 of the Iridium wideband sensitivity campaign (vs a gr-iridium A/B on identical IQ). The ~50x burst-yield gap is the per-burst demod, not detection.
Change
Adds a root-raised-cosine matched filter (matched to Iridium's RRC transmit pulse; gr-iridium uses RRC α0.4, 51 taps) to the wideband extract path, reusing
modulate::rrc_taps.It's applied as a fallback: demodulate the unfiltered burst first, fall back to the matched-filtered burst only when the clean path finds nothing. Strong/clean bursts decode unfiltered (bit-exact, no penalty — keeps the fixture tests green); weak bursts the clean path misses get the matched filter's few-dB lift above the acquisition gate. So it's on by default with no regression (
XNG_IRIDIUM_RC_ALPHA=0disables).Measured (real benchmark capture, 300s, Airspy R2 @ 1622 MHz/10 MS/s)
Live soak confirmed IDA climbing 2.8 → ~18/min after enabling it.
Also adds env tuning knobs for the ongoing campaign (defaults preserve behavior):
XNG_IRIDIUM_RC_ALPHA,XNG_IRIDIUM_UWCOST,XNG_IRIDIUM_GATE,XNG_IRIDIUM_DEDUP_BINS,XNG_IRIDIUM_THRESHOLD.Testing
xng-mode-iridiumsuite green (incl. the wideband fixture/synthetic tests that pinned clean-burst decode).Next rounds will push further toward gr-iridium's yield (demod acquisition: correlation-based UW, finer timing).
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Improvements