module

Kozai::TLE

Parsing of NORAD two-line element sets.

The format is fixed-column, and this parser treats it that way. Splitting on whitespace looks like it works and then quietly fails, because adjacent fields run together whenever a value fills its column span. A real example from the verification set:

2 00005  34.2682 348.7242 1859667 331.7664  19.3264 10.82419157413667

The tail 10.82419157413667 is three separate fields — mean motion 10.82419157, revolution number 41366, checksum 7 — with no separators at all. Whitespace splitting yields six tokens where seven are needed and silently misassigns every one of them.

No regular expressions are used here, and none are needed: with fixed columns there is nothing to search for. That also keeps PCRE2 out of the binary.

NOTE: column numbers throughout this file are 1-based, matching the CelesTrak format description, not 0-based like Crystal indices. The field helper does the conversion in one place.

Constants

ALPHA5_LETTERS = "ABCDEFGHJKLMNPQRSTUVWXYZ"

Digits and letters usable as the leading character of an alpha-5 catalog number. I and O are excluded because they are too easily confused with 1 and 0.

NOTE: alpha-5 extension, CelesTrak "A New Way to Obtain GP Data". A maps to 10, and the sequence continues to Z = 33, giving catalog numbers up to 339999 in five characters.

LINE_LENGTH = 69

Number of characters in a element set line, excluding any line ending.

Class methods

checksum(line : String) : Int32

Computes the modulo-10 checksum of an element set line.

NOTE: per the TLE format description the sum runs over columns 1 through 68, counting each digit as its value and each minus sign as one. Every other character, plus signs and letters and blanks alike, counts zero.

Source
decode_alpha5(field : String) : Int32

Decodes an alpha-5 catalog number.

Plain five-digit numbers pass through unchanged. A leading letter extends the range: A adds 100000, B adds 110000, and so on up to Z, skipping I and O.

Raises TLE::ParseError on an unusable leading character or non-numeric remainder.

Source
encode_alpha5(number : Int32) : String

Encodes a catalog number in alpha-5 form, the inverse of .decode_alpha5.

Numbers below 100000 are returned as five digits.

Source
parse(line1 : String, line2 : String, name : String | Nil = nil, strict_checksum : Bool = true) : Elements

Parses one element set from its two lines.

name is the optional common name from a preceding 3LE line.

When strict_checksum is true, a line whose modulo-10 checksum does not match raises TLE::ParseError. Set it to false to accept such lines: some real and several synthetic element sets carry wrong checksums, the SGP4 verification set among them, and rejecting those would make the most important fixture in this project unloadable.

Content past column 69 is ignored. The verification set stores a start/stop/step window there, and ignoring it lets the same parser read both ordinary catalogue files and that fixture.

Raises TLE::ParseError if either line is malformed.

Source
parse?(line1 : String, line2 : String, name : String | Nil = nil, strict_checksum : Bool = true) : Elements | Nil

Like .parse, but returns nil instead of raising.

Source
parse_catalog(io : IO, strict_checksum : Bool = true, skip_invalid : Bool = false) : Array(Elements)

Parses a catalogue containing many element sets.

Accepts both two-line and three-line ("3LE") records, mixed freely, along with the 0 NAME name form used by Space-Track. Blank lines and lines beginning with # are skipped, which is what lets the verification fixture carry its commentary inline.

When skip_invalid is true, records that fail to parse are dropped and parsing continues — appropriate for a bulk catalogue download where one bad record should not lose the other nine hundred. When false, the first bad record raises.

Source
parse_catalog(text : String, strict_checksum : Bool = true, skip_invalid : Bool = false) : Array(Elements)

Parses a catalogue containing many element sets.

Accepts both two-line and three-line ("3LE") records, mixed freely, along with the 0 NAME name form used by Space-Track. Blank lines and lines beginning with # are skipped, which is what lets the verification fixture carry its commentary inline.

When skip_invalid is true, records that fail to parse are dropped and parsing continues — appropriate for a bulk catalogue download where one bad record should not lose the other nine hundred. When false, the first bad record raises.

Source
parse_file(path : String, strict_checksum : Bool = true, skip_invalid : Bool = false) : Array(Elements)

Reads and parses a catalogue file.

Source
valid_checksum?(line : String) : Bool

Whether the checksum in column 69 matches the rest of the line.

Source

Nested types