diff options
-rw-r--r-- | TLE.go | 5 | ||||
-rw-r--r-- | convert.go | 110 | ||||
-rw-r--r-- | convert_test.go | 242 |
3 files changed, 348 insertions, 9 deletions
diff --git a/TLE.go b/TLE.go index 89257ed..a0c51a8 100644 --- a/TLE.go +++ b/TLE.go @@ -7,7 +7,7 @@ More information can be found here: */ -package TLE +package tle // TLE defines the lines contained in a Two-Line-Element type TLE struct { @@ -88,11 +88,12 @@ type Epoch struct { Dayfraction float64 `json:"dayfraction"` } +// LineTwo of the TLE type LineTwo struct { Linenumber int `json:"linenumber"` // Catalog number defined by USSPACECOM - Satellitenumber int `json:"satellitenumber"` + SatelliteNumber int `json:"satellitenumber"` // Inclination // Unit: degrees diff --git a/convert.go b/convert.go index e8000e6..7e76f93 100644 --- a/convert.go +++ b/convert.go @@ -1,4 +1,4 @@ -package TLE +package tle import ( "fmt" @@ -7,12 +7,15 @@ import ( "strings" ) +// NewTLE creates a new TLE object from a given TLE string func NewTLE(RawTLE string) (TLE, error) { // split the TLE - var SplitTLE []string = strings.Split(RawTLE, "\n") + var SplitTLE = strings.Split(RawTLE, "\n") + //////////////////////////////////////////////////////////////////////////// // Line One + //////////////////////////////////////////////////////////////////////////// // parse the line number LineOneLinenumber, err := strconv.Atoi(string(SplitTLE[1][0])) @@ -38,6 +41,9 @@ func NewTLE(RawTLE string) (TLE, error) { return TLE{}, 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 { @@ -102,10 +108,89 @@ func NewTLE(RawTLE string) (TLE, error) { return TLE{}, 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 TLE{}, 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 TLE{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the checksum", SplitTLE[1][68], err) + } + + //////////////////////////////////////////////////////////////////////////// + // Line Two + //////////////////////////////////////////////////////////////////////////// + + // parse the line number + LineTwoLinenumber, err := strconv.Atoi(string(SplitTLE[2][0])) + if err != nil { + return TLE{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the line number", SplitTLE[2][0], err) + } + + // SatelliteNumber + // (Parsed before in line one) + + // Parse the Inclination + RawInclination := strings.TrimSpace(SplitTLE[2][9:16]) + Inclination, err := strconv.ParseFloat(RawInclination, 64) + if err != nil { + return TLE{}, 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 TLE{}, 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 TLE{}, 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 TLE{}, 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 TLE{}, 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 TLE{}, 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 TLE{}, 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 TLE{}, fmt.Errorf("%s: %#v\n%v", "Could not parse the checksum", SplitTLE[2][68], err) + } + // fill the generatedTLE struct var generatedTLE TLE = TLE{ TitleLine: TitleLine{ - Satname: fmt.Sprintf("%-25s", SplitTLE[0][0:24]), + Satname: fmt.Sprintf("%-24s", SplitTLE[0][0:24]), }, LineOne: LineOne{ Linenumber: LineOneLinenumber, @@ -114,7 +199,7 @@ func NewTLE(RawTLE string) (TLE, error) { InternationalDesignator: InternationalDesignator{ Launchyear: LaunchYear, Launchnumber: LaunchNumber, - Launchpiece: string(SplitTLE[1][14]), + Launchpiece: LaunchPiece, }, Epoch: Epoch{ Year: EpochYear, @@ -123,11 +208,22 @@ func NewTLE(RawTLE string) (TLE, error) { Firstderiv: FirstDeriv, Secondderiv: SecondDeriv, BSTAR: BSTAR, - Numberzero: int8(SplitTLE[1][62]), + Numberzero: NumberZero, ElementSetNumber: ElementSetNumber, - Checksum: int8(SplitTLE[1][68]), + Checksum: Checksum, + }, + LineTwo: LineTwo{ + Linenumber: LineTwoLinenumber, + SatelliteNumber: SatelliteNumber, + Inclination: Inclination, + RightAscensionOfTheAscendingNode: RightAscensionOfTheAscendingNode, + Eccentricity: Eccentricity, + ArgumentOfPerigee: ArgumentOfPerigee, + MeanAnomaly: MeanAnomaly, + MeanMotion: MeanMotion, + RevolutionNumberAtEpoch: RevolutionNumberAtEpoch, + Checksum: ChecksumLineTwo, }, - LineTwo: LineTwo{}, } return generatedTLE, nil diff --git a/convert_test.go b/convert_test.go new file mode 100644 index 0000000..96ee3c3 --- /dev/null +++ b/convert_test.go @@ -0,0 +1,242 @@ +package tle + +import ( + "encoding/json" + "fmt" + "os" + "reflect" + "testing" +) + +func ExampleNewTLE() { + var RawTLE = `ISS (ZARYA) +1 25544U 98067A 19229.39083552 .00000228 00000-0 11917-4 0 9993 +2 25544 51.6447 57.6210 0007373 294.0868 138.8050 15.50381554184754` + + TLE, err := NewTLE(RawTLE) + if err != nil { + fmt.Println(err) + } + + // convert the TLE to json + b, err := json.MarshalIndent(TLE, "", " ") + if err != nil { + fmt.Println("error: ", err) + } + _, err = os.Stdout.Write(b) + if err != nil { + fmt.Println("error: ", err) + } + + // Output: + // { + // "titleline": { + // "satname": "ISS (ZARYA) " + // }, + // "lineone": { + // "linenumber": 1, + // "satellitenumber": 25544, + // "classification": "U", + // "internationaldesignator": { + // "launchyear": 98, + // "launchnumber": 67, + // "launchpiece": "A" + // }, + // "epoch": { + // "year": 19, + // "dayfraction": 229.39083552 + // }, + // "firstderiv": 0.00000228, + // "secondderiv": 0, + // "BSTAR": 0.000011917, + // "numberzero": 0, + // "elementesetnumber": 999, + // "checksum": 3 + // }, + // "linetwo": { + // "linenumber": 2, + // "satellitenumber": 25544, + // "inclination": 51.6447, + // "rightascensionoftheascendingnode": 57.621, + // "eccentricity": 7373, + // "argumentofperigee": 294.0868, + // "meananomaly": 138.805, + // "meanmotion": 15.50381554, + // "revolutionnumberatepoch": 18475, + // "checksum": 4 + // } + //} +} + +func TestNewTLE(t *testing.T) { + type args struct { + RawTLE string + } + tests := []struct { + name string + args args + want TLE + wantErr bool + }{ + { + name: "ISS (ZARYA) ", + args: args{ + RawTLE: `ISS (ZARYA) +1 25544U 98067A 19229.39083552 .00000228 00000-0 11917-4 0 9993 +2 25544 51.6447 57.6210 0007373 294.0868 138.8050 15.50381554184754`, + }, + want: TLE{ + TitleLine: TitleLine{ + Satname: "ISS (ZARYA) ", + }, + LineOne: LineOne{ + Linenumber: 1, + SatelliteNumber: 25544, + Classification: "U", + InternationalDesignator: InternationalDesignator{ + Launchyear: 98, + Launchnumber: 67, + Launchpiece: "A", + }, + Epoch: Epoch{ + Year: 19, + Dayfraction: 229.39083552, + }, + Firstderiv: 0.00000228, + Secondderiv: 0, + BSTAR: 0.000011917, + Numberzero: 0, + ElementSetNumber: 999, + Checksum: 3, + }, + LineTwo: LineTwo{ + Linenumber: 2, + SatelliteNumber: 25544, + Inclination: 51.6447, + RightAscensionOfTheAscendingNode: 57.621, + Eccentricity: 7373, + ArgumentOfPerigee: 294.0868, + MeanAnomaly: 138.805, + MeanMotion: 15.50381554, + RevolutionNumberAtEpoch: 18475, + Checksum: 4, + }, + }, + wantErr: false, + }, + { + name: "ALTAIR PATHFINDER ", + args: args{ + RawTLE: `ALTAIR PATHFINDER +1 42711U 98067LS 19228.69980992 .00034716 00000-0 14927-3 0 9996 +2 42711 51.6342 342.8763 0003425 355.3059 4.7912 15.84686251128432`, + }, + want: TLE{ + TitleLine: TitleLine{ + Satname: "ALTAIR PATHFINDER ", + }, + LineOne: LineOne{ + Linenumber: 1, + SatelliteNumber: 42711, + Classification: "U", + InternationalDesignator: InternationalDesignator{ + Launchyear: 98, + Launchnumber: 67, + Launchpiece: "LS", + }, + Epoch: Epoch{ + Year: 19, + Dayfraction: 228.69980992, + }, + Firstderiv: 0.00034716, + Secondderiv: 0, + BSTAR: 0.00014927, + Numberzero: 0, + ElementSetNumber: 999, + Checksum: 6, + }, + LineTwo: LineTwo{ + Linenumber: 2, + SatelliteNumber: 42711, + Inclination: 51.6342, + RightAscensionOfTheAscendingNode: 342.8763, + Eccentricity: 3425, + ArgumentOfPerigee: 355.3059, + MeanAnomaly: 4.7912, + MeanMotion: 15.84686251, + RevolutionNumberAtEpoch: 12843, + Checksum: 2, + }, + }, + wantErr: false, + }, + { + name: "CALSPHERE 1 ", + args: args{ + RawTLE: `CALSPHERE 1 +1 00900U 64063C 19230.92310804 .00000183 00000-0 18763-3 0 9990 +2 00900 90.1493 23.5442 0025413 246.1721 230.7950 13.73262737728795`, + }, + want: TLE{ + TitleLine: TitleLine{ + Satname: "CALSPHERE 1 ", + }, + LineOne: LineOne{ + Linenumber: 1, + SatelliteNumber: 900, + Classification: "U", + InternationalDesignator: InternationalDesignator{ + Launchyear: 64, + Launchnumber: 63, + Launchpiece: "C", + }, + Epoch: Epoch{ + Year: 19, + Dayfraction: 230.92310804, + }, + Firstderiv: 0.00000183, + Secondderiv: 0, + BSTAR: 0.00018763, + Numberzero: 0, + ElementSetNumber: 999, + Checksum: 0, + }, + LineTwo: LineTwo{ + Linenumber: 2, + SatelliteNumber: 900, + Inclination: 90.1493, + RightAscensionOfTheAscendingNode: 23.5442, + Eccentricity: 25413, + ArgumentOfPerigee: 246.1721, + MeanAnomaly: 230.795, + MeanMotion: 13.73262737, + RevolutionNumberAtEpoch: 72879, + Checksum: 5, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewTLE(tt.args.RawTLE) + if (err != nil) != tt.wantErr { + t.Errorf("NewTLE() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewTLE() got = %v\n,......................... want %v", got, tt.want) + } + }) + } +} + +func BenchmarkNewTLE(b *testing.B) { + RawTLE := `CALSPHERE 1 +1 00900U 64063C 19230.92310804 .00000183 00000-0 18763-3 0 9990 +2 00900 90.1493 23.5442 0025413 246.1721 230.7950 13.73262737728795` + + for i := 0; i < b.N; i++ { + _, _ = NewTLE(RawTLE) + } +} |