Skip to content

Conversation

@thkruz
Copy link
Owner

@thkruz thkruz commented Nov 16, 2025

No description provided.

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.
Copilot AI review requested due to automatic review settings November 16, 2025 23:49
@CLAassistant
Copy link

CLAassistant commented Nov 16, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ thkruz
❌ claude
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a 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".

Comment on lines +215 to +218
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;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines 723 to 724
for (let t = 0; t < maxLookAhead; t += dt) {
const time = startTime.roll(t * 1000 as Milliseconds);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Copy link
Contributor

Copilot AI left a 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';
Copy link

Copilot AI Nov 16, 2025

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.

Suggested change
import { Degrees, DetailedSatellite, DetailedSensor, eci2rae, EpochUTC, Seconds } from '@ootk/src/main';
import { Degrees, DetailedSatellite, DetailedSensor, eci2rae, EpochUTC, Seconds, Milliseconds } from '@ootk/src/main';

Copilot uses AI. Check for mistakes.
// 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');
Copy link

Copilot AI Nov 16, 2025

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.

Copilot uses AI. Check for mistakes.
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);
Copy link

Copilot AI Nov 16, 2025

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.

Copilot uses AI. Check for mistakes.

this.passAnalysis_ = passData;
this.displayPassAnalysis_(passData);

Copy link

Copilot AI Nov 16, 2025

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.

Copilot uses AI. Check for mistakes.
Comment on lines +689 to +691
* Analyze next pass and calculate data volume
*/
// eslint-disable-next-line require-await
Copy link

Copilot AI Nov 16, 2025

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.

Copilot uses AI. Check for mistakes.
Comment on lines +690 to +691
*/
// eslint-disable-next-line require-await
Copy link

Copilot AI Nov 16, 2025

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.

Copilot uses AI. Check for mistakes.
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';
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import EciVec3.

Suggested change
import { saveCsv } from '@app/engine/utils/saveVariable';

Copilot uses AI. Check for mistakes.
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';
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import SensorMath.

Suggested change
import satcomPng from '@public/img/icons/satcom.png';

Copilot uses AI. Check for mistakes.
@thkruz thkruz merged commit a6d41b2 into develop Nov 17, 2025
2 of 4 checks passed
@thkruz thkruz deleted the claude/link-budget-plugin-plan-01FssRrnyxz9m4sGnyErBBXo branch November 17, 2025 00:04
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants