package tle import ( "fmt" "math" "strconv" "strings" ) // NewTLE creates a new TLE object from a given TLE string func NewTLE(RawTLE string) (TLE, error) { // split the TLE var SplitTLE = strings.Split(RawTLE, "\n") lineOne, err := parseLineOne(SplitTLE) if err != nil { fmt.Println(err) } lineTwo, err := parseLineTwo(SplitTLE) if err != nil { fmt.Println(err) } // fill the generatedTLE struct var generatedTLE TLE = TLE{ TitleLine: TitleLine{ Satname: fmt.Sprintf("%-24s", SplitTLE[0][0:24]), }, LineOne: lineOne, LineTwo: lineTwo, } return generatedTLE, nil } func parseLineOne(SplitTLE []string) (LineOne, error) { // parse the line number LineOneLinenumber, err := strconv.Atoi(string(SplitTLE[1][0])) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the line number", SplitTLE[1][1], err) } // Parse the Satellite Number SatelliteNumber, err := strconv.Atoi(SplitTLE[1][2:7]) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Satellite Number", SplitTLE[1][2:7], err) } // Parse the launch year LaunchYear, err := strconv.Atoi(SplitTLE[1][9:11]) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Launch Year", SplitTLE[1][9:11], err) } // Parse the launch number LaunchNumber, err := strconv.Atoi(SplitTLE[1][11:14]) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Launch Number", SplitTLE[1][11:14], err) } // Parse the launch number LaunchPiece := strings.TrimSpace(SplitTLE[1][14:16]) // Parse the epoch year EpochYear, err := strconv.Atoi(SplitTLE[1][18:20]) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Epoch Year", SplitTLE[1][18:20], err) } // Parse the epoch day fraction EpochDayFraction, err := strconv.ParseFloat(SplitTLE[1][20:32], 64) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Epoch Day Fraction", SplitTLE[1][20:32], err) } // Parse the First Time Derivative of the Mean Motion RawFirstDeriv := strings.TrimSpace(SplitTLE[1][33:43]) FirstDeriv, err := strconv.ParseFloat(RawFirstDeriv, 64) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the First Time Derivative of the Mean Motion", SplitTLE[1][33:43], err) } /* Parse the Second Time Derivative of the Mean Motion */ RawSecondDerivBase := strings.TrimSpace(SplitTLE[1][44:50]) SecondDerivBase, err := strconv.Atoi(RawSecondDerivBase) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Second Time Derivative of the Mean Motion Base", SplitTLE[1][44:50], err) } RawSecondDerivPower := strings.TrimSpace(SplitTLE[1][50:52]) SecondDerivPower, err := strconv.Atoi(RawSecondDerivPower) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Second Time Derivative of the Mean Motion Power", SplitTLE[1][50:52], err) } // This converts the following format: (67960-4 = 0.000067960) // Also: (00000-0 = 0.00000) SecondDeriv := float64(SecondDerivBase) / math.Pow(10, (-1*float64(SecondDerivPower))+5) /* Parse the Second Time Derivative of the Mean Motion */ RawBSTARBase := strings.TrimSpace(SplitTLE[1][53:59]) BSTARBase, err := strconv.Atoi(RawBSTARBase) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the BSTAR Drag Term Base", SplitTLE[1][53:59], err) } RawBSTARPower := strings.TrimSpace(SplitTLE[1][59:61]) BSTARPower, err := strconv.Atoi(RawBSTARPower) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the BSTAR Drag Term Power", SplitTLE[1][59:61], err) } // This converts the following format: (67960-4 = 0.000067960) // Also: (00000-0 = 0.00000) BSTAR := float64(BSTARBase) / math.Pow(10, (-1*float64(BSTARPower))+5) // Parse the Element set number RawElementSetNumber := strings.TrimSpace(SplitTLE[1][64:68]) ElementSetNumber, err := strconv.Atoi(RawElementSetNumber) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Element set number", SplitTLE[1][64:68], err) } // Parse the Number Zero NumberZero, err := strconv.Atoi(string(SplitTLE[1][62])) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the number zero", SplitTLE[1][62], err) } // Parse the Checksum Checksum, err := strconv.Atoi(string(SplitTLE[1][68])) if err != nil { return LineOne{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the checksum", SplitTLE[1][68], err) } newLineOne := LineOne{ Linenumber: LineOneLinenumber, SatelliteNumber: SatelliteNumber, Classification: string(SplitTLE[1][7]), InternationalDesignator: InternationalDesignator{ Launchyear: LaunchYear, Launchnumber: LaunchNumber, Launchpiece: LaunchPiece, }, Epoch: Epoch{ Year: EpochYear, Dayfraction: EpochDayFraction, }, Firstderiv: FirstDeriv, Secondderiv: SecondDeriv, BSTAR: BSTAR, Numberzero: NumberZero, ElementSetNumber: ElementSetNumber, Checksum: Checksum, } return newLineOne, nil } func parseLineTwo(SplitTLE []string) (LineTwo, error) { // parse the line number LineTwoLinenumber, err := strconv.Atoi(string(SplitTLE[2][0])) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the line number", SplitTLE[2][0], err) } // Parse the Satellite Number SatelliteNumber, err := strconv.Atoi(SplitTLE[1][2:7]) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Satellite Number", SplitTLE[1][2:7], err) } // Parse the Inclination RawInclination := strings.TrimSpace(SplitTLE[2][9:16]) Inclination, err := strconv.ParseFloat(RawInclination, 64) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Inclination", SplitTLE[2][6:19], err) } // Parse the RightAscensionOfTheAscendingNode RawRightAscensionOfTheAscendingNode := strings.TrimSpace(SplitTLE[2][17:25]) RightAscensionOfTheAscendingNode, err := strconv.ParseFloat(RawRightAscensionOfTheAscendingNode, 64) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the RightAscensionOfTheAscendingNode", SplitTLE[2][17:25], err) } // Parse the Eccentricity RawEccentricity := strings.TrimSpace(SplitTLE[2][26:33]) Eccentricity, err := strconv.ParseFloat(RawEccentricity, 64) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the Eccentricity", SplitTLE[2][26:33], err) } // Parse the ArgumentOfPerigee RawArgumentOfPerigee := strings.TrimSpace(SplitTLE[2][34:42]) ArgumentOfPerigee, err := strconv.ParseFloat(RawArgumentOfPerigee, 64) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the ArgumentOfPerigee", SplitTLE[2][34:42], err) } // Parse the MeanAnomaly RawMeanAnomaly := strings.TrimSpace(SplitTLE[2][43:51]) MeanAnomaly, err := strconv.ParseFloat(RawMeanAnomaly, 64) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the MeanAnomaly", SplitTLE[2][43:51], err) } // Parse the MeanMotion RawMeanMotion := strings.TrimSpace(SplitTLE[2][52:63]) MeanMotion, err := strconv.ParseFloat(RawMeanMotion, 64) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the MeanMotion", SplitTLE[2][52:63], err) } // Parse the RevolutionNumberAtEpoch RevolutionNumberAtEpoch, err := strconv.Atoi(SplitTLE[2][63:68]) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the MeanMotion", SplitTLE[2][63:68], err) } // Parse the Checksum ChecksumLineTwo, err := strconv.Atoi(string(SplitTLE[2][68])) if err != nil { return LineTwo{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the checksum", SplitTLE[2][68], err) } newLineTwo := LineTwo{ Linenumber: LineTwoLinenumber, SatelliteNumber: SatelliteNumber, Inclination: Inclination, RightAscensionOfTheAscendingNode: RightAscensionOfTheAscendingNode, Eccentricity: Eccentricity, ArgumentOfPerigee: ArgumentOfPerigee, MeanAnomaly: MeanAnomaly, MeanMotion: MeanMotion, RevolutionNumberAtEpoch: RevolutionNumberAtEpoch, Checksum: ChecksumLineTwo, } return newLineTwo, nil }