fix(sat): LilacSat-2 keeps its FM transponder
Shipped with nothing but an APRS digipeater on 144.390, which is not what anybody works that satellite on. The FM transponder — 144.350 up, 437.200 down — was dropped by the generator, correctly by its own rule: SatNOGS marks that transmitter inactive. And SatNOGS is not wrong. LilacSat-2's transponder is switched on to an announced schedule rather than left running, and from a database a scheduled transponder looks exactly like a dead one. The judgement belongs to whoever reads the diff, not to the filter. So the transponder goes back in, labelled "(scheduled)" the way PO-101 already is, and the satellite takes its OSCAR name, LO-90, with LILACSAT-2 and CAS-3H as aliases so the element feeds still meet it. The generator now reports what it refused on that ground and kept nothing else for — one line per satellite, phrased as a question. Reviving every inactive transponder would fill the list with birds that answer nothing; saying nothing is how this one shipped wrong. There is no third option that a filter can decide on its own. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
@@ -140,6 +140,23 @@ func main() {
|
||||
}
|
||||
byNORAD[t.NORAD] = append(byNORAD[t.NORAD], t)
|
||||
}
|
||||
// A satellite whose only WORKABLE path is one SatNOGS calls inactive.
|
||||
//
|
||||
// LilacSat-2 is the case that taught this: its FM transponder (144.350 up,
|
||||
// 437.200 down) is marked inactive because it runs on an announced schedule
|
||||
// rather than continuously, so the generator dropped it and shipped the
|
||||
// satellite with nothing but an APRS digipeater. An operator comparing
|
||||
// against any other tracker then finds a frequency plan missing the only
|
||||
// thing anybody works that bird on.
|
||||
//
|
||||
// Not fixed automatically: "inactive" is right far more often than it is
|
||||
// wrong, and reviving every dead transponder would fill the list with
|
||||
// satellites that answer nothing. It is REPORTED, so the next regeneration
|
||||
// is read with this in front of it and the handful worth curating are
|
||||
// curated — a scheduled transponder belongs in the plan with "(scheduled)"
|
||||
// in its label, the way PO-101 and now LO-90 carry it.
|
||||
reportRefused(txs, feed, covered, byNORAD)
|
||||
|
||||
added := 0
|
||||
for n, list := range byNORAD {
|
||||
b := sat.Bird{Name: displayName(feed[n]), NORAD: n}
|
||||
@@ -442,3 +459,34 @@ func die(err error) {
|
||||
fmt.Fprintln(os.Stderr, "satgen:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// reportRefused names the satellites whose only two-way path was refused for
|
||||
// being inactive, so the operator running this can decide about each one.
|
||||
//
|
||||
// The output is deliberately a question and not a change: SatNOGS calling a
|
||||
// transponder inactive is usually correct, and the exceptions are the birds
|
||||
// whose transponder is switched on to a schedule rather than left running.
|
||||
func reportRefused(txs []transmitter, feed map[int]string, covered map[int]bool, kept map[int][]transmitter) {
|
||||
var lines []string
|
||||
for _, t := range txs {
|
||||
if t.Status == "active" || t.UplinkLow <= 0 || t.DownlinkLow <= 0 {
|
||||
continue
|
||||
}
|
||||
if feed[t.NORAD] == "" || covered[t.NORAD] || len(kept[t.NORAD]) > 0 {
|
||||
continue
|
||||
}
|
||||
lines = append(lines, fmt.Sprintf(" ? %5d %-22s %-4s %.3f up / %.3f down %q",
|
||||
t.NORAD, displayName(feed[t.NORAD]), adifMode(t.Mode),
|
||||
float64(t.UplinkLow)/1e6, float64(t.DownlinkLow)/1e6, t.Description))
|
||||
}
|
||||
if len(lines) == 0 {
|
||||
return
|
||||
}
|
||||
sort.Strings(lines)
|
||||
fmt.Println("\nRefused as inactive, and nothing else was kept for these satellites.")
|
||||
fmt.Println("A transponder that runs to a schedule looks exactly like a dead one here:")
|
||||
for _, l := range lines {
|
||||
fmt.Println(l)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user