-
Notifications
You must be signed in to change notification settings - Fork 131
Link Budget Plugin #1242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Link Budget Plugin #1242
Conversation
This commit implements a fully functional Link Budget Plugin that provides: Core Features: - Real-time RF link analysis (uplink/downlink budgets) - Free Space Path Loss (FSPL) calculations - EIRP, G/T, C/N0 calculations - Link margin analysis with visual indicators - Data rate calculations based on range and link quality - Next pass prediction and analysis - Total data volume calculations per pass - CSV export for pass data Technical Implementation: - link-budget-math.ts: Complete RF mathematics module - FSPL calculations - EIRP and received power - C/N0 and link margin - Shannon capacity and data rate - Elevation-dependent atmospheric losses - Antenna gain patterns and pointing loss - link-budget.ts: Main plugin with UI - Requires satellite and sensor selection - Interactive parameter inputs (frequencies, power, gains) - Real-time link budget display - Pass prediction with 10-second sampling - Visual status indicators (✓/⚠/✗) - Frequency band presets (UHF, S-band, X-band) - Auto-update mode for time propagation - CSV export functionality Unique Value Proposition: Users can instantly determine if a satellite communication link is viable, what data rate is achievable, and how much data can be transferred during a pass - critical for mission planning and amateur radio operations. Plugin registered in plugin system and configuration.
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| export function calculateCNo(eirp: number, fspl: number, gt: number, losses: number): number { | ||
| // C/N0 = EIRP - FSPL + G/T - k - Losses | ||
| // where k is Boltzmann's constant in dB(W/K/Hz) | ||
| return eirp - fspl + gt - BOLTZMANN_CONSTANT_DBW - losses; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert EIRP to dBW before C/N0 computation
The C/N0 calculation uses calculateEIRP’s dBm output directly with Boltzmann’s constant expressed in dBW/Hz/K, so the returned C/N0 is inflated by ~30 dB. Every link budget and viability check will report far more margin and data rate than the RF conditions support because EIRP is not converted to dBW before subtracting BOLTZMANN_CONSTANT_DBW.
Useful? React with 👍 / 👎.
| for (let t = 0; t < maxLookAhead; t += dt) { | ||
| const time = startTime.roll(t * 1000 as Milliseconds); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import Milliseconds before using startTime.roll
The pass search calls startTime.roll(t * 1000 as Milliseconds) but Milliseconds is never imported or declared in this module, so TypeScript will fail to compile with “Cannot find name ‘Milliseconds’”. The new plugin won’t build until the time unit type is brought into scope.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a comprehensive Link Budget Plugin for KeepTrack that provides RF link budget analysis capabilities for satellite-to-ground station communications. The plugin calculates uplink and downlink performance, predicts signal strength, determines data rates, and analyzes total data volume during satellite passes.
Key Changes
- New Link Budget Plugin with real-time RF link analysis for uplink and downlink communications
- Mathematical library for link budget calculations including FSPL, EIRP, C/N0, and data rate computations
- Pass analysis feature that integrates data rates over time to predict total data volume per pass
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/plugins/plugins.ts | Registers the new LinkBudgetPlugin in the plugin manager |
| src/plugins/link-budget/link-budget.ts | Main plugin implementation with UI, event handling, and integration with orbital mechanics |
| src/plugins/link-budget/link-budget-math.ts | RF mathematics module with link budget equations and calculations |
| src/plugins/keeptrack-plugins-configuration.ts | Adds LinkBudgetPlugin to the configuration type definitions |
| docs/link-budget-plugin-plan.md | Comprehensive implementation plan and technical documentation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import { getEl } from '@app/engine/utils/get-el'; | ||
| import { saveCsv } from '@app/engine/utils/saveVariable'; | ||
| import { showLoading } from '@app/engine/utils/showLoading'; | ||
| import { Degrees, DetailedSatellite, DetailedSensor, eci2rae, EpochUTC, Seconds } from '@ootk/src/main'; |
Copilot
AI
Nov 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing type import: The Milliseconds type is used at line 724 but is not imported from '@ootk/src/main'. Add Milliseconds to the import statement at line 16.
| import { Degrees, DetailedSatellite, DetailedSensor, eci2rae, EpochUTC, Seconds } from '@ootk/src/main'; | |
| import { Degrees, DetailedSatellite, DetailedSensor, eci2rae, EpochUTC, Seconds, Milliseconds } from '@ootk/src/main'; |
| // Secondary menu (satellite) | ||
| this.params_.satTxPower = parseFloat((getEl('sat-tx-power') as HTMLInputElement)?.value || '5'); | ||
| this.params_.satTxGain = parseFloat((getEl('sat-tx-gain') as HTMLInputElement)?.value || '3'); | ||
| this.params_.satRxGain = parseFloat((getEl('sat-rx-gain') as HTMLInputElement)?.value || '2'); |
Copilot
AI
Nov 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect parameter mapping: gsNoiseFigure is being read from the 'link-eb-no' input element, but should be read from a noise figure input field. The current code reads the Eb/N0 requirement value and assigns it to the noise figure parameter, which is incorrect. This will cause inaccurate link budget calculations.
| const uplinkFspl = calculateFSPL(range, params.satFreqUp); | ||
| const uplinkRxPower = uplinkEirp - uplinkFspl + params.satRxGain - totalLosses; | ||
| // Assume satellite system temperature of 500K (typical) | ||
| const satGT = calculateGT(params.satRxGain, 500); |
Copilot
AI
Nov 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Hardcoded satellite system temperature: The satellite system temperature is hardcoded to 500K at line 298. This value should be configurable as a parameter in LinkBudgetParams similar to gsSystemTemp, as different satellites may have significantly different system temperatures affecting uplink calculations.
|
|
||
| this.passAnalysis_ = passData; | ||
| this.displayPassAnalysis_(passData); | ||
|
|
Copilot
AI
Nov 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential type safety issue: The expression t * 1000 as Milliseconds may not parse as intended due to operator precedence. The as operator has lower precedence than multiplication, so this could be interpreted as t * (1000 as Milliseconds). Use parentheses for clarity: (t * 1000) as Milliseconds.
| * Analyze next pass and calculate data volume | ||
| */ | ||
| // eslint-disable-next-line require-await |
Copilot
AI
Nov 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Missing input validation: The findNextPass_ method could return null if no pass is found, but the result is checked at line 689. However, if an empty pass is found (samples.length === 0 at line 760), the function returns null correctly. The error message at line 690 should be more user-friendly and could be extracted to a constant or displayed via a proper notification mechanism rather than directly manipulating innerHTML.
| */ | ||
| // eslint-disable-next-line require-await |
Copilot
AI
Nov 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing null safety: At line 690, getEl('link-pass-analysis')! uses the non-null assertion operator (!), but if the element doesn't exist, this will throw a runtime error. Similarly at line 691. Consider adding a null check before manipulating the element.
| import { ClickDragOptions, KeepTrackPlugin } from '@app/engine/plugins/base-plugin'; | ||
| import { html } from '@app/engine/utils/development/formatter'; | ||
| import { getEl } from '@app/engine/utils/get-el'; | ||
| import { saveCsv } from '@app/engine/utils/saveVariable'; |
Copilot
AI
Nov 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import EciVec3.
| import { saveCsv } from '@app/engine/utils/saveVariable'; |
| import { saveCsv } from '@app/engine/utils/saveVariable'; | ||
| import { showLoading } from '@app/engine/utils/showLoading'; | ||
| import { Degrees, DetailedSatellite, DetailedSensor, eci2rae, EpochUTC, Seconds } from '@ootk/src/main'; | ||
| import satcomPng from '@public/img/icons/satcom.png'; |
Copilot
AI
Nov 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import SensorMath.
| import satcomPng from '@public/img/icons/satcom.png'; |
|



No description provided.