Context
SpecularCoverage.calculate_coverage returns List[Tuple[DiscreteCoverageTP, List[float]]], one tuple per GNSS transmitter. get_topk_coverage returns the same tuple type but one entry per rank (best-first by RCG, selected per time step). Because the selected transmitter varies per time step, get_topk_coverage currently drops transmitter identity entirely — unlike its trajectory-domain twin specular.get_topk_trajectories, which returns selected_ids_by_time.
To recover identity, Mission.execute_gnssr_coverage_calculator (added for the topk feature) re-ranks the same RCGs through get_topk_trajectories, feeding it a throwaway placeholder PositionSeries purely as a vehicle. This works (both functions use identical ranking logic), but it's a workaround that couples coverage to the trajectory API and is non-obvious.
Proposal
- Have
get_topk_coverage accept ids and return the selected transmitter id per (time, rank) directly — mirroring get_topk_trajectories.
- Replace the ad-hoc
(DiscreteCoverageTP, List[float]) tuple with a single, shared return type (e.g. a small dataclass carrying coverage, rcg, and optionally transmitter_id(s)) used by both calculate_coverage and get_topk_coverage, so consumers handle one consistent structure.
- Simplify
Mission.execute_gnssr_coverage_calculator to use the new IDs directly and drop the placeholder-PositionSeries workaround.
Acceptance criteria
Related: orbitpy/coveragecalculator.py (SpecularCoverage), orbitpy/specular.py (get_topk_trajectories), orbitpy/mission.py (execute_gnssr_coverage_calculator).
Context
SpecularCoverage.calculate_coveragereturnsList[Tuple[DiscreteCoverageTP, List[float]]], one tuple per GNSS transmitter.get_topk_coveragereturns the same tuple type but one entry per rank (best-first by RCG, selected per time step). Because the selected transmitter varies per time step,get_topk_coveragecurrently drops transmitter identity entirely — unlike its trajectory-domain twinspecular.get_topk_trajectories, which returnsselected_ids_by_time.To recover identity,
Mission.execute_gnssr_coverage_calculator(added for thetopkfeature) re-ranks the same RCGs throughget_topk_trajectories, feeding it a throwaway placeholderPositionSeriespurely as a vehicle. This works (both functions use identical ranking logic), but it's a workaround that couples coverage to the trajectory API and is non-obvious.Proposal
get_topk_coverageacceptidsand return the selected transmitter id per(time, rank)directly — mirroringget_topk_trajectories.(DiscreteCoverageTP, List[float])tuple with a single, shared return type (e.g. a small dataclass carryingcoverage,rcg, and optionallytransmitter_id(s)) used by bothcalculate_coverageandget_topk_coverage, so consumers handle one consistent structure.Mission.execute_gnssr_coverage_calculatorto use the new IDs directly and drop the placeholder-PositionSeriesworkaround.Acceptance criteria
get_topk_coveragereturns, or makes available, the transmitter id behind each rank at each time step.calculate_coverageandget_topk_coverageshare one documented return type.PositionSerieshack inmission.pyis removed.dshield-cygnss-demoexample anddshield_format_converterare updated to the new type.Related:
orbitpy/coveragecalculator.py(SpecularCoverage),orbitpy/specular.py(get_topk_trajectories),orbitpy/mission.py(execute_gnssr_coverage_calculator).