Skip to content

Commit

Permalink
Ref partially TLE parsing from C++ to C
Browse files Browse the repository at this point in the history
  • Loading branch information
gunvirranu committed Nov 23, 2024
1 parent 2c5ad61 commit f93bc90
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 76 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ endif()

add_library(
perturb
src/perturb.c src/perturb.cpp
src/perturb.c src/perturb.cpp src/tle.c
)

target_include_directories(
Expand Down
10 changes: 0 additions & 10 deletions include/perturb/perturb.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,6 @@ namespace c_internal {
extern "C" {
#endif // __cplusplus

#if !(defined(__cplusplus) && defined(PERTURB_ENABLE_CPP_INTERFACE))
/// Both lines of a TLE **must** be this length, for TLE constructors.
///
/// It is assumed that this memory can be safely accessed.
/// Lines can be longer for verification mode, but that's for internal testing
/// purposes only and doesn't pertain to general usage.
/// Macro definition is excluded in C++ cases to not pollute globals.
# define PERTURB_TLE_LINE_LEN 69U
#endif

/// Alias to allow possibility of supporting 32-bit and 64-bit floating point
///
/// TODO: Support float32_t and float64_t
Expand Down
11 changes: 6 additions & 5 deletions include/perturb/perturb.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ constexpr std::size_t TLE_LINE_LEN = 69;

enum class TLEParseError {
NONE, ///< If no issues when parsing
SHOULD_BE_SPACE, ///< If there is a lack of space in the TLE
INVALID_FORMAT, ///< If general parsing was unsuccessfully
INVALID_VALUE, ///< If a parsed value doesn't make sense
CHECKSUM_MISMATCH, ///< If the checksum doesn't match
INVALID_VALUE, ///< If a parsed value doesn't make sense
INVALID_FORMAT, ///< If general parsing was unsuccessfully
SHOULD_BE_SPACE, ///< If there is a lack of space in the TLE
INVALID_INPUT, ///< If any inputs are null pointers
};

enum class GravModel {
Expand All @@ -79,7 +80,7 @@ enum class Sgp4Error {
SEMI_LATUS_RECTUM,
EPOCH_ELEMENTS_SUB_ORBITAL,
DECAYED,
INVALID_TLE,
INVALID_INPUT,
UNKNOWN
};

Expand Down Expand Up @@ -177,7 +178,7 @@ struct ClassicalOrbitalElements {
};

struct TwoLineElement {
c_internal::perturb_Tle internal; /// Internal C data
c_internal::perturb_TwoLineElement internal; /// Internal C data

#ifndef PERTURB_DISABLE_IO
/// Parse a TLE record string.
Expand Down
2 changes: 1 addition & 1 deletion include/perturb/sgp4.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ enum perturb_Sgp4Error {
PERTURB_SGP4_ERROR_SEMI_LATUS_RECTUM,
PERTURB_SGP4_ERROR_EPOCH_ELEMENTS_SUB_ORBITAL,
PERTURB_SGP4_ERROR_DECAYED,
PERTURB_SGP4_ERROR_INVALID_TLE, ///< Not from base impl, added in
PERTURB_SGP4_ERROR_INVALID_INPUT, ///< Not from base impl, added in
PERTURB_SGP4_ERROR_UNKNOWN
};

Expand Down
114 changes: 73 additions & 41 deletions include/perturb/tle.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,44 @@
#include "perturb/perturb.h"
#include "perturb/sgp4.h"

#if __cplusplus
#ifdef __cplusplus
# ifdef PERTURB_ENABLE_CPP_INTERFACE
namespace perturb {
namespace c_internal {
# endif
extern "C" {
#endif

#if !(defined(__cplusplus) && defined(PERTURB_ENABLE_CPP_INTERFACE))
/// Both lines of a TLE **must** be this length, for TLE constructors.
///
/// It is assumed that this memory can be safely accessed.
/// Lines can be longer for verification mode, but that's for internal testing
/// purposes only and doesn't pertain to general usage.
///
/// Macro definition is excluded in C++ cases to not pollute globals.
/// The C++ library redefines this as a proper type.
# define PERTURB_TLE_LINE_LEN 69U
#endif

/// Possible errors when parsing a TLE.
///
/// Returned by `TwoLineElement::parse` after processing a TLE record string.
///
/// @post
/// Errors (excluding `NONE`) are guaranteed to occur in definition order.
/// Meaning that spaces are checked first, then invalid format, then invalid
/// values, and lastly checksum. This allows you to assume, for example, that
/// if there is a `CHECKSUM_MISMATCH`, then none of the previous errors
/// occurred first, and so the invalid checksum is the *only* issue.
/// Errors are guaranteed to occur in reverse definition order, in that higher
/// enum values are checked first. Meaning invalid input is checked first, then
/// spaces, and so on. This allows you to assume, for example, that if there is
/// a `CHECKSUM_MISMATCH`, none of the previous errors occured first.
enum perturb_TleParseError {
PERTURB_TLE_PARSE_ERROR_NONE, ///< If no issues when parsing
PERTURB_TLE_PARSE_ERROR_SHOULD_BE_SPACE, ///< If there is a lack of space in the TLE
PERTURB_TLE_PARSE_ERROR_INVALID_FORMAT, ///< If general parsing was unsuccessfully
PERTURB_TLE_PARSE_ERROR_INVALID_VALUE, ///< If a parsed value doesn't make sense
PERTURB_TLE_PARSE_ERROR_CHECKSUM_MISMATCH, ///< If the checksum doesn't match
PERTURB_TLE_PARSE_ERROR_INVALID_VALUE, ///< If a parsed value doesn't make sense
PERTURB_TLE_PARSE_ERROR_INVALID_FORMAT, ///< If general parsing was unsuccessfully
PERTURB_TLE_PARSE_ERROR_SHOULD_BE_SPACE, ///< If there is a lack of space in the TLE
PERTURB_TLE_PARSE_ERROR_INVALID_INPUT, ///< If any inputs are null pointers
};


/// Represents a pre-parsed TLE record.
///
/// Can be generated via `TwoLineElement::parse`, but not particularly useful
Expand All @@ -60,46 +71,67 @@ enum perturb_TleParseError {
/// a case where all I/O and string processing is removed, this type still
/// allows you to construct and initialize a `Satellite` manually. However, you
/// must handle your own method of creating the `TwoLineElement`s.
struct perturb_Tle {
// clang-format off
// Line 1
char catalog_number[6]; ///< Satellite catalog number
char classification; ///< Classification {U: Unclassified, C: Classified, S: Secret}
unsigned int launch_year; ///< International Designator - Launch year (last two digits)
unsigned int launch_number; ///< International Designator - Launch number of the year
char launch_piece[4]; ///< International Designator - Piece of launch
unsigned int epoch_year; ///< Epoch year (last two digits)
double epoch_day_of_year; ///< Epoch fractional day of year
double n_dot; ///< First derivative of mean motion (ballistic coefficient) [rev/day^2]
double n_ddot; ///< Second derivative of mean motion [rev/day^3]
double b_star; ///< B* radiation pressure coefficient [1 / (earth radii)]
unsigned char ephemeris_type; ///< Orbital model used to generate data (usually 0)
unsigned int element_set_number; ///< Element set number
unsigned char line_1_checksum; ///< Line 1 check-sum

// Line 2
double inclination; ///< Inclination, 0 ≤ [deg] ≤ 180
double raan; ///< Right ascension of the ascending node, 0 ≤ [deg] ≤ 360
double eccentricity; ///< Eccentricity (0 ≤ [] ≤ 1)
double arg_of_perigee; ///< Argument of perigee, 0 ≤ [deg] ≤ 360
double mean_anomaly; ///< Mean anomaly, 0 ≤ [deg] ≤ 360
double mean_motion; ///< Mean motion, 0 < [rev/day]
unsigned long revolution_number; ///< Revolution number at epoch, 0 ≤ [rev] ≤ 99999
unsigned char line_2_checksum; ///< Line 2 check-sum
// clang-format on
struct perturb_TwoLineElement {
// These are ordered same as a TLE in string format
// clang-format off

// Line 1 - Metadata
char catalog_number[6]; ///< Satellite catalog number as a string
char classification; ///< Classification {U: Unclassified, C: Classified, S: Secret}

// Line 1 - Launch
uint8_t launch_year; ///< International Designator - Launch year (last two digits)
uint16_t launch_number; ///< International Designator - Launch number of the year
char launch_piece[4]; ///< International Designator - Piece of launch

// Line 1 - Epoch Time
uint8_t epoch_year; ///< Epoch year (last two digits)
perturb_real_t epoch_day_of_year; ///< Epoch fractional day of year

// Line 1 - Trajectory
perturb_real_t n_dot; ///< First derivative of mean motion (ballistic coefficient) [rev/day^2]
perturb_real_t n_ddot; ///< Second derivative of mean motion [rev/day^3]
perturb_real_t b_star; ///< B* radiation pressure coefficient [1 / (earth radii)]

// Line 1 - Metadata
uint8_t ephemeris_type; ///< Orbital model used to generate data (usually 0)
uint16_t element_set_number; ///< Element set number
uint8_t line_1_checksum; ///< Line 1 check-sum

// Line 2 - Orbit
perturb_real_t inclination; ///< Inclination, 0 ≤ [deg] ≤ 180
perturb_real_t raan; ///< Right ascension of the ascending node, 0 ≤ [deg] ≤ 360
perturb_real_t eccentricity; ///< Eccentricity (0 ≤ [] ≤ 1)
perturb_real_t arg_of_perigee; ///< Argument of perigee, 0 ≤ [deg] ≤ 360
perturb_real_t mean_anomaly; ///< Mean anomaly, 0 ≤ [deg] ≤ 360
perturb_real_t mean_motion; ///< Mean motion, 0 < [rev/day]

// Line 2 - Metadata
uint32_t revolution_number; ///< Revolution number at epoch, 0 ≤ [rev] ≤ 99999
int8_t line_2_checksum; ///< Line 2 check-sum

// clang-format on
};

enum perturb_TleParseError perturb_init_sat_from_tle(
struct perturb_Tle tle, enum perturb_GravityModel grav_model, struct perturb_Satellite * sat
enum perturb_Sgp4Error perturb_init_sat_from_tle(
struct perturb_TwoLineElement tle,
enum perturb_GravityModel grav_model,
struct perturb_Satellite * sat
);

#ifndef PERTURB_DISABLE_IO
enum perturb_TleParseError perturb_parse_tle(const char * line_1, const char * line_2, struct perturb_Tle * tle);
enum perturb_TleParseError perturb_parse_tle(
const char * line_1, const char * line_2,
struct perturb_TwoLineElement * tle
);
#endif

#ifndef PERTURB_DISABLE_IO
/// TODO: Think about if there's value to having this
enum perturb_TleParseError perturb_parse_tle_and_init_sat(
char * line_1, char * line_2, enum perturb_GravityModel grav_model, struct perturb_Satellite * sat
char * line_1, char * line_2,
enum perturb_GravityModel grav_model,
struct perturb_Satellite * sat
);
#endif

Expand Down
6 changes: 4 additions & 2 deletions src/common_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
#ifndef PERTURB_COMMON_PRIVATE_H
#define PERTURB_COMMON_PRIVATE_H

typedef perturb_real_t real_t;

#define PI 3.14159265358979323846

#define MINS_PER_DAY (24 * 60)

#define FABS(x) fabs(x)
#define FLOOR(x) floor(x)

#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))

typedef perturb_real_t real_t;

#endif // PERTURB_COMMON_PRIVATE_H
2 changes: 2 additions & 0 deletions src/perturb.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
# error "Hah someone messed up, why r u compiling this C as C++"
#endif

// FIXME: Reformat files for C and C++

struct perturb_JulianDate perturb_datetime_to_julian(const struct perturb_DateTime t) {
struct perturb_JulianDate jd;
jday_SGP4(t.year, t.month, t.day, t.hour, t.min, t.sec, &jd.jd, &jd.jd_frac);
Expand Down
11 changes: 6 additions & 5 deletions src/perturb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ namespace perturb {
#define CHECK_ENUM_MATCHES(A, B) static_assert(static_cast<int>(A) == c_internal::PERTURB_ ## B, "Enum mismatch!")

CHECK_ENUM_MATCHES(TLEParseError::NONE, TLE_PARSE_ERROR_NONE);
CHECK_ENUM_MATCHES(TLEParseError::SHOULD_BE_SPACE, TLE_PARSE_ERROR_SHOULD_BE_SPACE);
CHECK_ENUM_MATCHES(TLEParseError::INVALID_FORMAT, TLE_PARSE_ERROR_INVALID_FORMAT);
CHECK_ENUM_MATCHES(TLEParseError::INVALID_VALUE, TLE_PARSE_ERROR_INVALID_VALUE);
CHECK_ENUM_MATCHES(TLEParseError::CHECKSUM_MISMATCH, TLE_PARSE_ERROR_CHECKSUM_MISMATCH);
CHECK_ENUM_MATCHES(TLEParseError::INVALID_VALUE, TLE_PARSE_ERROR_INVALID_VALUE);
CHECK_ENUM_MATCHES(TLEParseError::INVALID_FORMAT, TLE_PARSE_ERROR_INVALID_FORMAT);
CHECK_ENUM_MATCHES(TLEParseError::SHOULD_BE_SPACE, TLE_PARSE_ERROR_SHOULD_BE_SPACE);
CHECK_ENUM_MATCHES(TLEParseError::INVALID_INPUT, TLE_PARSE_ERROR_INVALID_INPUT);

CHECK_ENUM_MATCHES(GravModel::WGS72_OLD, GRAVITY_MODEL_WGS72_OLD);
CHECK_ENUM_MATCHES(GravModel::WGS72, GRAVITY_MODEL_WGS72);
Expand All @@ -39,7 +40,7 @@ CHECK_ENUM_MATCHES(Sgp4Error::PERT_ELEMENTS, SGP4_ERROR_PERT_ELEMENTS);
CHECK_ENUM_MATCHES(Sgp4Error::SEMI_LATUS_RECTUM, SGP4_ERROR_SEMI_LATUS_RECTUM);
CHECK_ENUM_MATCHES(Sgp4Error::EPOCH_ELEMENTS_SUB_ORBITAL, SGP4_ERROR_EPOCH_ELEMENTS_SUB_ORBITAL);
CHECK_ENUM_MATCHES(Sgp4Error::DECAYED, SGP4_ERROR_DECAYED);
CHECK_ENUM_MATCHES(Sgp4Error::INVALID_TLE, SGP4_ERROR_INVALID_TLE);
CHECK_ENUM_MATCHES(Sgp4Error::INVALID_INPUT, SGP4_ERROR_INVALID_INPUT);
CHECK_ENUM_MATCHES(Sgp4Error::UNKNOWN, SGP4_ERROR_UNKNOWN);

static Sgp4Error convert_sgp4_error_code(const int error_code) {
Expand Down Expand Up @@ -133,7 +134,7 @@ ClassicalOrbitalElements::ClassicalOrbitalElements(StateVector sv, GravModel gra
#ifndef PERTURB_DISABLE_IO
TLEParseError TwoLineElement::parse(const char * line_1, const char * line_2) {
// Pass parsing call directly to underlying C impl
c_internal::perturb_Tle * tle = &this->internal;
c_internal::perturb_TwoLineElement * tle = &this->internal;
const c_internal::perturb_TleParseError err = c_internal::perturb_parse_tle(line_1, line_2, tle);
return static_cast<TLEParseError>(err);
}
Expand Down
Loading

0 comments on commit f93bc90

Please sign in to comment.