Skip to content

Commit

Permalink
Ref to C99 base layer (work in progress)
Browse files Browse the repository at this point in the history
  • Loading branch information
gunvirranu committed Sep 20, 2024
1 parent cf93882 commit 3eaf166
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 488 deletions.
13 changes: 7 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ project(
VERSION 1.0.0
DESCRIPTION "A modern C++ wrapper for SGP4 orbit propagation"
HOMEPAGE_URL "https://github.com/gunvirranu/perturb"
LANGUAGES CXX
LANGUAGES C
)

option(perturb_DISABLE_IO "Disable I/O and string functionality" OFF)
option(perturb_EXPORT_C_INTERFACE "Provide a C ABI interface" OFF)
option(perturb_ENABLE_CPP_INTERFACE "Expose a small C++ wrapper interface" OFF)

# For CMake 3.21+, variable is set by default by project()
if(CMAKE_VERSION VERSION_LESS 3.21.0)
Expand Down Expand Up @@ -56,7 +56,7 @@ endif()

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

target_include_directories(
Expand All @@ -65,14 +65,15 @@ target_include_directories(
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
)

target_compile_features(perturb PUBLIC cxx_std_11)
target_compile_features(perturb PUBLIC c_std_99)
# target_compile_features(perturb PUBLIC cxx_std_11)

if(perturb_DISABLE_IO)
target_compile_definitions(perturb PUBLIC PERTURB_DISABLE_IO)
endif()

if(perturb_EXPORT_C_INTERFACE)
target_compile_definitions(perturb PUBLIC PERTURB_EXPORT_C_INTERFACE)
if(perturb_ENABLE_CPP_INTERFACE)
target_compile_definitions(perturb PUBLIC PERTURB_ENABLE_CPP_INTERFACE)
endif()

# ---- Install rules ----
Expand Down
9 changes: 7 additions & 2 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"inherits": "cmake-pedantic",
"cacheVariables": {
"perturb_DEVELOPER_MODE": "ON",
"perturb_EXPORT_C_INTERFACE": "ON"
"perturb_ENABLE_CPP_INTERFACE": "ON"
}
},
{
Expand All @@ -49,22 +49,27 @@
"description": "This preset makes sure perturb actually builds with C++11",
"hidden": true,
"cacheVariables": {
"CMAKE_CXX_EXTENSIONS": "OFF",
"CMAKE_C_STANDARD": "99",
"CMAKE_C_EXTENSIONS": "OFF",
"CMAKE_C_STANDARD_REQUIRED": "ON",
"CMAKE_CXX_STANDARD": "11",
"CMAKE_CXX_EXTENSIONS": "OFF",
"CMAKE_CXX_STANDARD_REQUIRED": "ON"
}
},
{
"name": "flags-unix",
"hidden": true,
"cacheVariables": {
"CMAKE_C_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wcast-align -Wshadow -Wformat=2 -Wundef -Wdouble-promotion -Wstrict-overflow=5 -Wno-unused-result -Wpointer-arith -Wstrict-prototypes -Wwrite-strings -Wswitch-default -Wswitch-enum -Wunreachable-code",
"CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wcast-align -Wshadow -Wformat=2 -Wformat-overflow -Wformat-truncation -Wundef -Wdouble-promotion -Wstrict-overflow=5 -Wno-maybe-uninitialized -Wno-unused-result"
}
},
{
"name": "flags-windows",
"hidden": true,
"cacheVariables": {
"CMAKE_C_FLAGS": "/W4 /permissive- /utf-8 /volatile:iso",
"CMAKE_CXX_FLAGS": "/W4 /permissive- /utf-8 /volatile:iso /EHsc /Zc:__cplusplus /Zc:throwingNew"
}
},
Expand Down
164 changes: 116 additions & 48 deletions include/perturb/perturb.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,91 +6,159 @@
* Licensed under the MIT License <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: MIT
*
* Copyright (c) 2024 Gunvir Ranu
* Copyright (c) 2024 Gunvir Singh Ranu
*/

//! @file
//! Exported C interface header for the C++ perturb library
//! @file Primary C header for the perturb library
//! @author Gunvir Singh Ranu
//! @version 1.0.0
//! @copyright Gunvir Singh Ranu, MIT License

#ifndef PERTURB_PERTURB_H
#define PERTURB_PERTURB_H

// Sanity checks on if you're including this header correctly
// `perturb.hpp` is the primary C++ header for this library, perturb.
// This header, `perturb.h`, is intended only for C ABI consumers.
#ifndef PERTURB_EXPORT_C_INTERFACE
# if __cplusplus
# error "Seems like you're using C++. Use the perturb.hpp header."
# else
# error "Seems like you're using C. Enable the PERTURB_EXPORT_C_INTERFACE option."
# endif
#endif
#ifdef PERTURB_EXPORT_C_INTERFACE

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#define PERTURB_TLE_LINE_LEN 69U
// Define `PERTURB_SGP4_ENABLE_DEBUG` to enable Vallado's verification mode.
// Generally, this is unwanted. Only enabled for tests.
#if (defined(PERTURB_SGP4_ENABLE_DEBUG) && defined(PERTURB_DISABLE_IO))
# error "Cannot enable SGP4 debug without I/O functionality"
#endif

#ifdef __cplusplus
extern "C" { // Support header inclusion from C++

// Support header inclusion from C++
#if __cplusplus
extern "C" {
# ifdef PERTURB_ENABLE_CPP_INTERFACE
namespace perturb {
/// Namespace to shove C interface into to not pollute globals
namespace c_internal {
# endif
#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

typedef double perturb_real_t;
/// Alias to allow possibility of supporting 32-bit and 64-bit floating point
typedef double perturb_real_t; // TODO: Support float32_t and float64_t

extern const size_t PERTURB_C_SATELLITE_ALLOC_SIZE;
extern const size_t PERTURB_C_TLE_ALLOC_SIZE;

struct perturb_satellite {
void * p_satellite;
};

struct perturb_tle {
void * p_tle;
/// A basic and human readable representation of a point in time.
///
/// The primary purpose of this type is to be constructed manually via
/// aggregate initialization and the converted to a `JulianDate`.
///
/// @warning
/// This type doesn't enforce a valid date and time upon construction; there
/// are no checks. Additionally, the conversion to `JulianDate` values are only
/// valid from years 1900 to 2100.
///
/// The question of what this time point represents gets complicated. In the
/// "Revisiting Spacetrack Report #3" paper from Celestrak, it is discussed
/// what this time represents. While UTC would make sense, the method
/// `perturb::sgp4::gstime_SGP4` requires UT1 time to calculate GMST. This
/// library makes the same assumption that the paper concludes:
///
/// @par
/// "The error associated with approximating UT1 with UTC is within the
/// theoretical uncertainty of the SGP4 theory itself. Except for the GMST
/// calculation, this paper and code assumes time to be realized as UTC."
struct perturb_date_time {
uint16_t year; ///< [year] from 1900 to 2100
uint8_t month; ///< [month] from 1 to 12
uint8_t day; ///< [day] from 1 to {28, 29, 30, 31} (depending on month)
uint8_t hour; ///< [hour] from 0 to 23
uint8_t min; ///< [minute] from 0 to 59
perturb_real_t sec; ///< Fractional [sec] from 0.0 to 59.999...
};

/// Represents a specific point in time on the Julian calendar.
///
/// Generally not constructed manually, but instead converted from a `DateTime`
/// or from `Satellite::epoch`. Supports some basic manipulation operations.
/// For a human readable representation, can be converted back to `DateTime`.
/// As for what time point this represents, see the comment on `DateTime`.
///
/// Internally, this is represented as the "theoretical" sum of two double
/// precision floats. This is to preserve as much time accuracy as possible,
/// since many bits are lost due to storing the number of the day. The smaller
/// value is used to represent a more accurate time offset from that day. The
/// "normalized" value restricts the larger value to entire days and the
/// smaller to a [0.0, 1.0) time offset.
struct perturb_julian_date {
perturb_real_t jd;
perturb_real_t jd_frac;
perturb_real_t jd; /// Fractional # of [day] since the epoch (4713 B.C.)
perturb_real_t jd_frac; /// Smaller fractional number of [day], *usually* between 0 and 1
};

/// Represents the output prediction from SGP4.
///
/// Generated by `Satellite::propagate` method. The vectors are represented in
/// the TEME (True Equator Mean Equinox) reference frame. Can be converted to
/// classical orbital elements with the `ClassicalOrbitalElements` type.
struct perturb_state_vector {
struct perturb_julian_date epoch;
perturb_real_t position[3];
perturb_real_t velocity[3];
struct perturb_julian_date epoch; /// Time-stamp of the state vector
perturb_real_t position[3]; /// Position in the TEME frame in [km]
perturb_real_t velocity[3]; /// Velocity in the TEME frame in [km/s]
};

struct perturb_julian_date perturb_datetime_to_julian(
uint8_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t min,
perturb_real_t sec
);
/// Classical Keplerian orbital elements.
///
/// Names and values are from the underlying SGP4 implementation. Can be
/// generated from a `StateVector` via the constructor.
struct perturb_classical_orbital_elements {
perturb_real_t semilatus_rectum; ///< Samilatus rectum in [km]
perturb_real_t semimajor_axis; ///< Semimajor axis in [km]
perturb_real_t eccentricity; ///< Eccentricity (unitless)
perturb_real_t inclination; ///< Inlination in [rad]
perturb_real_t raan; ///< Right ascension of ascending node in [rad]
perturb_real_t arg_of_perigee; ///< Argument of perigee in [rad]
perturb_real_t true_anomaly; ///< True anomaly in [rad]
perturb_real_t mean_anomaly; ///< Mean anomaly in [rad]
perturb_real_t arg_of_latitude; ///< Argument of latitude in [rad]
perturb_real_t true_longitude; ///< True longitude in [rad]
perturb_real_t longitude_of_periapsis; ///< Longitude of periapsis in [rad]
};

struct perturb_satellite; // Forward declare, defined in `sgp4.h`
struct perturb_tle; // Forward declare, defined in `tle.h`

struct perturb_julian_date perturb_datetime_to_julian(struct perturb_date_time t);

struct perturb_julian_date perturb_add_days_to_julian(
struct perturb_julian_date t,
perturb_real_t days
struct perturb_julian_date t, perturb_real_t days
);

struct perturb_julian_date perturb_epoch(struct perturb_satellite sat);

bool perturb_init_sat_from_tle(struct perturb_satellite sat, struct perturb_tle tle);
bool perturb_parse_tle(char * line_1, char * line_2, struct perturb_tle tle);
bool perturb_parse_tle_and_init_sat(char * line_1, char * line_2, struct perturb_satellite sat);
bool perturb_parse_tle(char *line_1, char *line_2, struct perturb_tle tle);
bool perturb_parse_tle_and_init_sat(
char *line_1, char *line_2, struct perturb_satellite sat
);

struct perturb_state_vector perturb_propagate_days(struct perturb_satellite sat, perturb_real_t days);
struct perturb_state_vector perturb_propagate(struct perturb_satellite sat, struct perturb_julian_date t);
struct perturb_state_vector perturb_propagate_days(
struct perturb_satellite sat, perturb_real_t days
);
struct perturb_state_vector perturb_propagate(
struct perturb_satellite sat, struct perturb_julian_date t
);

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

#endif // PERTURB_EXPORT_C_INTERFACE
#endif // PERTURB_PERTURB_H
Loading

0 comments on commit 3eaf166

Please sign in to comment.