Update after major changes
parent
69744793e6
commit
2b5e39efe2
|
|
@ -1,7 +1,7 @@
|
||||||
# Exact paths to config junk
|
# Exact paths to config junk
|
||||||
^INSTALL$
|
^INSTALL$
|
||||||
^aclocal.m4$
|
^aclocal.m4$
|
||||||
^configure$
|
#^configure$
|
||||||
^(config.guess|config.sub|depcomp|install-sh|ltmain.sh|missing)$
|
^(config.guess|config.sub|depcomp|install-sh|ltmain.sh|missing)$
|
||||||
^config.(log|status)$
|
^config.(log|status)$
|
||||||
^autom4te.cache$
|
^autom4te.cache$
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
.(deps|libs)/*$
|
.(deps|libs)/*$
|
||||||
.cmp$
|
.cmp$
|
||||||
autom4te.cache/*$
|
autom4te.cache/*$
|
||||||
|
doxygen/*$
|
||||||
|
|
||||||
Makefile(.in)?$
|
Makefile(.in)?$
|
||||||
.(deps|libs)$
|
.(deps|libs)$
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
SUBDIRS = libsgp4 passpredict runtest sattrack
|
SUBDIRS = libsgp4 sattrack runtest passpredict
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#undef PACKAGE_URL
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#undef VERSION
|
||||||
File diff suppressed because it is too large
Load Diff
22
configure.ac
22
configure.ac
|
|
@ -2,8 +2,10 @@ AC_PREREQ([2.61])
|
||||||
AC_INIT([sgp4], 1.0, [info@danrw.com])
|
AC_INIT([sgp4], 1.0, [info@danrw.com])
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
#AC_CANONICAL_BUILD
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([libsgp4/Tle.cpp])
|
AC_CONFIG_SRCDIR([libsgp4/Tle.cpp])
|
||||||
|
AM_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
CFLAGS=" $CFLAGS"
|
CFLAGS=" $CFLAGS"
|
||||||
CXXFLAGS=" $CXXFLAGS"
|
CXXFLAGS=" $CXXFLAGS"
|
||||||
|
|
@ -19,11 +21,13 @@ AC_ARG_ENABLE(debug,
|
||||||
enable_debug=no)
|
enable_debug=no)
|
||||||
|
|
||||||
if test x$enable_debug = xyes; then
|
if test x$enable_debug = xyes; then
|
||||||
AM_CXXFLAGS="-g -O0 -Wall -Werror"
|
AM_CXXFLAGS="-g -O0 -Werror -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
|
||||||
else
|
else
|
||||||
AM_CXXFLAGS="-DNDEBUG -O2 -Wall -Werror -fomit-frame-pointer"
|
AM_CXXFLAGS="-DNDEBUG -O2 -fomit-frame-pointer -Werror -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_SEARCH_LIBS(clock_gettime, [rt])
|
||||||
|
|
||||||
AC_SUBST(AM_CXXFLAGS)
|
AC_SUBST(AM_CXXFLAGS)
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
|
|
@ -33,3 +37,17 @@ AC_CONFIG_FILES([Makefile
|
||||||
sattrack/Makefile])
|
sattrack/Makefile])
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
echo "---"
|
||||||
|
echo "Configuration summary for $PACKAGE_NAME version $VERSION"
|
||||||
|
echo ""
|
||||||
|
echo " * Installation prefix: $prefix"
|
||||||
|
echo " * System type: $build_vendor-$build_os"
|
||||||
|
echo " * Host CPU: $build_cpu"
|
||||||
|
echo " C Compiler: ${CC}"
|
||||||
|
echo " C++ Compiler: ${CXX}"
|
||||||
|
echo " Compiler flags: ${AM_CXXFLAGS}"
|
||||||
|
echo " Linker flags: ${AM_LDFLAGS}"
|
||||||
|
echo " Libraries: ${LIBS}"
|
||||||
|
echo " Debug enabled: $enable_debug"
|
||||||
|
echo ""
|
||||||
|
echo "---"
|
||||||
|
|
|
||||||
|
|
@ -1,106 +1,129 @@
|
||||||
#ifndef COORDGEODETIC_H_
|
#ifndef COORDGEODETIC_H_
|
||||||
#define COORDGEODETIC_H_
|
#define COORDGEODETIC_H_
|
||||||
|
|
||||||
#include "Globals.h"
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a geodetic position
|
||||||
|
*/
|
||||||
struct CoordGeodetic
|
struct CoordGeodetic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CoordGeodetic()
|
/**
|
||||||
: latitude(0.0), longitude(0.0), altitude(0.0)
|
* Default constructor
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* default is in degrees
|
|
||||||
*/
|
*/
|
||||||
CoordGeodetic(double lat, double lon, double alt, bool radians = false)
|
CoordGeodetic()
|
||||||
|
: latitude(0.0),
|
||||||
|
longitude(0.0),
|
||||||
|
altitude(0.0)
|
||||||
{
|
{
|
||||||
if (radians)
|
|
||||||
{
|
|
||||||
latitude = lat;
|
|
||||||
longitude = lon;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
latitude = Util::DegreesToRadians(lat);
|
|
||||||
longitude = Util::DegreesToRadians(lon);
|
|
||||||
}
|
|
||||||
altitude = alt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordGeodetic(const CoordGeodetic& g)
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param[in] arg_latitude the latitude in degrees
|
||||||
|
* @param[in] arg_longitude the longitude in degrees
|
||||||
|
* @param[in] arg_altitude the altitude in kilometers
|
||||||
|
*/
|
||||||
|
CoordGeodetic(
|
||||||
|
double arg_latitude,
|
||||||
|
double arg_longitude,
|
||||||
|
double arg_altitude)
|
||||||
{
|
{
|
||||||
latitude = g.latitude;
|
latitude = Util::DegreesToRadians(arg_latitude);
|
||||||
longitude = g.longitude;
|
longitude = Util::DegreesToRadians(arg_longitude);
|
||||||
altitude = g.altitude;
|
altitude = arg_altitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor
|
||||||
|
* @param[in] geo object to copy from
|
||||||
|
*/
|
||||||
|
CoordGeodetic(const CoordGeodetic& geo)
|
||||||
|
{
|
||||||
|
latitude = geo.latitude;
|
||||||
|
longitude = geo.longitude;
|
||||||
|
altitude = geo.altitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~CoordGeodetic()
|
virtual ~CoordGeodetic()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordGeodetic& operator=(const CoordGeodetic& g)
|
/**
|
||||||
|
* Assignment operator
|
||||||
|
* @param[in] geo object to copy from
|
||||||
|
*/
|
||||||
|
CoordGeodetic& operator=(const CoordGeodetic& geo)
|
||||||
{
|
{
|
||||||
if (this != &g)
|
if (this != &geo)
|
||||||
{
|
{
|
||||||
latitude = g.latitude;
|
latitude = geo.latitude;
|
||||||
longitude = g.longitude;
|
longitude = geo.longitude;
|
||||||
altitude = g.altitude;
|
altitude = geo.altitude;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const CoordGeodetic& g) const
|
/**
|
||||||
|
* Equality operator
|
||||||
|
* @param[in] geo the object to compare with
|
||||||
|
* @returns whether the object is equal
|
||||||
|
*/
|
||||||
|
bool operator==(const CoordGeodetic& geo) const
|
||||||
{
|
{
|
||||||
return IsEqual(g);
|
return IsEqual(geo);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const CoordGeodetic& g) const
|
/**
|
||||||
|
* Inequality operator
|
||||||
|
* @param[in] geo the object to compare with
|
||||||
|
* @returns whether the object is not equal
|
||||||
|
*/
|
||||||
|
bool operator!=(const CoordGeodetic& geo) const
|
||||||
{
|
{
|
||||||
return !IsEqual(g);
|
return !IsEqual(geo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump this object to a string
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
std::string ToString() const
|
std::string ToString() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::right << std::fixed << std::setprecision(2);
|
ss << std::right << std::fixed << std::setprecision(3);
|
||||||
ss << "Lat: " << std::setw(7) << Util::RadiansToDegrees(latitude);
|
ss << "Lat: " << std::setw(7) << Util::RadiansToDegrees(latitude);
|
||||||
ss << ", Lon: " << std::setw(7) << Util::RadiansToDegrees(longitude);
|
ss << ", Lon: " << std::setw(7) << Util::RadiansToDegrees(longitude);
|
||||||
ss << ", Alt: " << std::setw(9) << altitude;
|
ss << ", Alt: " << std::setw(9) << altitude;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/** latitude in radians (-PI >= latitude < PI) */
|
||||||
* radians (north positive, south negative)
|
|
||||||
*/
|
|
||||||
double latitude;
|
double latitude;
|
||||||
/*
|
/** latitude in radians (-PI/2 >= latitude <= PI/2) */
|
||||||
* radians (east positive, west negative)
|
|
||||||
*/
|
|
||||||
double longitude;
|
double longitude;
|
||||||
/*
|
/** altitude in kilometers */
|
||||||
* kilometers
|
|
||||||
*/
|
|
||||||
double altitude;
|
double altitude;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
bool IsEqual(const CoordGeodetic& g) const
|
bool IsEqual(const CoordGeodetic& geo) const
|
||||||
{
|
{
|
||||||
if (latitude == g.latitude && longitude == g.longitude &&
|
bool equal = false;
|
||||||
altitude == g.altitude)
|
if (latitude == geo.latitude &&
|
||||||
|
longitude == geo.longitude &&
|
||||||
|
altitude == geo.altitude)
|
||||||
{
|
{
|
||||||
return false;
|
equal = false;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return equal;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -110,4 +133,3 @@ inline std::ostream& operator<<(std::ostream& strm, const CoordGeodetic& g)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,99 +1,139 @@
|
||||||
#ifndef COORDTOPOGRAPHIC_H_
|
#ifndef COORDTOPOGRAPHIC_H_
|
||||||
#define COORDTOPOGRAPHIC_H_
|
#define COORDTOPOGRAPHIC_H_
|
||||||
|
|
||||||
#include "Globals.h"
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a topographic position
|
||||||
|
*/
|
||||||
struct CoordTopographic
|
struct CoordTopographic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
CoordTopographic()
|
CoordTopographic()
|
||||||
: azimuth(0.0), elevation(0.0), range(0.0), range_rate(0.0)
|
: azimuth(0.0),
|
||||||
|
elevation(0.0),
|
||||||
|
range(0.0),
|
||||||
|
range_rate(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordTopographic(double az, double el, double rnge, double rnge_rate)
|
/**
|
||||||
: azimuth(az), elevation(el), range(rnge), range_rate(rnge_rate)
|
* Constructor
|
||||||
|
* @param[in] arg_azimuth azimuth in radians
|
||||||
|
* @param[in] arg_elevation elevation in radians
|
||||||
|
* @param[in] arg_range range in kilometers
|
||||||
|
* @param[in] arg_range_rate range rate in kilometers per second
|
||||||
|
*/
|
||||||
|
CoordTopographic(
|
||||||
|
double arg_azimuth,
|
||||||
|
double arg_elevation,
|
||||||
|
double arg_range,
|
||||||
|
double arg_range_rate)
|
||||||
|
: azimuth(arg_azimuth),
|
||||||
|
elevation(arg_elevation),
|
||||||
|
range(arg_range),
|
||||||
|
range_rate(arg_range_rate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordTopographic(const CoordTopographic& t)
|
/**
|
||||||
|
* Copy constructor
|
||||||
|
* @param[in] topo object to copy from
|
||||||
|
*/
|
||||||
|
CoordTopographic(const CoordTopographic& topo)
|
||||||
{
|
{
|
||||||
azimuth = t.azimuth;
|
azimuth = topo.azimuth;
|
||||||
elevation = t.elevation;
|
elevation = topo.elevation;
|
||||||
range = t.range;
|
range = topo.range;
|
||||||
range_rate = t.range_rate;
|
range_rate = topo.range_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~CoordTopographic()
|
virtual ~CoordTopographic()
|
||||||
{
|
{
|
||||||
};
|
}
|
||||||
|
|
||||||
CoordTopographic& operator=(const CoordTopographic& t)
|
/**
|
||||||
|
* Assignment operator
|
||||||
|
* @param[in] topo object to copy from
|
||||||
|
*/
|
||||||
|
CoordTopographic& operator=(const CoordTopographic& topo)
|
||||||
{
|
{
|
||||||
if (this != &t) {
|
if (this != &topo)
|
||||||
azimuth = t.azimuth;
|
{
|
||||||
elevation = t.elevation;
|
azimuth = topo.azimuth;
|
||||||
range = t.range;
|
elevation = topo.elevation;
|
||||||
range_rate = t.range_rate;
|
range = topo.range;
|
||||||
|
range_rate = topo.range_rate;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const CoordTopographic& t) const
|
/**
|
||||||
|
* Equality operator
|
||||||
|
* @param[in] topo value to check
|
||||||
|
* @returns whether the object is equal
|
||||||
|
*/
|
||||||
|
bool operator==(const CoordTopographic& topo) const
|
||||||
{
|
{
|
||||||
return IsEqual(t);
|
return IsEqual(topo);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator !=(const CoordTopographic& t) const
|
/**
|
||||||
|
* Inequality operator
|
||||||
|
* @param[in] topo the object to compare with
|
||||||
|
* @returns whether the object is not equal
|
||||||
|
*/
|
||||||
|
bool operator !=(const CoordTopographic& topo) const
|
||||||
{
|
{
|
||||||
return !IsEqual(t);
|
return !IsEqual(topo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump this object to a string
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
std::string ToString() const
|
std::string ToString() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::right << std::fixed << std::setprecision(2);
|
ss << std::right << std::fixed << std::setprecision(3);
|
||||||
ss << "Az: " << std::setw(7) << Util::RadiansToDegrees(azimuth);
|
ss << "Az: " << std::setw(8) << Util::RadiansToDegrees(azimuth);
|
||||||
ss << ", El: " << std::setw(7) << Util::RadiansToDegrees(elevation);
|
ss << ", El: " << std::setw(8) << Util::RadiansToDegrees(elevation);
|
||||||
ss << ", Rng: " << std::setw(9) << range;
|
ss << ", Rng: " << std::setw(10) << range;
|
||||||
ss << ", Rng Rt: " << std::setw(6) << range_rate;
|
ss << ", Rng Rt: " << std::setw(7) << range_rate;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/** azimuth in radians */
|
||||||
* radians
|
|
||||||
*/
|
|
||||||
double azimuth;
|
double azimuth;
|
||||||
/*
|
/** elevations in radians */
|
||||||
* radians
|
|
||||||
*/
|
|
||||||
double elevation;
|
double elevation;
|
||||||
/*
|
/** range in kilometers */
|
||||||
* kilometers
|
|
||||||
*/
|
|
||||||
double range;
|
double range;
|
||||||
/*
|
/** range rate in kilometers per second */
|
||||||
* kilometers / second
|
|
||||||
*/
|
|
||||||
double range_rate;
|
double range_rate;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
bool IsEqual(const CoordTopographic& t) const
|
bool IsEqual(const CoordTopographic& topo) const
|
||||||
{
|
{
|
||||||
if (azimuth == t.azimuth && elevation == t.elevation &&
|
bool equal = false;
|
||||||
range == t.range && range_rate == t.range_rate)
|
if (azimuth == topo.azimuth &&
|
||||||
|
elevation == topo.elevation &&
|
||||||
|
range == topo.range &&
|
||||||
|
range_rate == topo.range_rate)
|
||||||
{
|
{
|
||||||
return true;
|
equal = true;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return equal;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -104,4 +144,3 @@ inline std::ostream& operator<<(std::ostream& strm, const CoordTopographic& t)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
#include "DateTime.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
bool jd_dmy(int JD, int c_year, int c_month, int c_day)
|
||||||
|
{
|
||||||
|
// For the Gregorian calendar:
|
||||||
|
int a = JD + 32044;
|
||||||
|
int b = (4 * a + 3) / 146097;
|
||||||
|
int c = a - (b * 146097) / 4;
|
||||||
|
|
||||||
|
// Then, for both calendars:
|
||||||
|
int d = (4 * c + 3) / 1461;
|
||||||
|
int e = c - (1461 * d) / 4;
|
||||||
|
int m = (5 * e + 2) / 153;
|
||||||
|
|
||||||
|
int day = e - (153 * m + 2) / 5 + 1;
|
||||||
|
int month = m + 3 - 12 * (m / 10);
|
||||||
|
int year = b * 100 + d - 4800 + m / 10;
|
||||||
|
|
||||||
|
if (c_year != year || c_month != month || c_day != day)
|
||||||
|
{
|
||||||
|
std::cout << year << " " << month << " " << day << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
for (int year = 1; year <= 9999; year++)
|
||||||
|
{
|
||||||
|
for (int month = 1; month <= 12; month++)
|
||||||
|
{
|
||||||
|
for (int day = 1; day <= DateTime::DaysInMonth(year, month); day++)
|
||||||
|
{
|
||||||
|
int hour = 23;
|
||||||
|
int minute = 59;
|
||||||
|
int second = 59;
|
||||||
|
int microsecond = 999999;
|
||||||
|
|
||||||
|
DateTime dt(year, month, day, hour, minute, second, microsecond);
|
||||||
|
|
||||||
|
if (dt.Year() != year ||
|
||||||
|
dt.Month() != month ||
|
||||||
|
dt.Day() != day ||
|
||||||
|
dt.Hour() != hour ||
|
||||||
|
dt.Minute() != minute ||
|
||||||
|
dt.Second() != second ||
|
||||||
|
dt.Microsecond() != microsecond)
|
||||||
|
{
|
||||||
|
std::cout << "failed" << std::endl;
|
||||||
|
std::cout << "Y " << dt.Year() << " " << year << std::endl;
|
||||||
|
std::cout << "M " << dt.Month() << " " << month << std::endl;
|
||||||
|
std::cout << "D " << dt.Day() << " " << day << std::endl;
|
||||||
|
std::cout << "H " << dt.Hour() << " " << hour << std::endl;
|
||||||
|
std::cout << "M " << dt.Minute() << " " << minute << std::endl;
|
||||||
|
std::cout << "S " << dt.Second() << " " << second << std::endl;
|
||||||
|
std::cout << "F " << dt.Microsecond() << " " << microsecond << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jd_dmy(dt.Julian() + 0.5, year, month, day))
|
||||||
|
{
|
||||||
|
std::cout << "julian" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int hour = 1; hour < 24; hour++)
|
||||||
|
{
|
||||||
|
std::cout << hour << std::endl;
|
||||||
|
for (int minute = 0; minute < 60; minute++)
|
||||||
|
{
|
||||||
|
for (int second = 0; second < 60; second++)
|
||||||
|
{
|
||||||
|
for (int microsecond = 0; microsecond < 1000000; microsecond += 10000)
|
||||||
|
{
|
||||||
|
int year = 1000;
|
||||||
|
int month = 10;
|
||||||
|
int day = 23;
|
||||||
|
|
||||||
|
DateTime dt(year, month, day, hour, minute, second, microsecond);
|
||||||
|
|
||||||
|
if (dt.Year() != year ||
|
||||||
|
dt.Month() != month ||
|
||||||
|
dt.Day() != day ||
|
||||||
|
dt.Hour() != hour ||
|
||||||
|
dt.Minute() != minute ||
|
||||||
|
dt.Second() != second ||
|
||||||
|
dt.Microsecond() != microsecond)
|
||||||
|
{
|
||||||
|
std::cout << "failed" << std::endl;
|
||||||
|
std::cout << "Y " << dt.Year() << " " << year << std::endl;
|
||||||
|
std::cout << "M " << dt.Month() << " " << month << std::endl;
|
||||||
|
std::cout << "D " << dt.Day() << " " << day << std::endl;
|
||||||
|
std::cout << "H " << dt.Hour() << " " << hour << std::endl;
|
||||||
|
std::cout << "M " << dt.Minute() << " " << minute << std::endl;
|
||||||
|
std::cout << "S " << dt.Second() << " " << second << std::endl;
|
||||||
|
std::cout << "F " << dt.Microsecond() << " " << microsecond << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jd_dmy(1721425.5, 0, 0, 0);
|
||||||
|
|
||||||
|
DateTime d1(1000, 1, 1);
|
||||||
|
DateTime d2(2000, 1, 1);
|
||||||
|
DateTime d3(4000, 1, 1);
|
||||||
|
DateTime d4(6000, 1, 1);
|
||||||
|
DateTime d5(8000, 1, 1);
|
||||||
|
|
||||||
|
std::cout << std::setprecision(20);
|
||||||
|
std::cout << d1.Julian() << std::endl;
|
||||||
|
std::cout << d2.Julian() << std::endl;
|
||||||
|
std::cout << d3.Julian() << std::endl;
|
||||||
|
std::cout << d4.Julian() << std::endl;
|
||||||
|
std::cout << d5.Julian() << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,585 @@
|
||||||
|
#ifndef DATETIME_H_
|
||||||
|
#define DATETIME_H_
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include "TimeSpan.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
static int daysInMonth[2][13] = {
|
||||||
|
// 1 2 3 4 5 6 7 8 9 10 11 12
|
||||||
|
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||||
|
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||||
|
};
|
||||||
|
static int cumulDaysInMonth[2][13] = {
|
||||||
|
// 1 2 3 4 5 6 7 8 9 10 11 12
|
||||||
|
{0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
|
||||||
|
{0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class DateTime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DateTime()
|
||||||
|
{
|
||||||
|
Initialise(1, 1, 1, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime(unsigned long long ticks)
|
||||||
|
: m_encoded(ticks)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime(int year, double doy)
|
||||||
|
{
|
||||||
|
m_encoded = TimeSpan(AbsoluteDays(year, doy) * TicksPerDay).Ticks();
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime(int year, int month, int day)
|
||||||
|
{
|
||||||
|
Initialise(year, month, day, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime(int year, int month, int day, int hour, int minute, int second)
|
||||||
|
{
|
||||||
|
Initialise(year, month, day, hour, minute, second, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime(int year,
|
||||||
|
int month,
|
||||||
|
int day,
|
||||||
|
int hour,
|
||||||
|
int minute,
|
||||||
|
int second,
|
||||||
|
int microsecond)
|
||||||
|
{
|
||||||
|
Initialise(year, month, day, hour, minute, second, microsecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialise(int year,
|
||||||
|
int month,
|
||||||
|
int day,
|
||||||
|
int hour,
|
||||||
|
int minute,
|
||||||
|
int second,
|
||||||
|
int microsecond)
|
||||||
|
{
|
||||||
|
if (!IsValidYearMonthDay(year, month, day) ||
|
||||||
|
hour < 0 || hour > 23 ||
|
||||||
|
minute < 0 || minute > 59 ||
|
||||||
|
second < 0 || second > 59 ||
|
||||||
|
microsecond < 0 || microsecond > 999999)
|
||||||
|
{
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
m_encoded = TimeSpan(
|
||||||
|
AbsoluteDays(year, month, day),
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second,
|
||||||
|
microsecond).Ticks();
|
||||||
|
}
|
||||||
|
|
||||||
|
static DateTime Now(bool microseconds = false)
|
||||||
|
{
|
||||||
|
DateTime dt;
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
|
||||||
|
{
|
||||||
|
if (microseconds)
|
||||||
|
{
|
||||||
|
dt = DateTime(UnixEpoch
|
||||||
|
+ ts.tv_sec * TicksPerSecond
|
||||||
|
+ ts.tv_nsec / 1000LL * TicksPerMicrosecond);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dt = DateTime(UnixEpoch
|
||||||
|
+ ts.tv_sec * TicksPerSecond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsLeapYear(int year)
|
||||||
|
{
|
||||||
|
if (!IsValidYear(year))
|
||||||
|
{
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsValidYear(int year)
|
||||||
|
{
|
||||||
|
bool valid = true;
|
||||||
|
if (year < 1 || year > 9999)
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsValidYearMonth(int year, int month)
|
||||||
|
{
|
||||||
|
bool valid = true;
|
||||||
|
if (IsValidYear(year))
|
||||||
|
{
|
||||||
|
if (month < 1 || month > 12)
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsValidYearMonthDay(int year, int month, int day)
|
||||||
|
{
|
||||||
|
bool valid = true;
|
||||||
|
if (IsValidYearMonth(year, month))
|
||||||
|
{
|
||||||
|
if (day < 1 || day > DaysInMonth(year, month))
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DaysInMonth(int year, int month)
|
||||||
|
{
|
||||||
|
if (!IsValidYearMonth(year, month))
|
||||||
|
{
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int* daysInMonthPtr;
|
||||||
|
|
||||||
|
if (IsLeapYear(year))
|
||||||
|
{
|
||||||
|
daysInMonthPtr = daysInMonth[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
daysInMonthPtr = daysInMonth[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return daysInMonthPtr[month];
|
||||||
|
}
|
||||||
|
|
||||||
|
int DayOfYear(int year, int month, int day) const
|
||||||
|
{
|
||||||
|
if (!IsValidYearMonthDay(year, month, day))
|
||||||
|
{
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int daysThisYear = day;
|
||||||
|
|
||||||
|
if (IsLeapYear(year))
|
||||||
|
{
|
||||||
|
daysThisYear += cumulDaysInMonth[1][month];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
daysThisYear += cumulDaysInMonth[0][month];
|
||||||
|
}
|
||||||
|
|
||||||
|
return daysThisYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
double AbsoluteDays(int year, double doy) const
|
||||||
|
{
|
||||||
|
|
||||||
|
int previousYear = year - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* + days in previous years ignoring leap days
|
||||||
|
* + Julian leap days before this year
|
||||||
|
* - minus prior century years
|
||||||
|
* + plus prior years divisible by 400 days
|
||||||
|
*/
|
||||||
|
long long daysSoFar = 365 * previousYear
|
||||||
|
+ previousYear / 4
|
||||||
|
- previousYear / 100
|
||||||
|
+ previousYear / 400;
|
||||||
|
|
||||||
|
return daysSoFar + doy - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbsoluteDays(int year, int month, int day) const
|
||||||
|
{
|
||||||
|
int previousYear = year - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* days this year (0 - ...)
|
||||||
|
* + days in previous years ignoring leap days
|
||||||
|
* + Julian leap days before this year
|
||||||
|
* - minus prior century years
|
||||||
|
* + plus prior years divisible by 400 days
|
||||||
|
*/
|
||||||
|
int result = DayOfYear(year, month, day) - 1
|
||||||
|
+ 365 * previousYear
|
||||||
|
+ previousYear / 4
|
||||||
|
- previousYear / 100
|
||||||
|
+ previousYear / 400;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeSpan TimeOfDay() const
|
||||||
|
{
|
||||||
|
return TimeSpan(Ticks() % TicksPerDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DayOfWeek() const
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The fixed day 1 (January 1, 1 Gregorian) is Monday.
|
||||||
|
* 0 Sunday
|
||||||
|
* 1 Monday
|
||||||
|
* 2 Tuesday
|
||||||
|
* 3 Wednesday
|
||||||
|
* 4 Thursday
|
||||||
|
* 5 Friday
|
||||||
|
* 6 Saturday
|
||||||
|
*/
|
||||||
|
return (((m_encoded / TicksPerDay) + 1) % 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Equals(const DateTime& dt) const
|
||||||
|
{
|
||||||
|
return (m_encoded == dt.m_encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compare(const DateTime& dt) const
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (m_encoded < dt.m_encoded)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (m_encoded > dt.m_encoded)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime AddYears(const int years) const
|
||||||
|
{
|
||||||
|
return AddMonths(years * 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime AddMonths(const int months) const
|
||||||
|
{
|
||||||
|
int year;
|
||||||
|
int month;
|
||||||
|
int day;
|
||||||
|
FromTicks(year, month, day);
|
||||||
|
month += months % 12;
|
||||||
|
year += months / 12;
|
||||||
|
|
||||||
|
if (month < 1)
|
||||||
|
{
|
||||||
|
month += 12;
|
||||||
|
--year;
|
||||||
|
}
|
||||||
|
else if (month > 12)
|
||||||
|
{
|
||||||
|
month -= 12;
|
||||||
|
++year;
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxday = DaysInMonth(year, month);
|
||||||
|
day = std::min(day, maxday);
|
||||||
|
|
||||||
|
return DateTime(year, month, day).Add(TimeOfDay());
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime Add(const TimeSpan& t) const
|
||||||
|
{
|
||||||
|
return AddTicks(t.Ticks());
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime AddDays(const double days) const
|
||||||
|
{
|
||||||
|
return AddMicroseconds(days * 86400000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime AddHours(const double hours) const
|
||||||
|
{
|
||||||
|
return AddMicroseconds(hours * 3600000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime AddMinutes(const double minutes) const
|
||||||
|
{
|
||||||
|
return AddMicroseconds(minutes * 60000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime AddSeconds(const double seconds) const
|
||||||
|
{
|
||||||
|
return AddMicroseconds(seconds * 1000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime AddMicroseconds(const double microseconds) const
|
||||||
|
{
|
||||||
|
long long ticks = microseconds * TicksPerMicrosecond;
|
||||||
|
return AddTicks(ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime AddTicks(long long ticks) const
|
||||||
|
{
|
||||||
|
return DateTime(m_encoded + ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
long long Ticks() const
|
||||||
|
{
|
||||||
|
return m_encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FromTicks(int& year, int& month, int& day) const
|
||||||
|
{
|
||||||
|
int totalDays = m_encoded / TicksPerDay;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* number of 400 year cycles
|
||||||
|
*/
|
||||||
|
int num400 = totalDays / 146097;
|
||||||
|
totalDays -= num400 * 146097;
|
||||||
|
/*
|
||||||
|
* number of 100 year cycles
|
||||||
|
*/
|
||||||
|
int num100 = totalDays / 36524;
|
||||||
|
if (num100 == 4)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* last day of the last leap century
|
||||||
|
*/
|
||||||
|
num100 = 3;
|
||||||
|
}
|
||||||
|
totalDays -= num100 * 36524;
|
||||||
|
/*
|
||||||
|
* number of 4 year cycles
|
||||||
|
*/
|
||||||
|
int num4 = totalDays / 1461;
|
||||||
|
totalDays -= num4 * 1461;
|
||||||
|
/*
|
||||||
|
* number of years
|
||||||
|
*/
|
||||||
|
int num1 = totalDays / 365;
|
||||||
|
if (num1 == 4)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* last day of the last leap olympiad
|
||||||
|
*/
|
||||||
|
num1 = 3;
|
||||||
|
}
|
||||||
|
totalDays -= num1 * 365;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find year
|
||||||
|
*/
|
||||||
|
year = (num400 * 400) + (num100 * 100) + (num4 * 4) + num1 + 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* convert day of year to month/day
|
||||||
|
*/
|
||||||
|
const int* daysInMonthPtr;
|
||||||
|
if (IsLeapYear(year))
|
||||||
|
{
|
||||||
|
daysInMonthPtr = daysInMonth[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
daysInMonthPtr = daysInMonth[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
month = 1;
|
||||||
|
while (totalDays >= daysInMonthPtr[month] && month <= 12)
|
||||||
|
{
|
||||||
|
totalDays -= daysInMonthPtr[month++];
|
||||||
|
}
|
||||||
|
|
||||||
|
day = totalDays + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Year() const
|
||||||
|
{
|
||||||
|
int year;
|
||||||
|
int month;
|
||||||
|
int day;
|
||||||
|
FromTicks(year, month, day);
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Month() const
|
||||||
|
{
|
||||||
|
int year;
|
||||||
|
int month;
|
||||||
|
int day;
|
||||||
|
FromTicks(year, month, day);
|
||||||
|
return month;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Day() const
|
||||||
|
{
|
||||||
|
int year;
|
||||||
|
int month;
|
||||||
|
int day;
|
||||||
|
FromTicks(year, month, day);
|
||||||
|
return day;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Hour() const
|
||||||
|
{
|
||||||
|
return m_encoded % TicksPerDay / TicksPerHour;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Minute() const
|
||||||
|
{
|
||||||
|
return m_encoded % TicksPerHour / TicksPerMinute;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Second() const
|
||||||
|
{
|
||||||
|
return m_encoded % TicksPerMinute / TicksPerSecond;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Microsecond() const
|
||||||
|
{
|
||||||
|
return m_encoded % TicksPerSecond / TicksPerMicrosecond;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Julian() const
|
||||||
|
{
|
||||||
|
TimeSpan ts = TimeSpan(Ticks());
|
||||||
|
return ts.TotalDays() + 1721425.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ToGreenwichSiderealTime() const
|
||||||
|
{
|
||||||
|
// t = Julian centuries from 2000 Jan. 1 12h UT1
|
||||||
|
const double t = (Julian() - 2451545.0) / 36525.0;
|
||||||
|
|
||||||
|
// Rotation angle in arcseconds
|
||||||
|
double theta = 67310.54841
|
||||||
|
+ (876600.0 * 3600.0 + 8640184.812866) * t
|
||||||
|
+ 0.093104 * t * t
|
||||||
|
- 0.0000062 * t * t * t;
|
||||||
|
|
||||||
|
// 360.0 / 86400.0 = 1.0 / 240.0
|
||||||
|
return Util::WrapTwoPI(Util::DegreesToRadians(theta / 240.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
double ToLocalMeanSiderealTime(const double& lon) const
|
||||||
|
{
|
||||||
|
return Util::WrapTwoPI(ToGreenwichSiderealTime() + lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToString() const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
int year;
|
||||||
|
int month;
|
||||||
|
int day;
|
||||||
|
FromTicks(year, month, day);
|
||||||
|
ss << std::right << std::setfill('0');
|
||||||
|
ss << std::setw(4) << year << "-";
|
||||||
|
ss << std::setw(2) << month << "-";
|
||||||
|
ss << std::setw(2) << day << " ";
|
||||||
|
ss << std::setw(2) << Hour() << ":";
|
||||||
|
ss << std::setw(2) << Minute() << ":";
|
||||||
|
ss << std::setw(2) << Second() << ".";
|
||||||
|
ss << std::setw(6) << Microsecond() << " UTC";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned long long m_encoded;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& strm, const DateTime& dt)
|
||||||
|
{
|
||||||
|
return strm << dt.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DateTime operator+(const DateTime& dt, TimeSpan ts)
|
||||||
|
{
|
||||||
|
long long int res = dt.Ticks() + ts.Ticks();
|
||||||
|
if (res < 0 || res > MaxValueTicks)
|
||||||
|
{
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DateTime(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DateTime operator-(const DateTime& dt, const TimeSpan& ts)
|
||||||
|
{
|
||||||
|
long long int res = dt.Ticks() - ts.Ticks();
|
||||||
|
if (res < 0 || res > MaxValueTicks)
|
||||||
|
{
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DateTime(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TimeSpan operator-(const DateTime& dt1, const DateTime& dt2)
|
||||||
|
{
|
||||||
|
return TimeSpan(dt1.Ticks() - dt2.Ticks());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const DateTime& dt1, const DateTime& dt2)
|
||||||
|
{
|
||||||
|
return dt1.Equals(dt2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator>(const DateTime& dt1, const DateTime& dt2)
|
||||||
|
{
|
||||||
|
return (dt1.Compare(dt2) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator>=(const DateTime& dt1, const DateTime& dt2)
|
||||||
|
{
|
||||||
|
return (dt1.Compare(dt2) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const DateTime& dt1, const DateTime& dt2)
|
||||||
|
{
|
||||||
|
return !dt1.Equals(dt2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<(const DateTime& dt1, const DateTime& dt2)
|
||||||
|
{
|
||||||
|
return (dt1.Compare(dt2) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<=(const DateTime& dt1, const DateTime& dt2)
|
||||||
|
{
|
||||||
|
return (dt1.Compare(dt2) <= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -2,44 +2,65 @@
|
||||||
#define DECAYEDEXCEPTION_H_
|
#define DECAYEDEXCEPTION_H_
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
|
||||||
#include "Julian.h"
|
#include "DateTime.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
|
|
||||||
class DecayedException : public std::exception
|
class DecayedException : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DecayedException(const Julian& dt, const Vector& pos, const Vector& vel)
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param[in] dt time of the event
|
||||||
|
* @param[in] pos position of the satellite at dt
|
||||||
|
* @param[in] vel velocity of the satellite at dt
|
||||||
|
*/
|
||||||
|
DecayedException(const DateTime& dt, const Vector& pos, const Vector& vel)
|
||||||
: _dt(dt), _pos(pos), _vel(vel)
|
: _dt(dt), _pos(pos), _vel(vel)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~DecayedException(void) throw ()
|
virtual ~DecayedException(void) throw ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the error string
|
||||||
|
*/
|
||||||
virtual const char* what() const throw ()
|
virtual const char* what() const throw ()
|
||||||
{
|
{
|
||||||
return "Error: Satellite decayed";
|
return "Error: Satellite decayed";
|
||||||
}
|
}
|
||||||
|
|
||||||
Julian GetDate() const
|
/**
|
||||||
|
* @returns the date
|
||||||
|
*/
|
||||||
|
DateTime GetDateTime() const
|
||||||
{
|
{
|
||||||
return _dt;
|
return _dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the position
|
||||||
|
*/
|
||||||
Vector GetPosition() const
|
Vector GetPosition() const
|
||||||
{
|
{
|
||||||
return _pos;
|
return _pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the velocity
|
||||||
|
*/
|
||||||
Vector GetVelocity() const
|
Vector GetVelocity() const
|
||||||
{
|
{
|
||||||
return _vel;
|
return _vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Julian _dt;
|
DateTime _dt;
|
||||||
Vector _pos;
|
Vector _pos;
|
||||||
Vector _vel;
|
Vector _vel;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,34 @@
|
||||||
#include "Eci.h"
|
#include "Eci.h"
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
void Eci::ToEci(const Julian& date, const CoordGeodetic &g)
|
/**
|
||||||
|
* Converts a DateTime and Geodetic position to Eci coordinates
|
||||||
|
* @param[in] dt the date
|
||||||
|
* @param[in] geo the geodetic position
|
||||||
|
*/
|
||||||
|
void Eci::ToEci(const DateTime& dt, const CoordGeodetic &geo)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* set date
|
* set date
|
||||||
*/
|
*/
|
||||||
date_ = date;
|
m_dt = dt;
|
||||||
|
|
||||||
static const double mfactor = kTWOPI * (kOMEGA_E / kSECONDS_PER_DAY);
|
static const double mfactor = kTWOPI * (kOMEGA_E / kSECONDS_PER_DAY);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate Local Mean Sidereal Time for observers longitude
|
* Calculate Local Mean Sidereal Time for observers longitude
|
||||||
*/
|
*/
|
||||||
const double theta = date_.ToLocalMeanSiderealTime(g.longitude);
|
const double theta = m_dt.ToLocalMeanSiderealTime(geo.longitude);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* take into account earth flattening
|
* take into account earth flattening
|
||||||
*/
|
*/
|
||||||
const double c = 1.0
|
const double c = 1.0
|
||||||
/ sqrt(1.0 + kF * (kF - 2.0) * pow(sin(g.latitude), 2.0));
|
/ sqrt(1.0 + kF * (kF - 2.0) * pow(sin(geo.latitude), 2.0));
|
||||||
const double s = pow(1.0 - kF, 2.0) * c;
|
const double s = pow(1.0 - kF, 2.0) * c;
|
||||||
const double achcp = (kXKMPER * c + g.altitude) * cos(g.latitude);
|
const double achcp = (kXKMPER * c + geo.altitude) * cos(geo.latitude);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* X position in km
|
* X position in km
|
||||||
|
|
@ -30,10 +36,10 @@ void Eci::ToEci(const Julian& date, const CoordGeodetic &g)
|
||||||
* Z position in km
|
* Z position in km
|
||||||
* W magnitude in km
|
* W magnitude in km
|
||||||
*/
|
*/
|
||||||
position_.x = achcp * cos(theta);
|
m_position.x = achcp * cos(theta);
|
||||||
position_.y = achcp * sin(theta);
|
m_position.y = achcp * sin(theta);
|
||||||
position_.z = (kXKMPER * s + g.altitude) * sin(g.latitude);
|
m_position.z = (kXKMPER * s + geo.altitude) * sin(geo.latitude);
|
||||||
position_.w = position_.GetMagnitude();
|
m_position.w = m_position.GetMagnitude();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* X velocity in km/s
|
* X velocity in km/s
|
||||||
|
|
@ -41,27 +47,28 @@ void Eci::ToEci(const Julian& date, const CoordGeodetic &g)
|
||||||
* Z velocity in km/s
|
* Z velocity in km/s
|
||||||
* W magnitude in km/s
|
* W magnitude in km/s
|
||||||
*/
|
*/
|
||||||
velocity_.x = -mfactor * position_.y;
|
m_velocity.x = -mfactor * m_position.y;
|
||||||
velocity_.y = mfactor * position_.x;
|
m_velocity.y = mfactor * m_position.x;
|
||||||
velocity_.z = 0.0;
|
m_velocity.z = 0.0;
|
||||||
velocity_.w = velocity_.GetMagnitude();
|
m_velocity.w = m_velocity.GetMagnitude();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the position in geodetic form
|
||||||
|
*/
|
||||||
CoordGeodetic Eci::ToGeodetic() const
|
CoordGeodetic Eci::ToGeodetic() const
|
||||||
{
|
{
|
||||||
const double theta = Util::AcTan(position_.y, position_.x);
|
const double theta = Util::AcTan(m_position.y, m_position.x);
|
||||||
|
|
||||||
// 0 >= lon < 360
|
const double lon = Util::WrapNegPosPI(theta
|
||||||
// const double lon = Fmod2p(theta - date_.ToGreenwichSiderealTime());
|
- m_dt.ToGreenwichSiderealTime());
|
||||||
// 180 >= lon < 180
|
|
||||||
const double lon = Util::WrapNegPosPI(theta - date_.ToGreenwichSiderealTime());
|
|
||||||
|
|
||||||
const double r = sqrt((position_.x * position_.x)
|
const double r = sqrt((m_position.x * m_position.x)
|
||||||
+ (position_.y * position_.y));
|
+ (m_position.y * m_position.y));
|
||||||
|
|
||||||
static const double e2 = kF * (2.0 - kF);
|
static const double e2 = kF * (2.0 - kF);
|
||||||
|
|
||||||
double lat = Util::AcTan(position_.z, r);
|
double lat = Util::AcTan(m_position.z, r);
|
||||||
double phi = 0.0;
|
double phi = 0.0;
|
||||||
double c = 0.0;
|
double c = 0.0;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
@ -71,12 +78,12 @@ CoordGeodetic Eci::ToGeodetic() const
|
||||||
phi = lat;
|
phi = lat;
|
||||||
const double sinphi = sin(phi);
|
const double sinphi = sin(phi);
|
||||||
c = 1.0 / sqrt(1.0 - e2 * sinphi * sinphi);
|
c = 1.0 / sqrt(1.0 - e2 * sinphi * sinphi);
|
||||||
lat = Util::AcTan(position_.z + kXKMPER * c * e2 * sinphi, r);
|
lat = Util::AcTan(m_position.z + kXKMPER * c * e2 * sinphi, r);
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
while (fabs(lat - phi) >= 1e-10 && cnt < 10);
|
while (fabs(lat - phi) >= 1e-10 && cnt < 10);
|
||||||
|
|
||||||
const double alt = r / cos(lat) - kXKMPER * c;
|
const double alt = r / cos(lat) - kXKMPER * c;
|
||||||
|
|
||||||
return CoordGeodetic(lat, lon, alt, true);
|
return CoordGeodetic(lat, lon, alt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
116
libsgp4/Eci.h
116
libsgp4/Eci.h
|
|
@ -3,67 +3,133 @@
|
||||||
|
|
||||||
#include "CoordGeodetic.h"
|
#include "CoordGeodetic.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "Julian.h"
|
#include "DateTime.h"
|
||||||
#include "Globals.h"
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class store to store an Earth-centered inertial position.
|
||||||
|
* This is only valid for the date specified.
|
||||||
|
*/
|
||||||
class Eci
|
class Eci
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* in degrees
|
* @param[in] dt the date to be used for this position
|
||||||
|
* @param[in] latitude the latitude in degrees
|
||||||
|
* @param[in] longitude the longitude in degrees
|
||||||
|
* @param[in] altitude the altitude in kilometers
|
||||||
*/
|
*/
|
||||||
Eci(const Julian& date, double latitude, double longitude, double altitude)
|
Eci(const DateTime& dt,
|
||||||
|
const double latitude,
|
||||||
|
const double longitude,
|
||||||
|
const double altitude)
|
||||||
{
|
{
|
||||||
ToEci(date, CoordGeodetic(latitude, longitude, altitude));
|
ToEci(dt, CoordGeodetic(latitude, longitude, altitude));
|
||||||
}
|
}
|
||||||
|
|
||||||
Eci(const Julian& date, const CoordGeodetic& g)
|
/**
|
||||||
|
* @param[in] dt the date to be used for this position
|
||||||
|
* @param[in] geo the position
|
||||||
|
*/
|
||||||
|
Eci(const DateTime& dt, const CoordGeodetic& geo)
|
||||||
{
|
{
|
||||||
ToEci(date, g);
|
ToEci(dt, geo);
|
||||||
}
|
}
|
||||||
|
|
||||||
Eci(const Julian &date, const Vector &position)
|
/**
|
||||||
: date_(date), position_(position)
|
* @param[in] dt the date to be used for this position
|
||||||
|
* @param[in] position
|
||||||
|
*/
|
||||||
|
Eci(const DateTime &dt, const Vector &position)
|
||||||
|
: m_dt(dt),
|
||||||
|
m_position(position)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Eci(const Julian &date, const Vector &position, const Vector &velocity)
|
/**
|
||||||
: date_(date), position_(position), velocity_(velocity)
|
* @param[in] dt the date to be used for this position
|
||||||
|
* @param[in] position the position
|
||||||
|
* @param[in] velocity the velocity
|
||||||
|
*/
|
||||||
|
Eci(const DateTime &dt, const Vector &position, const Vector &velocity)
|
||||||
|
: m_dt(dt),
|
||||||
|
m_position(position),
|
||||||
|
m_velocity(velocity)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~Eci()
|
virtual ~Eci()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equality operator
|
||||||
|
* @param dt the date to compare
|
||||||
|
* @returns true if the object matches
|
||||||
|
*/
|
||||||
|
bool operator==(const DateTime& dt) const
|
||||||
|
{
|
||||||
|
return m_dt == dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inequality operator
|
||||||
|
* @param dt the date to compare
|
||||||
|
* @returns true if the object doesn't match
|
||||||
|
*/
|
||||||
|
bool operator!=(const DateTime& dt) const
|
||||||
|
{
|
||||||
|
return m_dt != dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this object with a new date and geodetic position
|
||||||
|
* @param dt new date
|
||||||
|
* @param geo new geodetic position
|
||||||
|
*/
|
||||||
|
void Update(const DateTime& dt, const CoordGeodetic& geo)
|
||||||
|
{
|
||||||
|
ToEci(dt, geo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the position
|
||||||
|
*/
|
||||||
Vector GetPosition() const
|
Vector GetPosition() const
|
||||||
{
|
{
|
||||||
return position_;
|
return m_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the velocity
|
||||||
|
*/
|
||||||
Vector GetVelocity() const
|
Vector GetVelocity() const
|
||||||
{
|
{
|
||||||
return velocity_;
|
return m_velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
Julian GetDate() const
|
/**
|
||||||
|
* @returns the date
|
||||||
|
*/
|
||||||
|
DateTime GetDateTime() const
|
||||||
{
|
{
|
||||||
return date_;
|
return m_dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the position in geodetic form
|
||||||
|
*/
|
||||||
CoordGeodetic ToGeodetic() const;
|
CoordGeodetic ToGeodetic() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
void ToEci(const Julian& date, double latitude, double longitude,
|
|
||||||
double altitude);
|
|
||||||
void ToEci(const Julian& date, const CoordGeodetic& g);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Julian date_;
|
void ToEci(const DateTime& dt, const CoordGeodetic& geo);
|
||||||
Vector position_;
|
|
||||||
Vector velocity_;
|
DateTime m_dt;
|
||||||
|
Vector m_position;
|
||||||
|
Vector m_velocity;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,308 +0,0 @@
|
||||||
#include "Globals.h"
|
|
||||||
#include "Julian.h"
|
|
||||||
#include "Util.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <ctime>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Julian::Julian()
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
SYSTEMTIME st;
|
|
||||||
GetSystemTime(&st);
|
|
||||||
Initialize(st.wYear,
|
|
||||||
st.wMonth,
|
|
||||||
st.wDay,
|
|
||||||
st.wHour,
|
|
||||||
st.wMinute,
|
|
||||||
(double) st.wSecond + (double) st.wMilliseconds / 1000.0);
|
|
||||||
#else
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
struct tm gmt;
|
|
||||||
gmtime_r(&tv.tv_sec, &gmt);
|
|
||||||
Initialize(gmt.tm_year + 1900,
|
|
||||||
gmt.tm_mon + 1,
|
|
||||||
gmt.tm_mday,
|
|
||||||
gmt.tm_hour,
|
|
||||||
gmt.tm_min,
|
|
||||||
(double) gmt.tm_sec + (double) tv.tv_usec / 1000000.0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* create julian date given time_t value
|
|
||||||
*/
|
|
||||||
Julian::Julian(const time_t t)
|
|
||||||
{
|
|
||||||
struct tm ptm;
|
|
||||||
#if WIN32
|
|
||||||
if (gmtime_s(&ptm, &t))
|
|
||||||
{
|
|
||||||
assert(1);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (gmtime_r(&t, &ptm) == NULL)
|
|
||||||
{
|
|
||||||
assert(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
int year = ptm.tm_year + 1900;
|
|
||||||
double day = ptm.tm_yday + 1 +
|
|
||||||
(ptm.tm_hour +
|
|
||||||
((ptm.tm_min +
|
|
||||||
(ptm.tm_sec / 60.0)) / 60.0)) / 24.0;
|
|
||||||
|
|
||||||
Initialize(year, day);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* comparison
|
|
||||||
*/
|
|
||||||
bool Julian::operator==(const Julian &date) const
|
|
||||||
{
|
|
||||||
return date_ == date.date_ ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Julian::operator!=(const Julian &date) const
|
|
||||||
{
|
|
||||||
return !(*this == date);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Julian::operator>(const Julian &date) const
|
|
||||||
{
|
|
||||||
return date_ > date.date_ ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Julian::operator<(const Julian &date) const {
|
|
||||||
|
|
||||||
return date_ < date.date_ ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Julian::operator>=(const Julian &date) const
|
|
||||||
{
|
|
||||||
return date_ >= date.date_ ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Julian::operator<=(const Julian &date) const
|
|
||||||
{
|
|
||||||
return date_ <= date.date_ ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* assignment
|
|
||||||
*/
|
|
||||||
Julian& Julian::operator=(const Julian& b)
|
|
||||||
{
|
|
||||||
if (this != &b) {
|
|
||||||
date_ = b.date_;
|
|
||||||
}
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Julian& Julian::operator=(const double b)
|
|
||||||
{
|
|
||||||
date_ = b;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* arithmetic
|
|
||||||
*/
|
|
||||||
Julian Julian::operator +(const Timespan& b) const
|
|
||||||
{
|
|
||||||
return Julian(*this) += b;
|
|
||||||
}
|
|
||||||
|
|
||||||
Julian Julian::operator-(const Timespan& b) const
|
|
||||||
{
|
|
||||||
return Julian(*this) -= b;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan Julian::operator-(const Julian& b) const
|
|
||||||
{
|
|
||||||
return Timespan(date_ - b.date_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* compound assignment
|
|
||||||
*/
|
|
||||||
Julian & Julian::operator +=(const Timespan& b)
|
|
||||||
{
|
|
||||||
date_ += b;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Julian & Julian::operator -=(const Timespan& b)
|
|
||||||
{
|
|
||||||
date_ -= b;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* create julian date from year and day of year
|
|
||||||
*/
|
|
||||||
void Julian::Initialize(int year, double day)
|
|
||||||
{
|
|
||||||
year--;
|
|
||||||
|
|
||||||
int A = (year / 100);
|
|
||||||
int B = 2 - A + (A / 4);
|
|
||||||
|
|
||||||
double new_years = static_cast<int> (365.25 * year) +
|
|
||||||
static_cast<int> (30.6001 * 14) +
|
|
||||||
1720994.5 + B;
|
|
||||||
|
|
||||||
date_ = new_years + day;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* create julian date from individual components
|
|
||||||
* year: 2004
|
|
||||||
* mon: 1-12
|
|
||||||
* day: 1-31
|
|
||||||
* hour: 0-23
|
|
||||||
* min: 0-59
|
|
||||||
* sec: 0-59.99
|
|
||||||
*/
|
|
||||||
void Julian::Initialize(int year, int mon, int day,
|
|
||||||
int hour, int min, double sec)
|
|
||||||
{
|
|
||||||
// Calculate N, the day of the year (1..366)
|
|
||||||
int N;
|
|
||||||
int F1 = (int) ((275.0 * mon) / 9.0);
|
|
||||||
int F2 = (int) ((mon + 9.0) / 12.0);
|
|
||||||
|
|
||||||
if (IsLeapYear(year))
|
|
||||||
{
|
|
||||||
// Leap year
|
|
||||||
N = F1 - F2 + day - 30;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Common year
|
|
||||||
N = F1 - (2 * F2) + day - 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
double dblDay = N + (hour + (min + (sec / 60.0)) / 60.0) / 24.0;
|
|
||||||
|
|
||||||
Initialize(year, dblDay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* converts time to time_t
|
|
||||||
* note: resolution to seconds only
|
|
||||||
*/
|
|
||||||
time_t Julian::ToTime() const
|
|
||||||
{
|
|
||||||
return static_cast<time_t> ((date_ - 2440587.5) * 86400.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Greenwich Mean Sidereal Time
|
|
||||||
*/
|
|
||||||
double Julian::ToGreenwichSiderealTime() const
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
const double UT = fmod(jul + 0.5, 1.0);
|
|
||||||
const double TU = (jul - 2451545.0 - UT) / 36525.0;
|
|
||||||
|
|
||||||
double GMST = 24110.54841 + TU *
|
|
||||||
(8640184.812866 + TU * (0.093104 - TU * 6.2e-06));
|
|
||||||
|
|
||||||
GMST = fmod(GMST + SEC_PER_DAY * OMEGA_E * UT, SEC_PER_DAY);
|
|
||||||
|
|
||||||
if (GMST < 0.0)
|
|
||||||
{
|
|
||||||
GMST += SEC_PER_DAY; // "wrap" negative modulo value
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TWOPI * (GMST / SEC_PER_DAY));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// tut1 = Julian centuries from 2000 Jan. 1 12h UT1
|
|
||||||
// (since J2000 which is 2451545.0)
|
|
||||||
// a Julian century is 36525 days
|
|
||||||
const double tut1 = (date_ - 2451545.0) / 36525.0;
|
|
||||||
const double tut2 = tut1 * tut1;
|
|
||||||
const double tut3 = tut2 * tut1;
|
|
||||||
|
|
||||||
// Rotation angle in arcseconds
|
|
||||||
double theta = 67310.54841 + (876600.0 * 3600.0 + 8640184.812866) * tut1
|
|
||||||
+ 0.093104 * tut2 - 0.0000062 * tut3;
|
|
||||||
|
|
||||||
// 360.0 / 86400.0 = 1.0 / 240.0
|
|
||||||
theta = Util::WrapTwoPI(Util::DegreesToRadians(theta / 240.0));
|
|
||||||
|
|
||||||
return theta;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static const double C1 = 1.72027916940703639e-2;
|
|
||||||
static const double THGR70 = 1.7321343856509374;
|
|
||||||
static const double FK5R = 5.07551419432269442e-15;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get integer number of days from 0 jan 1970
|
|
||||||
*/
|
|
||||||
const double ts70 = date_ - 2433281.5 - 7305.0;
|
|
||||||
const double ds70 = floor(ts70 + 1.0e-8);
|
|
||||||
const double tfrac = ts70 - ds70;
|
|
||||||
/*
|
|
||||||
* find greenwich location at epoch
|
|
||||||
*/
|
|
||||||
const double c1p2p = C1 + kTWOPI;
|
|
||||||
double gsto = Util::WrapTwoPI(THGR70 + C1 * ds70 + c1p2p * tfrac
|
|
||||||
+ ts70 * ts70 * FK5R);
|
|
||||||
|
|
||||||
return gsto;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local Mean Sideral Time
|
|
||||||
*/
|
|
||||||
double Julian::ToLocalMeanSiderealTime(const double& lon) const
|
|
||||||
{
|
|
||||||
return fmod(ToGreenwichSiderealTime() + lon, kTWOPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Julian::ToGregorian(struct DateTimeComponents* datetime) const
|
|
||||||
{
|
|
||||||
double jdAdj = GetDate() + 0.5;
|
|
||||||
int Z = (int) jdAdj;
|
|
||||||
double F = jdAdj - Z;
|
|
||||||
|
|
||||||
int A = 0;
|
|
||||||
|
|
||||||
if (Z < 2299161)
|
|
||||||
{
|
|
||||||
A = static_cast<int> (Z);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int a = static_cast<int> ((Z - 1867216.25) / 36524.25);
|
|
||||||
A = static_cast<int> (Z + 1 + a - static_cast<int> (a / 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
int B = A + 1524;
|
|
||||||
int C = static_cast<int> ((B - 122.1) / 365.25);
|
|
||||||
int D = static_cast<int> (365.25 * C);
|
|
||||||
int E = static_cast<int> ((B - D) / 30.6001);
|
|
||||||
|
|
||||||
datetime->hours = static_cast<int> (F * 24.0);
|
|
||||||
F -= datetime->hours / 24.0;
|
|
||||||
datetime->minutes = static_cast<int> (F * 1440.0);
|
|
||||||
F -= datetime->minutes / 1440.0;
|
|
||||||
datetime->seconds = F * 86400.0;
|
|
||||||
|
|
||||||
datetime->days = B - D - static_cast<int> (30.6001 * E);
|
|
||||||
datetime->months = E < 14 ? E - 1 : E - 13;
|
|
||||||
datetime->years = datetime->months > 2 ? C - 4716 : C - 4715;
|
|
||||||
}
|
|
||||||
168
libsgp4/Julian.h
168
libsgp4/Julian.h
|
|
@ -1,168 +0,0 @@
|
||||||
#ifndef JULIAN_H_
|
|
||||||
#define JULIAN_H_
|
|
||||||
|
|
||||||
#include "Globals.h"
|
|
||||||
#include "Timespan.h"
|
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
class Julian
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Julian();
|
|
||||||
|
|
||||||
Julian(const Julian& jul)
|
|
||||||
{
|
|
||||||
date_ = jul.date_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Julian(const time_t t);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* create julian date from year and day of year
|
|
||||||
*/
|
|
||||||
Julian(int year, double day)
|
|
||||||
{
|
|
||||||
Initialize(year, day);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* create julian date from individual components
|
|
||||||
* year: 2004
|
|
||||||
* mon: 1-12
|
|
||||||
* day: 1-31
|
|
||||||
* hour: 0-23
|
|
||||||
* min: 0-59
|
|
||||||
* sec: 0-59.99
|
|
||||||
*/
|
|
||||||
Julian(int year, int mon, int day, int hour, int min, double sec)
|
|
||||||
{
|
|
||||||
Initialize(year, mon, day, hour, min, sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Julian()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// comparison operators
|
|
||||||
bool operator==(const Julian &date) const;
|
|
||||||
bool operator!=(const Julian &date) const;
|
|
||||||
bool operator>(const Julian &date) const;
|
|
||||||
bool operator<(const Julian &date) const;
|
|
||||||
bool operator>=(const Julian &date) const;
|
|
||||||
bool operator<=(const Julian &date) const;
|
|
||||||
|
|
||||||
// assignment
|
|
||||||
Julian& operator =(const Julian& b);
|
|
||||||
Julian& operator =(const double b);
|
|
||||||
// arithmetic
|
|
||||||
Julian operator +(const Timespan& b) const;
|
|
||||||
Julian operator -(const Timespan& b) const;
|
|
||||||
Timespan operator -(const Julian& b) const;
|
|
||||||
// compound assignment
|
|
||||||
Julian & operator +=(const Timespan& b);
|
|
||||||
Julian & operator -=(const Timespan& b);
|
|
||||||
|
|
||||||
std::string ToString() const
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
struct DateTimeComponents dt;
|
|
||||||
ToGregorian(&dt);
|
|
||||||
ss << std::right << std::fixed;
|
|
||||||
ss << std::setprecision(6) << std::setfill('0');
|
|
||||||
ss << std::setw(4) << dt.years << "-";
|
|
||||||
ss << std::setw(2) << dt.months << "-";
|
|
||||||
ss << std::setw(2) << dt.days << " ";
|
|
||||||
ss << std::setw(2) << dt.hours << ":";
|
|
||||||
ss << std::setw(2) << dt.minutes << ":";
|
|
||||||
ss << std::setw(9) << dt.seconds << " UTC";
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DateTimeComponents {
|
|
||||||
|
|
||||||
DateTimeComponents()
|
|
||||||
: years(0), months(0), days(0),
|
|
||||||
hours(0), minutes(0), seconds(0.0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
int years;
|
|
||||||
int months;
|
|
||||||
int days;
|
|
||||||
int hours;
|
|
||||||
int minutes;
|
|
||||||
double seconds;
|
|
||||||
};
|
|
||||||
|
|
||||||
void ToGregorian(struct DateTimeComponents* datetime) const;
|
|
||||||
|
|
||||||
time_t ToTime() const;
|
|
||||||
double ToGreenwichSiderealTime() const;
|
|
||||||
double ToLocalMeanSiderealTime(const double& lon) const;
|
|
||||||
|
|
||||||
double FromJan1_00h_1900() const
|
|
||||||
{
|
|
||||||
return date_ - kEPOCH_JAN1_00H_1900;
|
|
||||||
}
|
|
||||||
|
|
||||||
double FromJan1_12h_1900() const
|
|
||||||
{
|
|
||||||
return date_ - kEPOCH_JAN1_12H_1900;
|
|
||||||
}
|
|
||||||
|
|
||||||
double FromJan1_12h_2000() const
|
|
||||||
{
|
|
||||||
return date_ - kEPOCH_JAN1_12H_2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
double GetDate() const
|
|
||||||
{
|
|
||||||
return date_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddDay(double day)
|
|
||||||
{
|
|
||||||
date_ += day;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddHour(double hr)
|
|
||||||
{
|
|
||||||
date_ += (hr / kHOURS_PER_DAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddMin(double min)
|
|
||||||
{
|
|
||||||
date_ += (min / kMINUTES_PER_DAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddSec(double sec)
|
|
||||||
{
|
|
||||||
date_ += (sec / kSECONDS_PER_DAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsLeapYear(int y)
|
|
||||||
{
|
|
||||||
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void Initialize(int year, double day);
|
|
||||||
void Initialize(int year, int mon, int day, int hour, int min, double sec);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* the stored julian date
|
|
||||||
*/
|
|
||||||
double date_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& strm, const Julian& j)
|
|
||||||
{
|
|
||||||
return strm << j.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -2,24 +2,22 @@ lib_LIBRARIES = libsgp4.a
|
||||||
libsgp4_a_SOURCES = Tle.cpp \
|
libsgp4_a_SOURCES = Tle.cpp \
|
||||||
OrbitalElements.cpp \
|
OrbitalElements.cpp \
|
||||||
Observer.cpp \
|
Observer.cpp \
|
||||||
Timespan.cpp \
|
|
||||||
Util.cpp \
|
Util.cpp \
|
||||||
Eci.cpp \
|
Eci.cpp \
|
||||||
Julian.cpp \
|
|
||||||
SGP4.cpp \
|
SGP4.cpp \
|
||||||
SolarPosition.cpp
|
TimeSpan.cpp \
|
||||||
|
DateTime.cpp
|
||||||
include_HEADERS = CoordGeodetic.h \
|
include_HEADERS = CoordGeodetic.h \
|
||||||
Eci.h \
|
Eci.h \
|
||||||
Julian.h \
|
|
||||||
OrbitalElements.h \
|
OrbitalElements.h \
|
||||||
SatelliteException.h \
|
SatelliteException.h \
|
||||||
Timespan.h \
|
|
||||||
TleException.h \
|
TleException.h \
|
||||||
Vector.h \
|
Vector.h \
|
||||||
CoordTopographic.h \
|
CoordTopographic.h \
|
||||||
Globals.h \
|
Globals.h \
|
||||||
Observer.h \
|
Observer.h \
|
||||||
SGP4.h \
|
SGP4.h \
|
||||||
SolarPosition.h \
|
|
||||||
Tle.h \
|
Tle.h \
|
||||||
Util.h
|
Util.h \
|
||||||
|
TimeSpan.h \
|
||||||
|
DateTime.h
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "Observer.h"
|
#include "Observer.h"
|
||||||
|
|
||||||
|
#include "CoordTopographic.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* calculate lookangle between the observer and the passed in Eci object
|
* calculate lookangle between the observer and the passed in Eci object
|
||||||
*/
|
*/
|
||||||
|
|
@ -9,23 +11,23 @@ CoordTopographic Observer::GetLookAngle(const Eci &eci)
|
||||||
* update the observers Eci to match the time of the Eci passed in
|
* update the observers Eci to match the time of the Eci passed in
|
||||||
* if necessary
|
* if necessary
|
||||||
*/
|
*/
|
||||||
UpdateObserversEci(eci.GetDate());
|
Update(eci.GetDateTime());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* calculate differences
|
* calculate differences
|
||||||
*/
|
*/
|
||||||
Vector range_rate = eci.GetVelocity().Subtract(observers_eci_.GetVelocity());
|
Vector range_rate = eci.GetVelocity() - m_eci.GetVelocity();
|
||||||
Vector range = eci.GetPosition().Subtract(observers_eci_.GetPosition());
|
Vector range = eci.GetPosition() - m_eci.GetPosition();
|
||||||
|
|
||||||
range.w = range.GetMagnitude();
|
range.w = range.GetMagnitude();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate Local Mean Sidereal Time for observers longitude
|
* Calculate Local Mean Sidereal Time for observers longitude
|
||||||
*/
|
*/
|
||||||
double theta = eci.GetDate().ToLocalMeanSiderealTime(geo_.longitude);
|
double theta = eci.GetDateTime().ToLocalMeanSiderealTime(m_geo.longitude);
|
||||||
|
|
||||||
double sin_lat = sin(geo_.latitude);
|
double sin_lat = sin(m_geo.latitude);
|
||||||
double cos_lat = cos(geo_.latitude);
|
double cos_lat = cos(m_geo.latitude);
|
||||||
double sin_theta = sin(theta);
|
double sin_theta = sin(theta);
|
||||||
double cos_theta = cos(theta);
|
double cos_theta = cos(theta);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,66 +2,87 @@
|
||||||
#define OBSERVER_H_
|
#define OBSERVER_H_
|
||||||
|
|
||||||
#include "CoordGeodetic.h"
|
#include "CoordGeodetic.h"
|
||||||
#include "CoordTopographic.h"
|
|
||||||
#include "Julian.h"
|
|
||||||
#include "Eci.h"
|
#include "Eci.h"
|
||||||
|
|
||||||
|
class DateTime;
|
||||||
|
class CoordTopographic;
|
||||||
|
|
||||||
class Observer
|
class Observer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Observer(double latitude, double longitude, double altitude)
|
/**
|
||||||
: geo_(latitude, longitude, altitude),
|
* Constructor
|
||||||
observers_eci_(Julian(), geo_)
|
* @param[in] latitude observers latitude in degrees
|
||||||
|
* @param[in] longitude observers longitude in degrees
|
||||||
|
* @param[in] altitude observers altitude in kilometers
|
||||||
|
*/
|
||||||
|
Observer(const double latitude,
|
||||||
|
const double longitude,
|
||||||
|
const double altitude)
|
||||||
|
: m_geo(latitude, longitude, altitude),
|
||||||
|
m_eci(DateTime(), m_geo)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Observer(const CoordGeodetic &g)
|
/**
|
||||||
: geo_(g), observers_eci_(Julian(), geo_)
|
* Constructor
|
||||||
|
* @param[in] geo the observers position
|
||||||
|
*/
|
||||||
|
Observer(const CoordGeodetic &geo)
|
||||||
|
: m_geo(geo),
|
||||||
|
m_eci(DateTime(), geo)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~Observer()
|
virtual ~Observer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLocation(const CoordGeodetic& g)
|
/**
|
||||||
|
* Set the observers location
|
||||||
|
* @param[in] geo the observers position
|
||||||
|
*/
|
||||||
|
void SetLocation(const CoordGeodetic& geo)
|
||||||
{
|
{
|
||||||
geo_ = g;
|
m_geo = geo;
|
||||||
observers_eci_ = Eci(observers_eci_.GetDate(), geo_);
|
m_eci.Update(m_eci.GetDateTime(), m_geo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the observers location
|
||||||
|
* @returns the observers position
|
||||||
|
*/
|
||||||
CoordGeodetic GetLocation() const
|
CoordGeodetic GetLocation() const
|
||||||
{
|
{
|
||||||
return geo_;
|
return m_geo;
|
||||||
}
|
|
||||||
|
|
||||||
Eci GetEciPosition(const Julian &date) const
|
|
||||||
{
|
|
||||||
return Eci(date, geo_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the look angle for the observers position to the object
|
||||||
|
* @param[in] eci the object to find the look angle to
|
||||||
|
* @returns the lookup angle
|
||||||
|
*/
|
||||||
CoordTopographic GetLookAngle(const Eci &eci);
|
CoordTopographic GetLookAngle(const Eci &eci);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateObserversEci(const Julian &date)
|
/**
|
||||||
{
|
* @param[in] dt the date to update the observers position for
|
||||||
/*
|
|
||||||
* if date has changed, update for new date
|
|
||||||
*/
|
*/
|
||||||
if (observers_eci_.GetDate() != date)
|
void Update(const DateTime &dt)
|
||||||
{
|
{
|
||||||
observers_eci_ = Eci(date, geo_);
|
if (m_eci != dt)
|
||||||
|
{
|
||||||
|
m_eci.Update(dt, m_geo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/** the observers position */
|
||||||
* the observers position
|
CoordGeodetic m_geo;
|
||||||
*/
|
/** the observers Eci for a particular time */
|
||||||
CoordGeodetic geo_;
|
Eci m_eci;
|
||||||
/*
|
|
||||||
* the observers eci for a particular time
|
|
||||||
*/
|
|
||||||
Eci observers_eci_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "OrbitalElements.h"
|
#include "OrbitalElements.h"
|
||||||
|
|
||||||
|
#include "Tle.h"
|
||||||
|
|
||||||
OrbitalElements::OrbitalElements(const Tle& tle)
|
OrbitalElements::OrbitalElements(const Tle& tle)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
#ifndef ORBITALELEMENTS_H_
|
#ifndef ORBITALELEMENTS_H_
|
||||||
#define ORBITALELEMENTS_H_
|
#define ORBITALELEMENTS_H_
|
||||||
|
|
||||||
#include "Tle.h"
|
#include "Util.h"
|
||||||
|
#include "DateTime.h"
|
||||||
|
|
||||||
|
class Tle;
|
||||||
|
|
||||||
class OrbitalElements
|
class OrbitalElements
|
||||||
{
|
{
|
||||||
|
|
@ -103,7 +106,7 @@ public:
|
||||||
/*
|
/*
|
||||||
* EPOCH
|
* EPOCH
|
||||||
*/
|
*/
|
||||||
Julian Epoch() const
|
DateTime Epoch() const
|
||||||
{
|
{
|
||||||
return epoch_;
|
return epoch_;
|
||||||
}
|
}
|
||||||
|
|
@ -121,8 +124,7 @@ private:
|
||||||
double recovered_mean_motion_;
|
double recovered_mean_motion_;
|
||||||
double perigee_;
|
double perigee_;
|
||||||
double period_;
|
double period_;
|
||||||
Julian epoch_;
|
DateTime epoch_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
680
libsgp4/SGP4.cpp
680
libsgp4/SGP4.cpp
File diff suppressed because it is too large
Load Diff
111
libsgp4/SGP4.h
111
libsgp4/SGP4.h
|
|
@ -22,17 +22,10 @@ public:
|
||||||
|
|
||||||
void SetTle(const Tle& tle);
|
void SetTle(const Tle& tle);
|
||||||
Eci FindPosition(double tsince) const;
|
Eci FindPosition(double tsince) const;
|
||||||
Eci FindPosition(const Julian& date) const;
|
Eci FindPosition(const DateTime& date) const;
|
||||||
|
|
||||||
struct CommonConstants
|
struct CommonConstants
|
||||||
{
|
{
|
||||||
CommonConstants()
|
|
||||||
: cosio(0.0), sinio(0.0), eta(0.0), t2cof(0.0), a3ovk2(0.0),
|
|
||||||
x1mth2(0.0), x3thm1(0.0), x7thm1(0.0), aycof(0.0), xlcof(0.0),
|
|
||||||
xnodcf(0.0), c1(0.0), c4(0.0), omgdot(0.0), xnodot(0.0), xmdot(0.0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
double cosio;
|
double cosio;
|
||||||
double sinio;
|
double sinio;
|
||||||
double eta;
|
double eta;
|
||||||
|
|
@ -53,12 +46,6 @@ public:
|
||||||
|
|
||||||
struct NearSpaceConstants
|
struct NearSpaceConstants
|
||||||
{
|
{
|
||||||
NearSpaceConstants()
|
|
||||||
: c5(0.0), omgcof(0.0), xmcof(0.0), delmo(0.0), sinmo(0.0), d2(0.0),
|
|
||||||
d3(0.0), d4(0.0), t3cof(0.0), t4cof(0.0), t5cof(0.0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
double c5;
|
double c5;
|
||||||
double omgcof;
|
double omgcof;
|
||||||
double xmcof;
|
double xmcof;
|
||||||
|
|
@ -74,18 +61,6 @@ public:
|
||||||
|
|
||||||
struct DeepSpaceConstants
|
struct DeepSpaceConstants
|
||||||
{
|
{
|
||||||
DeepSpaceConstants()
|
|
||||||
: gsto(0.0), zmol(0.0), zmos(0.0), resonance_flag(false),
|
|
||||||
synchronous_flag(false), sse(0.0), ssi(0.0), ssl(0.0), ssg(0.0),
|
|
||||||
ssh(0.0), se2(0.0), si2(0.0), sl2(0.0), sgh2(0.0), sh2(0.0), se3(0.0),
|
|
||||||
si3(0.0), sl3(0.0), sgh3(0.0), sh3(0.0), sl4(0.0), sgh4(0.0), ee2(0.0),
|
|
||||||
e3(0.0), xi2(0.0), xi3(0.0), xl2(0.0), xl3(0.0), xl4(0.0), xgh2(0.0),
|
|
||||||
xgh3(0.0), xgh4(0.0), xh2(0.0), xh3(0.0), d2201(0.0), d2211(0.0),
|
|
||||||
d3210(0.0), d3222(0.0), d4410(0.0), d4422(0.0), d5220(0.0), d5232(0.0),
|
|
||||||
d5421(0.0), d5433(0.0), del1(0.0), del2(0.0), del3(0.0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
double gsto;
|
double gsto;
|
||||||
double zmol;
|
double zmol;
|
||||||
double zmos;
|
double zmos;
|
||||||
|
|
@ -156,10 +131,6 @@ public:
|
||||||
|
|
||||||
struct IntegratorValues
|
struct IntegratorValues
|
||||||
{
|
{
|
||||||
IntegratorValues() : xndot(0.0), xnddt(0.0), xldot(0.0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
double xndot;
|
double xndot;
|
||||||
double xnddt;
|
double xnddt;
|
||||||
double xldot;
|
double xldot;
|
||||||
|
|
@ -167,10 +138,6 @@ public:
|
||||||
|
|
||||||
struct IntegratorConstants
|
struct IntegratorConstants
|
||||||
{
|
{
|
||||||
IntegratorConstants() : xfact(0.0), xlamo(0.0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* integrator constants
|
* integrator constants
|
||||||
*/
|
*/
|
||||||
|
|
@ -185,10 +152,6 @@ public:
|
||||||
|
|
||||||
struct IntegratorParams
|
struct IntegratorParams
|
||||||
{
|
{
|
||||||
IntegratorParams() : xli(0.0), xni(0.0), atime(0.0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* integrator values
|
* integrator values
|
||||||
*/
|
*/
|
||||||
|
|
@ -203,25 +166,59 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Initialise();
|
void Initialise();
|
||||||
void DeepSpaceInitialise(const double& eosq, const double& sinio, const double& cosio, const double& betao,
|
Eci FindPositionSDP4(const double tsince) const;
|
||||||
const double& theta2, const double& betao2,
|
Eci FindPositionSGP4(double tsince) const;
|
||||||
const double& xmdot, const double& omgdot, const double& xnodot);
|
Eci CalculateFinalPositionVelocity(
|
||||||
void DeepSpaceCalculateLunarSolarTerms(const double t, double* pe, double* pinc,
|
const double tsince,
|
||||||
double* pl, double* pgh, double* ph) const;
|
const double e,
|
||||||
void DeepSpacePeriodics(const double& t, double* em, double* xinc,
|
const double a,
|
||||||
double* omgasm, double* xnodes, double* xll) const;
|
const double omega,
|
||||||
void DeepSpaceSecular(const double& t, double* xll, double* omgasm,
|
const double xl,
|
||||||
double* xnodes, double* em, double* xinc, double* xn) const;
|
const double xnode,
|
||||||
Eci FindPosition(const Julian& dt, double tsince) const;
|
const double xincl,
|
||||||
Eci FindPositionSDP4(const Julian& dt, double tsince) const;
|
const double xlcof,
|
||||||
Eci FindPositionSGP4(const Julian& dt, double tsince) const;
|
const double aycof,
|
||||||
Eci CalculateFinalPositionVelocity(const Julian& dt, const double& e,
|
const double x3thm1,
|
||||||
const double& a, const double& omega, const double& xl, const double& xnode,
|
const double x1mth2,
|
||||||
const double& xincl, const double& xlcof, const double& aycof,
|
const double x7thm1,
|
||||||
const double& x3thm1, const double& x1mth2, const double& x7thm1,
|
const double cosio,
|
||||||
const double& cosio, const double& sinio) const;
|
const double sinio) const;
|
||||||
void DeepSpaceCalcDotTerms(struct IntegratorValues *values) const;
|
void DeepSpaceInitialise(
|
||||||
void DeepSpaceIntegrator(const double delt, const double step2,
|
const double eosq,
|
||||||
|
const double sinio,
|
||||||
|
const double cosio,
|
||||||
|
const double betao,
|
||||||
|
const double theta2,
|
||||||
|
const double betao2,
|
||||||
|
const double xmdot,
|
||||||
|
const double omgdot,
|
||||||
|
const double xnodot);
|
||||||
|
void DeepSpaceCalculateLunarSolarTerms(
|
||||||
|
const double tsince,
|
||||||
|
double& pe,
|
||||||
|
double& pinc,
|
||||||
|
double& pl,
|
||||||
|
double& pgh,
|
||||||
|
double& ph) const;
|
||||||
|
void DeepSpacePeriodics(
|
||||||
|
const double tsince,
|
||||||
|
double& em,
|
||||||
|
double& xinc,
|
||||||
|
double& omgasm,
|
||||||
|
double& xnodes,
|
||||||
|
double& xll) const;
|
||||||
|
void DeepSpaceSecular(
|
||||||
|
const double tsince,
|
||||||
|
double& xll,
|
||||||
|
double& omgasm,
|
||||||
|
double& xnodes,
|
||||||
|
double& em,
|
||||||
|
double& xinc,
|
||||||
|
double& xn) const;
|
||||||
|
void DeepSpaceCalcDotTerms(struct IntegratorValues& values) const;
|
||||||
|
void DeepSpaceIntegrator(
|
||||||
|
const double delt,
|
||||||
|
const double step2,
|
||||||
const struct IntegratorValues& values) const;
|
const struct IntegratorValues& values) const;
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
#define SATELLITEEXCEPTION_H_
|
#define SATELLITEEXCEPTION_H_
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
class SatelliteException : public std::exception
|
class SatelliteException : public std::exception
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
Eci SolarPosition::FindPosition(const Julian& j)
|
Eci SolarPosition::FindPosition(const DateTime& dt)
|
||||||
{
|
{
|
||||||
const double mjd = j.FromJan1_12h_1900();
|
const double mjd = j.FromJan1_12h_1900();
|
||||||
const double year = 1900 + mjd / 365.25;
|
const double year = 1900 + mjd / 365.25;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef SOLARPOSITION_H_
|
#ifndef SOLARPOSITION_H_
|
||||||
#define SOLARPOSITION_H_
|
#define SOLARPOSITION_H_
|
||||||
|
|
||||||
#include "Julian.h"
|
#include "DateTime.h"
|
||||||
#include "Eci.h"
|
#include "Eci.h"
|
||||||
|
|
||||||
class SolarPosition
|
class SolarPosition
|
||||||
|
|
@ -15,7 +15,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Eci FindPosition(const Julian& j);
|
Eci FindPosition(const DateTime& dt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double Delta_ET(double year) const;
|
double Delta_ET(double year) const;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "TimeSpan.h"
|
||||||
|
|
@ -0,0 +1,194 @@
|
||||||
|
#ifndef TIMESPAN_H_
|
||||||
|
#define TIMESPAN_H_
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
static const long long TicksPerDay = 86400000000LL;
|
||||||
|
static const long long TicksPerHour = 3600000000LL;
|
||||||
|
static const long long TicksPerMinute = 60000000LL;
|
||||||
|
static const long long TicksPerSecond = 1000000LL;
|
||||||
|
static const long long TicksPerMillisecond = 1000LL;
|
||||||
|
static const long long TicksPerMicrosecond = 1LL;
|
||||||
|
|
||||||
|
static const long long UnixEpoch = 62135596800000000LL;
|
||||||
|
|
||||||
|
static const long long MaxValueTicks = 315537897599999999LL;
|
||||||
|
|
||||||
|
// 1582-Oct-15
|
||||||
|
static const long long GregorianStart = 49916304000000000LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimeSpan
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TimeSpan(long long ticks)
|
||||||
|
: m_ticks(ticks)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeSpan(int hours, int minutes, int seconds)
|
||||||
|
{
|
||||||
|
CalculateTicks(0, hours, minutes, seconds, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeSpan(int days, int hours, int minutes, int seconds)
|
||||||
|
{
|
||||||
|
CalculateTicks(days, hours, minutes, seconds, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeSpan(int days, int hours, int minutes, int seconds, int microseconds)
|
||||||
|
{
|
||||||
|
CalculateTicks(days, hours, minutes, seconds, microseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeSpan Add(const TimeSpan& ts) const
|
||||||
|
{
|
||||||
|
return TimeSpan(m_ticks + ts.m_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeSpan Subtract(const TimeSpan& ts) const
|
||||||
|
{
|
||||||
|
return TimeSpan(m_ticks - ts.m_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compare(const TimeSpan& ts) const
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (m_ticks < ts.m_ticks)
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
if (m_ticks < ts.m_ticks)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Equals(const TimeSpan& ts) const
|
||||||
|
{
|
||||||
|
return m_ticks == ts.m_ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Days()
|
||||||
|
{
|
||||||
|
return m_ticks / TicksPerDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Hours()
|
||||||
|
{
|
||||||
|
return (m_ticks % TicksPerDay / TicksPerHour);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Minutes() const
|
||||||
|
{
|
||||||
|
return (m_ticks % TicksPerHour / TicksPerMinute);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Seconds() const
|
||||||
|
{
|
||||||
|
return (m_ticks % TicksPerMinute / TicksPerSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Milliseconds() const
|
||||||
|
{
|
||||||
|
return (m_ticks % TicksPerSecond / TicksPerMillisecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Microseconds() const
|
||||||
|
{
|
||||||
|
return (m_ticks % TicksPerSecond / TicksPerMicrosecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
long long Ticks() const
|
||||||
|
{
|
||||||
|
return m_ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
double TotalDays() const
|
||||||
|
{
|
||||||
|
return m_ticks / static_cast<double>(TicksPerDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TotalHours() const
|
||||||
|
{
|
||||||
|
return m_ticks / static_cast<double>(TicksPerHour);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TotalMinutes() const
|
||||||
|
{
|
||||||
|
return m_ticks / static_cast<double>(TicksPerMinute);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TotalSeconds() const
|
||||||
|
{
|
||||||
|
return m_ticks / static_cast<double>(TicksPerSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TotalMilliseconds() const
|
||||||
|
{
|
||||||
|
return m_ticks / static_cast<double>(TicksPerMillisecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TotalMicroseconds() const
|
||||||
|
{
|
||||||
|
return m_ticks / static_cast<double>(TicksPerMicrosecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
long long m_ticks;
|
||||||
|
|
||||||
|
void CalculateTicks(int days,
|
||||||
|
int hours,
|
||||||
|
int minutes,
|
||||||
|
int seconds,
|
||||||
|
int microseconds)
|
||||||
|
{
|
||||||
|
m_ticks = days * TicksPerDay +
|
||||||
|
(hours * 3600LL + minutes * 60LL + seconds) * TicksPerSecond +
|
||||||
|
microseconds * TicksPerMicrosecond;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline TimeSpan operator+(const TimeSpan& ts1, const TimeSpan& ts2)
|
||||||
|
{
|
||||||
|
return ts1.Add(ts2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TimeSpan operator-(const TimeSpan& ts1, const TimeSpan& ts2)
|
||||||
|
{
|
||||||
|
return ts1.Subtract(ts2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const TimeSpan& ts1, TimeSpan& ts2)
|
||||||
|
{
|
||||||
|
return ts1.Equals(ts2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator>(const TimeSpan& ts1, const TimeSpan& ts2)
|
||||||
|
{
|
||||||
|
return (ts1.Compare(ts2) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator>=(const TimeSpan& ts1, const TimeSpan& ts2)
|
||||||
|
{
|
||||||
|
return (ts1.Compare(ts2) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const TimeSpan& ts1, const TimeSpan& ts2)
|
||||||
|
{
|
||||||
|
return !ts1.Equals(ts2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<(const TimeSpan& ts1, const TimeSpan& ts2)
|
||||||
|
{
|
||||||
|
return (ts1.Compare(ts2) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<=(const TimeSpan& ts1, const TimeSpan& ts2)
|
||||||
|
{
|
||||||
|
return (ts1.Compare(ts2) <= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,175 +0,0 @@
|
||||||
#include "Timespan.h"
|
|
||||||
|
|
||||||
#include "Globals.h"
|
|
||||||
|
|
||||||
Timespan::Timespan()
|
|
||||||
: time_span_(0.0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan::Timespan(const unsigned int days, const unsigned int hours,
|
|
||||||
const unsigned int minutes, const double seconds) {
|
|
||||||
|
|
||||||
SetValue(days, hours, minutes, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan::Timespan(const double b) {
|
|
||||||
|
|
||||||
time_span_ = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan::Timespan(const Timespan& b) {
|
|
||||||
time_span_ = b.time_span_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan::~Timespan(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timespan::SetValue(const unsigned int days, const unsigned int hours,
|
|
||||||
const unsigned int minutes, const double seconds) {
|
|
||||||
|
|
||||||
time_span_ = static_cast<double> (days);
|
|
||||||
AddHours(hours);
|
|
||||||
AddMinutes(minutes);
|
|
||||||
AddSeconds(seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timespan::AddDays(const unsigned int days) {
|
|
||||||
time_span_ += static_cast<double> (days);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timespan::AddHours(const unsigned int hours) {
|
|
||||||
time_span_ += (static_cast<double> (hours) / kHOURS_PER_DAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timespan::AddMinutes(const unsigned int minutes) {
|
|
||||||
time_span_ += (static_cast<double> (minutes) / kMINUTES_PER_DAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timespan::AddSeconds(const double seconds) {
|
|
||||||
time_span_ += (seconds / kSECONDS_PER_DAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
double Timespan::GetTotalDays() const {
|
|
||||||
return time_span_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Timespan::GetTotalHours() const {
|
|
||||||
return time_span_ * kHOURS_PER_DAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Timespan::GetTotalMinutes() const {
|
|
||||||
return time_span_ * kMINUTES_PER_DAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Timespan::GetTotalSeconds() const {
|
|
||||||
return time_span_ * kSECONDS_PER_DAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan& Timespan::operator =(const Timespan& b) {
|
|
||||||
|
|
||||||
if (this != &b) {
|
|
||||||
time_span_ = b.time_span_;
|
|
||||||
}
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan Timespan::operator +(const Timespan& b) const {
|
|
||||||
|
|
||||||
return Timespan(*this) += b;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan Timespan::operator -(const Timespan& b) const {
|
|
||||||
|
|
||||||
return Timespan(*this) -= b;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan Timespan::operator/(const double b) const {
|
|
||||||
|
|
||||||
return Timespan(*this) /= b;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan Timespan::operator*(const double b) const {
|
|
||||||
|
|
||||||
return Timespan(*this) *= b;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan & Timespan::operator+=(const Timespan& b) {
|
|
||||||
|
|
||||||
time_span_ += b.time_span_;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan & Timespan::operator-=(const Timespan& b) {
|
|
||||||
|
|
||||||
time_span_ -= b.time_span_;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan & Timespan::operator/=(const double b) {
|
|
||||||
|
|
||||||
time_span_ /= b;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timespan & Timespan::operator*=(const double b) {
|
|
||||||
|
|
||||||
time_span_ *= b;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Timespan::operator ==(const Timespan& b) const {
|
|
||||||
|
|
||||||
if (time_span_ == b.time_span_)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Timespan::operator !=(const Timespan& b) const {
|
|
||||||
|
|
||||||
return !(*this == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Timespan::operator>(const Timespan& b) const {
|
|
||||||
|
|
||||||
if (time_span_ > b.time_span_)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Timespan::operator<(const Timespan& b) const {
|
|
||||||
|
|
||||||
if (time_span_ < b.time_span_)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Timespan::operator >=(const Timespan& b) const {
|
|
||||||
|
|
||||||
if (time_span_ >= b.time_span_)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Timespan::operator <=(const Timespan & b) const {
|
|
||||||
|
|
||||||
if (time_span_ <= b.time_span_)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double& operator +=(double& a, const Timespan& b) {
|
|
||||||
|
|
||||||
a += b.time_span_;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
double& operator -=(double& a, const Timespan& b) {
|
|
||||||
|
|
||||||
a -= b.time_span_;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
#ifndef TIMESPAN_H_
|
|
||||||
#define TIMESPAN_H_
|
|
||||||
|
|
||||||
class Timespan {
|
|
||||||
public:
|
|
||||||
Timespan();
|
|
||||||
Timespan(const unsigned int days, const unsigned int hours,
|
|
||||||
const unsigned int minutes, const double seconds);
|
|
||||||
Timespan(const double b);
|
|
||||||
Timespan(const Timespan& b);
|
|
||||||
virtual ~Timespan(void);
|
|
||||||
|
|
||||||
void SetValue(const unsigned int days, const unsigned int hours,
|
|
||||||
const unsigned int minutes, const double seconds);
|
|
||||||
|
|
||||||
void AddDays(const unsigned int days);
|
|
||||||
void AddHours(const unsigned int hours);
|
|
||||||
void AddMinutes(const unsigned int minutes);
|
|
||||||
void AddSeconds(const double seconds);
|
|
||||||
|
|
||||||
double GetTotalDays() const;
|
|
||||||
double GetTotalHours() const;
|
|
||||||
double GetTotalMinutes() const;
|
|
||||||
double GetTotalSeconds() const;
|
|
||||||
|
|
||||||
// assignment
|
|
||||||
Timespan & operator=(const Timespan& b);
|
|
||||||
// arithmetic
|
|
||||||
Timespan operator+(const Timespan& b) const;
|
|
||||||
Timespan operator-(const Timespan& b) const;
|
|
||||||
Timespan operator/(const double b) const;
|
|
||||||
Timespan operator*(const double b) const;
|
|
||||||
// compound arithmetic
|
|
||||||
Timespan & operator+=(const Timespan& b);
|
|
||||||
Timespan & operator-=(const Timespan& b);
|
|
||||||
Timespan & operator/=(const double b);
|
|
||||||
Timespan & operator*=(const double b);
|
|
||||||
// comparison
|
|
||||||
bool operator==(const Timespan& b) const;
|
|
||||||
bool operator!=(const Timespan& b) const;
|
|
||||||
bool operator>(const Timespan& b) const;
|
|
||||||
bool operator<(const Timespan& b) const;
|
|
||||||
bool operator>=(const Timespan& b) const;
|
|
||||||
bool operator<=(const Timespan& b) const;
|
|
||||||
|
|
||||||
friend double& operator +=(double& a, const Timespan& b);
|
|
||||||
friend double& operator -=(double& a, const Timespan& b);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*
|
|
||||||
* stores value in minutes
|
|
||||||
*/
|
|
||||||
double time_span_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
624
libsgp4/Tle.cpp
624
libsgp4/Tle.cpp
|
|
@ -1,14 +1,9 @@
|
||||||
#include "Tle.h"
|
#include "Tle.h"
|
||||||
|
|
||||||
#include "Util.h"
|
|
||||||
|
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* line 1
|
|
||||||
*/
|
|
||||||
static const unsigned int TLE1_COL_NORADNUM = 2;
|
static const unsigned int TLE1_COL_NORADNUM = 2;
|
||||||
static const unsigned int TLE1_LEN_NORADNUM = 5;
|
static const unsigned int TLE1_LEN_NORADNUM = 5;
|
||||||
static const unsigned int TLE1_COL_INTLDESC_A = 9;
|
static const unsigned int TLE1_COL_INTLDESC_A = 9;
|
||||||
|
|
@ -21,10 +16,10 @@ namespace
|
||||||
static const unsigned int TLE1_LEN_EPOCH_A = 2;
|
static const unsigned int TLE1_LEN_EPOCH_A = 2;
|
||||||
static const unsigned int TLE1_COL_EPOCH_B = 20;
|
static const unsigned int TLE1_COL_EPOCH_B = 20;
|
||||||
static const unsigned int TLE1_LEN_EPOCH_B = 12;
|
static const unsigned int TLE1_LEN_EPOCH_B = 12;
|
||||||
static const unsigned int TLE1_COL_MEANMOTIONDT = 33;
|
static const unsigned int TLE1_COL_MEANMOTIONDT2 = 33;
|
||||||
static const unsigned int TLE1_LEN_MEANMOTIONDT = 10;
|
static const unsigned int TLE1_LEN_MEANMOTIONDT2 = 10;
|
||||||
static const unsigned int TLE1_COL_MEANMOTIONDT2 = 44;
|
static const unsigned int TLE1_COL_MEANMOTIONDDT6 = 44;
|
||||||
static const unsigned int TLE1_LEN_MEANMOTIONDT2 = 8;
|
static const unsigned int TLE1_LEN_MEANMOTIONDDT6 = 8;
|
||||||
static const unsigned int TLE1_COL_BSTAR = 53;
|
static const unsigned int TLE1_COL_BSTAR = 53;
|
||||||
static const unsigned int TLE1_LEN_BSTAR = 8;
|
static const unsigned int TLE1_LEN_BSTAR = 8;
|
||||||
static const unsigned int TLE1_COL_EPHEMTYPE = 62;
|
static const unsigned int TLE1_COL_EPHEMTYPE = 62;
|
||||||
|
|
@ -32,9 +27,6 @@ namespace
|
||||||
static const unsigned int TLE1_COL_ELNUM = 64;
|
static const unsigned int TLE1_COL_ELNUM = 64;
|
||||||
static const unsigned int TLE1_LEN_ELNUM = 4;
|
static const unsigned int TLE1_LEN_ELNUM = 4;
|
||||||
|
|
||||||
/*
|
|
||||||
* line 2
|
|
||||||
*/
|
|
||||||
static const unsigned int TLE2_COL_NORADNUM = 2;
|
static const unsigned int TLE2_COL_NORADNUM = 2;
|
||||||
static const unsigned int TLE2_LEN_NORADNUM = 5;
|
static const unsigned int TLE2_LEN_NORADNUM = 5;
|
||||||
static const unsigned int TLE2_COL_INCLINATION = 8;
|
static const unsigned int TLE2_COL_INCLINATION = 8;
|
||||||
|
|
@ -51,421 +43,309 @@ namespace
|
||||||
static const unsigned int TLE2_LEN_MEANMOTION = 11;
|
static const unsigned int TLE2_LEN_MEANMOTION = 11;
|
||||||
static const unsigned int TLE2_COL_REVATEPOCH = 63;
|
static const unsigned int TLE2_COL_REVATEPOCH = 63;
|
||||||
static const unsigned int TLE2_LEN_REVATEPOCH = 5;
|
static const unsigned int TLE2_LEN_REVATEPOCH = 5;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tle::Tle(const Tle& tle)
|
/**
|
||||||
{
|
* Initialise the tle object.
|
||||||
name_ = tle.name_;
|
* @exception TleException
|
||||||
line_one_ = tle.line_one_;
|
|
||||||
line_two_ = tle.line_two_;
|
|
||||||
|
|
||||||
norad_number_ = tle.norad_number_;
|
|
||||||
international_designator_ = tle.international_designator_;
|
|
||||||
epoch_ = tle.epoch_;
|
|
||||||
mean_motion_dot_ = tle.mean_motion_dot_;
|
|
||||||
mean_motion_dot2_ = tle.mean_motion_dot2_;
|
|
||||||
bstar_ = tle.bstar_;
|
|
||||||
inclination_ = tle.inclination_;
|
|
||||||
right_ascending_node_ = tle.right_ascending_node_;
|
|
||||||
eccentricity_ = tle.eccentricity_;
|
|
||||||
argument_perigee_ = tle.argument_perigee_;
|
|
||||||
mean_anomaly_ = tle.mean_anomaly_;
|
|
||||||
mean_motion_ = tle.mean_motion_;
|
|
||||||
orbit_number_ = tle.orbit_number_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* convert a tle raw string into an exponent string
|
|
||||||
*/
|
|
||||||
std::string Tle::ExpToDecimal(const std::string& str)
|
|
||||||
{
|
|
||||||
static const int START_SIGN = 0;
|
|
||||||
static const int LENGTH_SIGN = 1;
|
|
||||||
static const int START_MANTISSA = 1;
|
|
||||||
static const int LENGTH_MANTISSA = 5;
|
|
||||||
static const int START_EXP = 6;
|
|
||||||
static const int LENGTH_EXP = 2;
|
|
||||||
|
|
||||||
if ((LENGTH_SIGN + LENGTH_MANTISSA + LENGTH_EXP) != str.length())
|
|
||||||
{
|
|
||||||
throw TleException("Invalid string length for exponential conversion.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string value = str.substr(START_SIGN, LENGTH_SIGN);
|
|
||||||
value += ".";
|
|
||||||
value += str.substr(START_MANTISSA, LENGTH_MANTISSA);
|
|
||||||
value += "e";
|
|
||||||
value += str.substr(START_EXP, LENGTH_EXP);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* extract all variables
|
|
||||||
*/
|
*/
|
||||||
void Tle::Initialize()
|
void Tle::Initialize()
|
||||||
{
|
{
|
||||||
std::string temp;
|
if (!IsValidLineLength(line_one_))
|
||||||
|
|
||||||
/*
|
|
||||||
* trim whitespace
|
|
||||||
*/
|
|
||||||
Util::TrimLeft(name_);
|
|
||||||
Util::TrimRight(name_);
|
|
||||||
Util::TrimLeft(line_one_);
|
|
||||||
Util::TrimRight(line_one_);
|
|
||||||
Util::TrimLeft(line_two_);
|
|
||||||
Util::TrimRight(line_two_);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check the two lines are valid
|
|
||||||
*/
|
|
||||||
IsValidPair(line_one_, line_two_);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* line 1
|
|
||||||
*/
|
|
||||||
|
|
||||||
temp = ExtractNoradNumber(line_one_, 1);
|
|
||||||
if (!Util::FromString<unsigned int>(temp, norad_number_))
|
|
||||||
{
|
{
|
||||||
throw TleException("Conversion failed");
|
throw TleException("Invalid length for line one");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (!IsValidLineLength(line_two_))
|
||||||
* if blank use norad number for name
|
{
|
||||||
*/
|
throw TleException("Invalid length for line two");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_one_[0] != '1')
|
||||||
|
{
|
||||||
|
throw TleException("Invalid line beginning for line one");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_two_[0] != '2')
|
||||||
|
{
|
||||||
|
throw TleException("Invalid line beginning for line two");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int sat_number_1;
|
||||||
|
unsigned int sat_number_2;
|
||||||
|
|
||||||
|
ExtractInteger(line_one_.substr(TLE1_COL_NORADNUM,
|
||||||
|
TLE1_LEN_NORADNUM), sat_number_1);
|
||||||
|
ExtractInteger(line_two_.substr(TLE2_COL_NORADNUM,
|
||||||
|
TLE2_LEN_NORADNUM), sat_number_2);
|
||||||
|
|
||||||
|
if (sat_number_1 != sat_number_2)
|
||||||
|
{
|
||||||
|
throw TleException("Satellite numbers do not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
norad_number_ = sat_number_1;
|
||||||
|
|
||||||
if (name_.empty())
|
if (name_.empty())
|
||||||
{
|
{
|
||||||
name_ = temp;
|
name_ = line_one_.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
international_designator_ = line_one_.substr(TLE1_COL_INTLDESC_A,
|
int_designator_ = line_one_.substr(TLE1_COL_INTLDESC_A,
|
||||||
TLE1_LEN_INTLDESC_A + TLE1_LEN_INTLDESC_B + TLE1_LEN_INTLDESC_C);
|
TLE1_LEN_INTLDESC_A + TLE1_LEN_INTLDESC_B + TLE1_LEN_INTLDESC_C);
|
||||||
|
|
||||||
int year;
|
unsigned int year = 0;
|
||||||
double day;
|
double day = 0.0;
|
||||||
if (!Util::FromString<int>(line_one_.substr(TLE1_COL_EPOCH_A,
|
|
||||||
TLE1_LEN_EPOCH_A), year))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
if (!Util::FromString<double>(line_one_.substr(TLE1_COL_EPOCH_B,
|
|
||||||
TLE1_LEN_EPOCH_B), day))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* generate julian date for epoch
|
|
||||||
*/
|
|
||||||
if (year < 57)
|
|
||||||
year += 2000;
|
|
||||||
else
|
|
||||||
year += 1900;
|
|
||||||
epoch_ = Julian(year, day);
|
|
||||||
|
|
||||||
if (line_one_[TLE1_COL_MEANMOTIONDT] == '-') {
|
ExtractInteger(line_one_.substr(TLE1_COL_EPOCH_A,
|
||||||
temp = "-0";
|
TLE1_LEN_EPOCH_A), year);
|
||||||
} else
|
ExtractDouble(line_one_.substr(TLE1_COL_EPOCH_B,
|
||||||
temp = "0";
|
TLE1_LEN_EPOCH_B), 4, day);
|
||||||
temp += line_one_.substr(TLE1_COL_MEANMOTIONDT + 1, TLE1_LEN_MEANMOTIONDT);
|
ExtractDouble(line_one_.substr(TLE1_COL_MEANMOTIONDT2,
|
||||||
if (!Util::FromString<double>(temp, mean_motion_dot_))
|
TLE1_LEN_MEANMOTIONDT2), 2, mean_motion_dt2_);
|
||||||
{
|
ExtractExponential(line_one_.substr(TLE1_COL_MEANMOTIONDDT6,
|
||||||
throw TleException("Conversion failed");
|
TLE1_LEN_MEANMOTIONDDT6), mean_motion_ddt6_);
|
||||||
}
|
ExtractExponential(line_one_.substr(TLE1_COL_BSTAR,
|
||||||
|
TLE1_LEN_BSTAR), bstar_);
|
||||||
temp = ExpToDecimal(line_one_.substr(TLE1_COL_MEANMOTIONDT2,
|
|
||||||
TLE1_LEN_MEANMOTIONDT2));
|
|
||||||
if (!Util::FromString<double>(temp, mean_motion_dot2_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = ExpToDecimal(line_one_.substr(TLE1_COL_BSTAR,
|
|
||||||
TLE1_LEN_BSTAR).c_str());
|
|
||||||
if (!Util::FromString<double>(temp, bstar_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* line 2
|
* line 2
|
||||||
*/
|
*/
|
||||||
|
ExtractDouble(line_two_.substr(TLE2_COL_INCLINATION,
|
||||||
|
TLE2_LEN_INCLINATION), 4, inclination_);
|
||||||
|
ExtractDouble(line_two_.substr(TLE2_COL_RAASCENDNODE,
|
||||||
|
TLE2_LEN_RAASCENDNODE), 4, right_ascending_node_);
|
||||||
|
ExtractDouble(line_two_.substr(TLE2_COL_ECCENTRICITY,
|
||||||
|
TLE2_LEN_ECCENTRICITY), -1, eccentricity_);
|
||||||
|
ExtractDouble(line_two_.substr(TLE2_COL_ARGPERIGEE,
|
||||||
|
TLE2_LEN_ARGPERIGEE), 4, argument_perigee_);
|
||||||
|
ExtractDouble(line_two_.substr(TLE2_COL_MEANANOMALY,
|
||||||
|
TLE2_LEN_MEANANOMALY), 4, mean_anomaly_);
|
||||||
|
ExtractDouble(line_two_.substr(TLE2_COL_MEANMOTION,
|
||||||
|
TLE2_LEN_MEANMOTION), 3, mean_motion_);
|
||||||
|
ExtractInteger(line_two_.substr(TLE2_COL_REVATEPOCH,
|
||||||
|
TLE2_LEN_REVATEPOCH), orbit_number_);
|
||||||
|
|
||||||
temp = line_two_.substr(TLE2_COL_INCLINATION, TLE2_LEN_INCLINATION);
|
if (year < 57)
|
||||||
Util::TrimLeft(temp);
|
year += 2000;
|
||||||
if (!Util::FromString<double>(temp, inclination_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = line_two_.substr(TLE2_COL_RAASCENDNODE, TLE2_LEN_RAASCENDNODE);
|
|
||||||
Util::TrimLeft(temp);
|
|
||||||
if (!Util::FromString<double>(temp, right_ascending_node_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = "0.";
|
|
||||||
temp += line_two_.substr(TLE2_COL_ECCENTRICITY, TLE2_LEN_ECCENTRICITY);
|
|
||||||
if (!Util::FromString<double>(temp, eccentricity_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = line_two_.substr(TLE2_COL_ARGPERIGEE, TLE2_LEN_ARGPERIGEE);
|
|
||||||
Util::TrimLeft(temp);
|
|
||||||
if (!Util::FromString<double>(temp, argument_perigee_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = line_two_.substr(TLE2_COL_MEANANOMALY, TLE2_LEN_MEANANOMALY);
|
|
||||||
Util::TrimLeft(temp);
|
|
||||||
if (!Util::FromString<double>(temp, mean_anomaly_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = line_two_.substr(TLE2_COL_MEANMOTION, TLE2_LEN_MEANMOTION);
|
|
||||||
Util::TrimLeft(temp);
|
|
||||||
if (!Util::FromString<double>(temp, mean_motion_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = line_two_.substr(TLE2_COL_REVATEPOCH, TLE2_LEN_REVATEPOCH);
|
|
||||||
Util::TrimLeft(temp);
|
|
||||||
if (!Util::FromString<unsigned int>(temp, orbit_number_))
|
|
||||||
{
|
|
||||||
throw TleException("Conversion failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check the two lines have matching norad numbers
|
|
||||||
* and that the lines themselves are equal
|
|
||||||
*/
|
|
||||||
void Tle::IsValidPair(const std::string& line1, const std::string& line2)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* validate each line
|
|
||||||
*/
|
|
||||||
IsValidLine(line1, 1);
|
|
||||||
IsValidLine(line2, 2);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* extract norad numbers
|
|
||||||
*/
|
|
||||||
std::string norad_1 = ExtractNoradNumber(line1, 1);
|
|
||||||
std::string norad_2 = ExtractNoradNumber(line2, 2);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* make sure they match
|
|
||||||
*/
|
|
||||||
if (norad_1.compare(norad_2) != 0)
|
|
||||||
{
|
|
||||||
throw TleException("Norad numbers do not match.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* validate a line
|
|
||||||
*/
|
|
||||||
void Tle::IsValidLine(const std::string& str, int line_number)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* validation patterns
|
|
||||||
*/
|
|
||||||
static const std::string line1_pattern = "1 NNNNNC NNNNNXXX NNNNN.NNNNNNNN +.NNNNNNNN +NNNNN-N +NNNNN-N N NNNNN";
|
|
||||||
static const std::string line2_pattern = "2 NNNNN NNN.NNNN NNN.NNNN NNNNNNN NNN.NNNN NNN.NNNN NN.NNNNNNNNNNNNNN";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* validate line against the pattern
|
|
||||||
*/
|
|
||||||
if (1 == line_number)
|
|
||||||
{
|
|
||||||
ValidateLine(str, line1_pattern);
|
|
||||||
}
|
|
||||||
else if (2 == line_number)
|
|
||||||
{
|
|
||||||
ValidateLine(str, line2_pattern);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
year += 1900;
|
||||||
throw TleException("Invalid line number to check.");
|
epoch_ = DateTime(year, day);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* last char in string is modulo 10 checksum
|
* Check
|
||||||
* edited out as checksum isnt consistent
|
* @param str The string to check
|
||||||
*
|
* @returns Whether true of the string has a valid length
|
||||||
* int chk = CheckSum(str);
|
|
||||||
* if (chk != (str[TLE_LEN_LINE_DATA - 1] - '0'))
|
|
||||||
* return false;
|
|
||||||
*/
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
bool Tle::IsValidLineLength(const std::string& str)
|
bool Tle::IsValidLineLength(const std::string& str)
|
||||||
{
|
{
|
||||||
return str.length() == GetLineLength() ? true : false;
|
return str.length() == GetLineLength() ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* validate line given a pattern
|
* Convert a string containing an integer
|
||||||
|
* @param[in] str The string to convert
|
||||||
|
* @param[out] val The result
|
||||||
|
* @exception TleException on conversion error
|
||||||
*/
|
*/
|
||||||
void Tle::ValidateLine(const std::string& line, const std::string& pattern)
|
void Tle::ExtractInteger(const std::string& str, unsigned int& val)
|
||||||
{
|
{
|
||||||
/*
|
std::string temp;
|
||||||
* check length of line
|
bool found_digit = false;
|
||||||
*/
|
|
||||||
if (!IsValidLineLength(line))
|
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
|
||||||
{
|
{
|
||||||
throw TleException("Invalid line length.");
|
if (isdigit(*i))
|
||||||
|
{
|
||||||
|
found_digit = true;
|
||||||
|
temp += *i;
|
||||||
}
|
}
|
||||||
|
else if (found_digit)
|
||||||
for (size_t i = 0; i < pattern.length(); i++)
|
|
||||||
{
|
{
|
||||||
char ptrn = pattern[i];
|
throw TleException("Unexpected non digit");
|
||||||
char mtch = line[i];
|
}
|
||||||
|
else if (*i != ' ')
|
||||||
switch (ptrn)
|
|
||||||
{
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case ' ':
|
|
||||||
case '.':
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* should match exactly
|
|
||||||
*/
|
|
||||||
if (ptrn != mtch)
|
|
||||||
{
|
{
|
||||||
throw TleException("Invalid character");
|
throw TleException("Invalid character");
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 'N':
|
|
||||||
|
if (temp.length() == 0)
|
||||||
|
{
|
||||||
|
temp += '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Util::FromString<unsigned int>(temp, val))
|
||||||
|
{
|
||||||
|
throw TleException("Failed to convert value to integer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a string containing an double
|
||||||
|
* @param[in] str The string to convert
|
||||||
|
* @param[in] point_pos The position of the decimal point. (-1 if none)
|
||||||
|
* @param[out] val The result
|
||||||
|
* @exception TleException on conversion error
|
||||||
|
*/
|
||||||
|
void Tle::ExtractDouble(const std::string& str, int point_pos, double& val)
|
||||||
|
{
|
||||||
|
std::string temp;
|
||||||
|
bool found_digit = false;
|
||||||
|
|
||||||
|
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* number or ' '
|
* integer part
|
||||||
*/
|
*/
|
||||||
if (!std::isdigit(mtch, std::locale::classic()) && mtch != ' ')
|
if (i < str.begin() + point_pos - 1)
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
if (i == str.begin())
|
||||||
|
{
|
||||||
|
if(*i == '-' || *i == '+')
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* first character could be signed
|
||||||
|
*/
|
||||||
|
temp += *i;
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!done)
|
||||||
|
{
|
||||||
|
if (isdigit(*i))
|
||||||
|
{
|
||||||
|
found_digit = true;
|
||||||
|
temp += *i;
|
||||||
|
}
|
||||||
|
else if (found_digit)
|
||||||
|
{
|
||||||
|
throw TleException("Unexpected non digit");
|
||||||
|
}
|
||||||
|
else if (*i != ' ')
|
||||||
{
|
{
|
||||||
throw TleException("Invalid character");
|
throw TleException("Invalid character");
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case '+':
|
}
|
||||||
|
/*
|
||||||
|
* decimal point
|
||||||
|
*/
|
||||||
|
else if (i == str.begin() + point_pos - 1)
|
||||||
|
{
|
||||||
|
if (temp.length() == 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* + or - or space or 0 or digit
|
* integer part is blank, so add a '0'
|
||||||
*/
|
*/
|
||||||
if (mtch != '+' && mtch != '-'
|
temp += '0';
|
||||||
&& mtch != ' ' && mtch != '0'
|
|
||||||
&& !std::isdigit(mtch, std::locale::classic()))
|
|
||||||
{
|
|
||||||
throw TleException("Invalid character");
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
if (*i == '.')
|
||||||
case '-':
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* + or -
|
* decimal point found
|
||||||
*/
|
*/
|
||||||
if (mtch != '+' && mtch != '-')
|
temp += *i;
|
||||||
{
|
|
||||||
throw TleException("Invalid character");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'C':
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* U or S
|
|
||||||
*/
|
|
||||||
if (mtch != 'U' && mtch != 'S')
|
|
||||||
{
|
|
||||||
throw TleException("Invalid character");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'X':
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* alpha or ' '
|
|
||||||
*/
|
|
||||||
if (!std::isupper(mtch, std::locale::classic()) &&
|
|
||||||
!std::isalpha(mtch, std::locale::classic()) &&
|
|
||||||
mtch != ' ')
|
|
||||||
{
|
|
||||||
throw TleException("Invalid character");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw TleException("Invalid pattern character");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* compute checksum
|
|
||||||
*/
|
|
||||||
int Tle::CheckSum(const std::string & str)
|
|
||||||
{
|
|
||||||
size_t len = str.size() - 1;
|
|
||||||
int xsum = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
char ch = str[i];
|
|
||||||
|
|
||||||
if (std::isdigit(ch, std::locale::classic()))
|
|
||||||
{
|
|
||||||
xsum += (ch - '0');
|
|
||||||
}
|
|
||||||
else if (ch == '-')
|
|
||||||
{
|
|
||||||
xsum++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (xsum % 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Tle::ExtractNoradNumber(const std::string& str, int line_number)
|
|
||||||
{
|
|
||||||
std::string norad_number;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check length
|
|
||||||
*/
|
|
||||||
if (!IsValidLineLength(str))
|
|
||||||
{
|
|
||||||
throw TleException("Invalid line length.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* extract string
|
|
||||||
*/
|
|
||||||
if (line_number == 1)
|
|
||||||
{
|
|
||||||
norad_number = str.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM);
|
|
||||||
}
|
|
||||||
else if (line_number == 2)
|
|
||||||
{
|
|
||||||
norad_number = str.substr(TLE2_COL_NORADNUM, TLE2_LEN_NORADNUM);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw TleException("Invalid line number to check.");
|
throw TleException("Failed to find decimal point");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* fraction part
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (i == str.begin() && point_pos == -1)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* no decimal point expected, add 0. beginning
|
||||||
|
*/
|
||||||
|
temp += '0';
|
||||||
|
temp += '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
return norad_number;
|
/*
|
||||||
|
* should be a digit
|
||||||
|
*/
|
||||||
|
if (isdigit(*i))
|
||||||
|
{
|
||||||
|
temp += *i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw TleException("Invalid digit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Util::FromString<double>(temp, val))
|
||||||
|
{
|
||||||
|
throw TleException("Failed to convert value to double");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a string containing an exponential
|
||||||
|
* @param[in] str The string to convert
|
||||||
|
* @param[out] val The result
|
||||||
|
* @exception TleException on conversion error
|
||||||
|
*/
|
||||||
|
void Tle::ExtractExponential(const std::string& str, double& val)
|
||||||
|
{
|
||||||
|
std::string temp;
|
||||||
|
|
||||||
|
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
|
||||||
|
{
|
||||||
|
if (i == str.begin())
|
||||||
|
{
|
||||||
|
if (*i == '-' || *i == '+' || *i == ' ')
|
||||||
|
{
|
||||||
|
if (*i == '-')
|
||||||
|
{
|
||||||
|
temp += *i;
|
||||||
|
}
|
||||||
|
temp += '0';
|
||||||
|
temp += '.';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw TleException("Invalid sign");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (i == str.begin() + str.length() - 2)
|
||||||
|
{
|
||||||
|
if (*i == '-' || *i == '+')
|
||||||
|
{
|
||||||
|
temp += 'e';
|
||||||
|
temp += *i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw TleException("Invalid exponential sign");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isdigit(*i))
|
||||||
|
{
|
||||||
|
temp += *i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw TleException("Invalid digit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Util::FromString<double>(temp, val))
|
||||||
|
{
|
||||||
|
throw TleException("Failed to convert value to double");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
241
libsgp4/Tle.h
241
libsgp4/Tle.h
|
|
@ -1,86 +1,164 @@
|
||||||
#ifndef TLE_H_
|
#ifndef TLE_H_
|
||||||
#define TLE_H_
|
#define TLE_H_
|
||||||
|
|
||||||
#include "Globals.h"
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "Julian.h"
|
#include "DateTime.h"
|
||||||
#include "TleException.h"
|
#include "TleException.h"
|
||||||
|
|
||||||
#include <iostream>
|
/**
|
||||||
|
* Tle class
|
||||||
|
* @details Loads and validates a tle.
|
||||||
|
*/
|
||||||
class Tle
|
class Tle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Tle(const std::string& line_one, const std::string& line_two)
|
/**
|
||||||
: line_one_(line_one), line_two_(line_two)
|
* @details Initialise given the two lines of a tle
|
||||||
{
|
* @param[in] line_one Tle line one
|
||||||
Initialize();
|
* @param[in] line_two Tle line two
|
||||||
}
|
*/
|
||||||
|
Tle(const std::string& line_one,
|
||||||
Tle(const std::string& name, const std::string& line_one,
|
|
||||||
const std::string& line_two)
|
const std::string& line_two)
|
||||||
: name_(name),line_one_(line_one), line_two_(line_two)
|
: line_one_(line_one),
|
||||||
|
line_two_(line_two)
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tle(const Tle& tle);
|
/**
|
||||||
|
* @details Initialise given the satellite name and the two lines of a tle
|
||||||
|
* @param[in] name Satellite name
|
||||||
|
* @param[in] line_one Tle line one
|
||||||
|
* @param[in] line_two Tle line two
|
||||||
|
*/
|
||||||
|
Tle(const std::string& name,
|
||||||
|
const std::string& line_one,
|
||||||
|
const std::string& line_two)
|
||||||
|
: name_(name),
|
||||||
|
line_one_(line_one),
|
||||||
|
line_two_(line_two)
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor
|
||||||
|
* @param[in] tle Tle object to copy from
|
||||||
|
*/
|
||||||
|
Tle(const Tle& tle)
|
||||||
|
{
|
||||||
|
name_ = tle.name_;
|
||||||
|
line_one_ = tle.line_one_;
|
||||||
|
line_two_ = tle.line_two_;
|
||||||
|
|
||||||
|
norad_number_ = tle.norad_number_;
|
||||||
|
int_designator_ = tle.int_designator_;
|
||||||
|
epoch_ = tle.epoch_;
|
||||||
|
mean_motion_dt2_ = tle.mean_motion_dt2_;
|
||||||
|
mean_motion_ddt6_ = tle.mean_motion_ddt6_;
|
||||||
|
bstar_ = tle.bstar_;
|
||||||
|
inclination_ = tle.inclination_;
|
||||||
|
right_ascending_node_ = tle.right_ascending_node_;
|
||||||
|
eccentricity_ = tle.eccentricity_;
|
||||||
|
argument_perigee_ = tle.argument_perigee_;
|
||||||
|
mean_anomaly_ = tle.mean_anomaly_;
|
||||||
|
mean_motion_ = tle.mean_motion_;
|
||||||
|
orbit_number_ = tle.orbit_number_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~Tle()
|
virtual ~Tle()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* get raw strings
|
* Get the satellite name
|
||||||
|
* @returns the satellite name
|
||||||
*/
|
*/
|
||||||
std::string GetName() const
|
std::string GetName() const
|
||||||
{
|
{
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the first line of the tle
|
||||||
|
* @returns the first line of the tle
|
||||||
|
*/
|
||||||
std::string GetLine1() const
|
std::string GetLine1() const
|
||||||
{
|
{
|
||||||
return line_one_;
|
return line_one_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the second line of the tle
|
||||||
|
* @returns the second line of the tle
|
||||||
|
*/
|
||||||
std::string GetLine2() const
|
std::string GetLine2() const
|
||||||
{
|
{
|
||||||
return line_two_;
|
return line_two_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* get tle values
|
* Get the norad number
|
||||||
|
* @returns the norad number
|
||||||
*/
|
*/
|
||||||
unsigned int NoradNumber() const
|
unsigned int NoradNumber() const
|
||||||
{
|
{
|
||||||
return norad_number_;
|
return norad_number_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string InternationlDesignator() const
|
/**
|
||||||
|
* Get the international designator
|
||||||
|
* @returns the international designator
|
||||||
|
*/
|
||||||
|
std::string IntDesignator() const
|
||||||
{
|
{
|
||||||
return international_designator_;
|
return int_designator_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Julian Epoch() const
|
/**
|
||||||
|
* Get the tle epoch
|
||||||
|
* @returns the tle epoch
|
||||||
|
*/
|
||||||
|
DateTime Epoch() const
|
||||||
{
|
{
|
||||||
return epoch_;
|
return epoch_;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeanMotionDot() const
|
/**
|
||||||
|
* Get the first time derivative of the mean motion divided by two
|
||||||
|
* @returns the first time derivative of the mean motion divided by two
|
||||||
|
*/
|
||||||
|
double MeanMotionDt2() const
|
||||||
{
|
{
|
||||||
return mean_motion_dot_;
|
return mean_motion_dt2_;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeanMotionDot2() const
|
/**
|
||||||
|
* Get the second time derivative of mean motion divided by six
|
||||||
|
* @returns the second time derivative of mean motion divided by six
|
||||||
|
*/
|
||||||
|
double MeanMotionDdt6() const
|
||||||
{
|
{
|
||||||
return mean_motion_dot2_;
|
return mean_motion_ddt6_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the BSTAR drag term
|
||||||
|
* @returns the BSTAR drag term
|
||||||
|
*/
|
||||||
double BStar() const
|
double BStar() const
|
||||||
{
|
{
|
||||||
return bstar_;
|
return bstar_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the inclination
|
||||||
|
* @param in_degrees Whether to return the value in degrees or radians
|
||||||
|
* @returns the inclination
|
||||||
|
*/
|
||||||
double Inclination(bool in_degrees) const
|
double Inclination(bool in_degrees) const
|
||||||
{
|
{
|
||||||
if (in_degrees)
|
if (in_degrees)
|
||||||
|
|
@ -93,6 +171,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the right ascension of the ascending node
|
||||||
|
* @param in_degrees Whether to return the value in degrees or radians
|
||||||
|
* @returns the right ascension of the ascending node
|
||||||
|
*/
|
||||||
double RightAscendingNode(const bool in_degrees) const
|
double RightAscendingNode(const bool in_degrees) const
|
||||||
{
|
{
|
||||||
if (in_degrees)
|
if (in_degrees)
|
||||||
|
|
@ -105,11 +188,20 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the eccentricity
|
||||||
|
* @returns the eccentricity
|
||||||
|
*/
|
||||||
double Eccentricity() const
|
double Eccentricity() const
|
||||||
{
|
{
|
||||||
return eccentricity_;
|
return eccentricity_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the argument of perigee
|
||||||
|
* @param in_degrees Whether to return the value in degrees or radians
|
||||||
|
* @returns the argument of perigee
|
||||||
|
*/
|
||||||
double ArgumentPerigee(const bool in_degrees) const
|
double ArgumentPerigee(const bool in_degrees) const
|
||||||
{
|
{
|
||||||
if (in_degrees)
|
if (in_degrees)
|
||||||
|
|
@ -122,6 +214,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mean anomaly
|
||||||
|
* @param in_degrees Whether to return the value in degrees or radians
|
||||||
|
* @returns the mean anomaly
|
||||||
|
*/
|
||||||
double MeanAnomaly(const bool in_degrees) const
|
double MeanAnomaly(const bool in_degrees) const
|
||||||
{
|
{
|
||||||
if (in_degrees)
|
if (in_degrees)
|
||||||
|
|
@ -134,67 +231,84 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mean motion
|
||||||
|
* @returns the mean motion (revolutions per day)
|
||||||
|
*/
|
||||||
double MeanMotion() const
|
double MeanMotion() const
|
||||||
{
|
{
|
||||||
return mean_motion_;
|
return mean_motion_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the orbit number
|
||||||
|
* @returns the orbit number
|
||||||
|
*/
|
||||||
unsigned int OrbitNumber() const
|
unsigned int OrbitNumber() const
|
||||||
{
|
{
|
||||||
return orbit_number_;
|
return orbit_number_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* helper / validation methods
|
* Get the expected tle line length
|
||||||
|
* @returns the tle line length
|
||||||
*/
|
*/
|
||||||
static unsigned int GetLineLength()
|
static unsigned int GetLineLength()
|
||||||
{
|
{
|
||||||
return TLE_LEN_LINE_DATA;
|
return TLE_LEN_LINE_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IsValidPair(const std::string& line1, const std::string& line2);
|
/**
|
||||||
static void IsValidLine(const std::string& str, int line_number);
|
* Dump this object to a string
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
std::string ToString() const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::right << std::fixed;
|
||||||
|
ss << "Norad Number: " << NoradNumber() << std::endl;
|
||||||
|
ss << "Int. Designator: " << IntDesignator() << std::endl;
|
||||||
|
ss << "Epoch: " << Epoch() << std::endl;
|
||||||
|
ss << "Orbit Number: " << OrbitNumber() << std::endl;
|
||||||
|
ss << std::setprecision(8);
|
||||||
|
ss << "Mean Motion Dt2: ";
|
||||||
|
ss << std::setw(12) << MeanMotionDt2() << std::endl;
|
||||||
|
ss << "Mean Motion Ddt6: ";
|
||||||
|
ss << std::setw(12) << MeanMotionDdt6() << std::endl;
|
||||||
|
ss << "Eccentricity: ";
|
||||||
|
ss << std::setw(12) << Eccentricity() << std::endl;
|
||||||
|
ss << "BStar: ";
|
||||||
|
ss << std::setw(12) << BStar() << std::endl;
|
||||||
|
ss << "Inclination: ";
|
||||||
|
ss << std::setw(12) << Inclination(true) << std::endl;
|
||||||
|
ss << "Right Ascending Node: ";
|
||||||
|
ss << std::setw(12) << RightAscendingNode(true) << std::endl;
|
||||||
|
ss << "Argument Perigee: ";
|
||||||
|
ss << std::setw(12) << ArgumentPerigee(true) << std::endl;
|
||||||
|
ss << "Mean Anomaly: ";
|
||||||
|
ss << std::setw(12) << MeanAnomaly(true) << std::endl;
|
||||||
|
ss << "Mean Motion: ";
|
||||||
|
ss << std::setw(12) << MeanMotion() << std::endl;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
|
||||||
* initialize from raw tle strings
|
|
||||||
*/
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
/*
|
|
||||||
* format a raw string into an exponent string
|
|
||||||
*/
|
|
||||||
static std::string ExpToDecimal(const std::string&);
|
|
||||||
/*
|
|
||||||
* validate a line against a pattern
|
|
||||||
*/
|
|
||||||
static void ValidateLine(const std::string& line,
|
|
||||||
const std::string& pattern);
|
|
||||||
/*
|
|
||||||
* compute checksum
|
|
||||||
*/
|
|
||||||
static int CheckSum(const std::string& str);
|
|
||||||
|
|
||||||
static std::string ExtractNoradNumber(const std::string& str,
|
|
||||||
int line_number);
|
|
||||||
|
|
||||||
static bool IsValidLineLength(const std::string& str);
|
static bool IsValidLineLength(const std::string& str);
|
||||||
|
void ExtractInteger(const std::string& str, unsigned int& val);
|
||||||
|
void ExtractDouble(const std::string& str, int point_pos, double& val);
|
||||||
|
void ExtractExponential(const std::string& str, double& val);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
|
||||||
* raw tle data
|
|
||||||
*/
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::string line_one_;
|
std::string line_one_;
|
||||||
std::string line_two_;
|
std::string line_two_;
|
||||||
|
|
||||||
/*
|
|
||||||
* extracted values all in native units
|
|
||||||
*/
|
|
||||||
unsigned int norad_number_;
|
unsigned int norad_number_;
|
||||||
std::string international_designator_;
|
std::string int_designator_;
|
||||||
Julian epoch_;
|
DateTime epoch_;
|
||||||
double mean_motion_dot_;
|
double mean_motion_dt2_;
|
||||||
double mean_motion_dot2_;
|
double mean_motion_ddt6_;
|
||||||
double bstar_;
|
double bstar_;
|
||||||
double inclination_;
|
double inclination_;
|
||||||
double right_ascending_node_;
|
double right_ascending_node_;
|
||||||
|
|
@ -204,13 +318,14 @@ private:
|
||||||
double mean_motion_;
|
double mean_motion_;
|
||||||
unsigned int orbit_number_;
|
unsigned int orbit_number_;
|
||||||
|
|
||||||
/*
|
|
||||||
* line lengths
|
|
||||||
*/
|
|
||||||
static const unsigned int TLE_LEN_LINE_DATA = 69;
|
static const unsigned int TLE_LEN_LINE_DATA = 69;
|
||||||
static const unsigned int TLE_LEN_LINE_NAME = 22;
|
static const unsigned int TLE_LEN_LINE_NAME = 22;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& strm, const Tle& t)
|
||||||
|
{
|
||||||
|
return strm << t.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -2,28 +2,38 @@
|
||||||
#define TLEEXCEPTION_H_
|
#define TLEEXCEPTION_H_
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
class TleException : public std::exception
|
class TleException : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param message Exception message
|
||||||
|
*/
|
||||||
TleException(const char* message)
|
TleException(const char* message)
|
||||||
: message_(message)
|
: m_message(message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~TleException(void) throw ()
|
virtual ~TleException(void) throw ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the exception message
|
||||||
|
* @returns the exception message
|
||||||
|
*/
|
||||||
virtual const char* what() const throw ()
|
virtual const char* what() const throw ()
|
||||||
{
|
{
|
||||||
return message_.c_str();
|
return m_message.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string message_;
|
/** the exception message */
|
||||||
|
std::string m_message;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,4 @@ namespace Util
|
||||||
TrimLeft(s);
|
TrimLeft(s);
|
||||||
TrimRight(s);
|
TrimRight(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,46 @@ struct Vector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
Vector()
|
Vector()
|
||||||
: x(0.0), y(0.0), z(0.0), w(0.0)
|
: x(0.0), y(0.0), z(0.0), w(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(double xx, double yy, double zz)
|
/**
|
||||||
: x(xx), y(yy), z(zz), w(0.0)
|
* Constructor
|
||||||
|
* @param arg_x x value
|
||||||
|
* @param arg_y y value
|
||||||
|
* @param arg_z z value
|
||||||
|
*/
|
||||||
|
Vector(const double arg_x,
|
||||||
|
const double arg_y,
|
||||||
|
const double arg_z)
|
||||||
|
: x(arg_x), y(arg_y), z(arg_z), w(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(double xx, double yy, double zz, double ww)
|
/**
|
||||||
: x(xx), y(yy), z(zz), w(ww)
|
* Constructor
|
||||||
|
* @param arg_x x value
|
||||||
|
* @param arg_y y value
|
||||||
|
* @param arg_z z value
|
||||||
|
* @param arg_w w value
|
||||||
|
*/
|
||||||
|
Vector(const double arg_x,
|
||||||
|
const double arg_y,
|
||||||
|
const double arg_z,
|
||||||
|
const double arg_w)
|
||||||
|
: x(arg_x), y(arg_y), z(arg_z), w(arg_w)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor
|
||||||
|
* @param v value to copy from
|
||||||
|
*/
|
||||||
Vector(const Vector& v)
|
Vector(const Vector& v)
|
||||||
{
|
{
|
||||||
x = v.x;
|
x = v.x;
|
||||||
|
|
@ -33,10 +58,17 @@ public:
|
||||||
w = v.w;
|
w = v.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~Vector()
|
virtual ~Vector()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assignment operator
|
||||||
|
* @param v value to copy from
|
||||||
|
*/
|
||||||
Vector& operator=(const Vector& v)
|
Vector& operator=(const Vector& v)
|
||||||
{
|
{
|
||||||
if (this != &v)
|
if (this != &v)
|
||||||
|
|
@ -49,23 +81,31 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetMagnitude() const
|
/**
|
||||||
{
|
* Subtract operator
|
||||||
return sqrt(x * x + y * y + z * z);
|
* @param v value to suctract from
|
||||||
}
|
|
||||||
|
|
||||||
Vector Subtract(const Vector& v) const
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* subtract (this) - (v)
|
|
||||||
* and return result
|
|
||||||
*/
|
*/
|
||||||
|
Vector operator-(const Vector& v)
|
||||||
|
{
|
||||||
return Vector(x - v.x,
|
return Vector(x - v.x,
|
||||||
y - v.y,
|
y - v.y,
|
||||||
z - v.z,
|
z - v.z,
|
||||||
0.0);
|
0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the magnitude of the vector
|
||||||
|
* @returns magnitude of the vector
|
||||||
|
*/
|
||||||
|
double GetMagnitude() const
|
||||||
|
{
|
||||||
|
return sqrt(x * x + y * y + z * z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the dot product
|
||||||
|
* @returns dot product
|
||||||
|
*/
|
||||||
double Dot(const Vector& vec) const
|
double Dot(const Vector& vec) const
|
||||||
{
|
{
|
||||||
return (x * vec.x) +
|
return (x * vec.x) +
|
||||||
|
|
@ -73,20 +113,28 @@ public:
|
||||||
(z * vec.z);
|
(z * vec.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this vector to a string
|
||||||
|
* @returns this vector as a string
|
||||||
|
*/
|
||||||
std::string ToString() const
|
std::string ToString() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::right << std::fixed << std::setprecision(2);
|
ss << std::right << std::fixed << std::setprecision(3);
|
||||||
ss << "X: " << std::setw(8) << x;
|
ss << "X: " << std::setw(9) << x;
|
||||||
ss << ", Y: " << std::setw(8) << y;
|
ss << ", Y: " << std::setw(9) << y;
|
||||||
ss << ", Z: " << std::setw(8) << z;
|
ss << ", Z: " << std::setw(9) << z;
|
||||||
ss << ", W: " << std::setw(8) << w;
|
ss << ", W: " << std::setw(9) << w;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** x value */
|
||||||
double x;
|
double x;
|
||||||
|
/** y value */
|
||||||
double y;
|
double y;
|
||||||
|
/** z value */
|
||||||
double z;
|
double z;
|
||||||
|
/** w value */
|
||||||
double w;
|
double w;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,30 @@
|
||||||
#include <Observer.h>
|
#include <Observer.h>
|
||||||
#include <SGP4.h>
|
#include <SGP4.h>
|
||||||
#include <Util.h>
|
#include <Util.h>
|
||||||
|
#include <CoordTopographic.h>
|
||||||
|
#include <CoordGeodetic.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
const int kPASS_TIME_STEP = 180; // time step in seconds, when searching for aos/los
|
struct PassDetails
|
||||||
|
{
|
||||||
double FindMaxElevation(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian& aos, const Julian& los) {
|
DateTime aos;
|
||||||
|
DateTime los;
|
||||||
|
double max_elevation;
|
||||||
|
};
|
||||||
|
|
||||||
|
double FindMaxElevation(
|
||||||
|
const CoordGeodetic& user_geo,
|
||||||
|
SGP4& sgp4,
|
||||||
|
const DateTime& aos,
|
||||||
|
const DateTime& los)
|
||||||
|
{
|
||||||
Observer obs(user_geo);
|
Observer obs(user_geo);
|
||||||
|
|
||||||
double max_elevation = -99.9;
|
double max_elevation = 0.0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* time step in seconds
|
* time step in seconds
|
||||||
*/
|
*/
|
||||||
|
|
@ -25,9 +38,9 @@ double FindMaxElevation(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian&
|
||||||
*/
|
*/
|
||||||
bool fine_tune = false;
|
bool fine_tune = false;
|
||||||
|
|
||||||
Julian current_time = aos;
|
DateTime current_time(aos);
|
||||||
while (current_time < los && searching) {
|
while (current_time < los && searching)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* find position
|
* find position
|
||||||
*/
|
*/
|
||||||
|
|
@ -37,16 +50,18 @@ double FindMaxElevation(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian&
|
||||||
/*
|
/*
|
||||||
* keep updating max elevation
|
* keep updating max elevation
|
||||||
*/
|
*/
|
||||||
if (topo.elevation > max_elevation) {
|
if (topo.elevation > max_elevation)
|
||||||
|
{
|
||||||
max_elevation = topo.elevation;
|
max_elevation = topo.elevation;
|
||||||
} else if (!fine_tune) {
|
}
|
||||||
|
else if (!fine_tune)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* passed max elevation
|
* passed max elevation
|
||||||
* max elevation happened in the last 6 minutes
|
* max elevation happened in the last 6 minutes
|
||||||
* go back and fine tune max elevation value
|
* go back and fine tune max elevation value
|
||||||
*/
|
*/
|
||||||
current_time.AddSec(-2.0 * time_step);
|
current_time = current_time.AddSeconds(-2.0 * time_step);
|
||||||
/*
|
/*
|
||||||
* dont go back before aos
|
* dont go back before aos
|
||||||
*/
|
*/
|
||||||
|
|
@ -64,7 +79,9 @@ double FindMaxElevation(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian&
|
||||||
*/
|
*/
|
||||||
max_elevation = -99.9;
|
max_elevation = -99.9;
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* found max elevation
|
* found max elevation
|
||||||
*/
|
*/
|
||||||
|
|
@ -72,48 +89,72 @@ double FindMaxElevation(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian&
|
||||||
searching = false;
|
searching = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searching) {
|
if (searching)
|
||||||
current_time.AddSec(time_step);
|
{
|
||||||
|
current_time = current_time.AddSeconds(time_step);
|
||||||
if (current_time > los)
|
if (current_time > los)
|
||||||
|
{
|
||||||
current_time = los;
|
current_time = los;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return max_elevation;
|
return max_elevation;
|
||||||
}
|
}
|
||||||
|
|
||||||
Julian FindCrossingPoint(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian& initial_time1, const Julian& initial_time2, bool finding_aos) {
|
DateTime FindCrossingPoint(
|
||||||
|
const CoordGeodetic& user_geo,
|
||||||
|
SGP4& sgp4,
|
||||||
|
const DateTime& initial_time1,
|
||||||
|
const DateTime& initial_time2,
|
||||||
|
bool finding_aos)
|
||||||
|
{
|
||||||
Observer obs(user_geo);
|
Observer obs(user_geo);
|
||||||
|
|
||||||
bool searching = true;
|
bool searching = true;
|
||||||
unsigned int loop_count = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
Julian time1 = initial_time1;
|
DateTime time1(initial_time1);
|
||||||
Julian time2 = initial_time2;
|
DateTime time2(initial_time2);
|
||||||
|
|
||||||
Julian middle_time = time1 + (time2 - time1) / 2.0;
|
double diff = (time2 - time1).TotalSeconds();
|
||||||
|
if (finding_aos)
|
||||||
while (searching && loop_count < 25) {
|
{
|
||||||
|
diff = std::floor(diff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = std::ceil(diff);
|
||||||
|
}
|
||||||
|
DateTime middle_time(time1.AddSeconds(diff));
|
||||||
|
|
||||||
|
while (searching && cnt < 25)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* find position
|
* calculate satellite position
|
||||||
*/
|
*/
|
||||||
Eci eci = sgp4.FindPosition(middle_time);
|
Eci eci = sgp4.FindPosition(middle_time);
|
||||||
CoordTopographic topo = obs.GetLookAngle(eci);
|
CoordTopographic topo = obs.GetLookAngle(eci);
|
||||||
|
|
||||||
if (topo.elevation > 0.0) {
|
if (topo.elevation > 0.0)
|
||||||
|
{
|
||||||
if (finding_aos) {
|
if (finding_aos)
|
||||||
|
{
|
||||||
time2 = middle_time;
|
time2 = middle_time;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
time1 = middle_time;
|
time1 = middle_time;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
if (finding_aos) {
|
{
|
||||||
|
if (finding_aos)
|
||||||
|
{
|
||||||
time1 = middle_time;
|
time1 = middle_time;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
time2 = middle_time;
|
time2 = middle_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -121,120 +162,206 @@ Julian FindCrossingPoint(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian
|
||||||
/*
|
/*
|
||||||
* when two times are within a second, stop
|
* when two times are within a second, stop
|
||||||
*/
|
*/
|
||||||
if (((time2.GetDate() - time1.GetDate()) * kSECONDS_PER_DAY) < 0.5) {
|
if ((time2 - time1).TotalSeconds() < 1.5)
|
||||||
|
{
|
||||||
searching = false;
|
searching = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = (time2 - time1).TotalSeconds();
|
||||||
|
if (finding_aos)
|
||||||
|
{
|
||||||
|
diff = std::floor(diff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = std::ceil(diff);
|
||||||
|
}
|
||||||
|
middle_time = time1.AddSeconds(diff);
|
||||||
|
}
|
||||||
|
|
||||||
middle_time = time1 + (time2 - time1) / 2.0;
|
cnt++;
|
||||||
loop_count++;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return middle_time;
|
return middle_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AOSLOS(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian& start_time, const Julian& end_time) {
|
std::list<struct PassDetails> GeneratePassList(
|
||||||
|
const CoordGeodetic& user_geo,
|
||||||
|
SGP4& sgp4,
|
||||||
|
const DateTime& start_time,
|
||||||
|
const DateTime& end_time,
|
||||||
|
const int time_step)
|
||||||
|
{
|
||||||
|
std::list<struct PassDetails> pass_list;
|
||||||
|
|
||||||
Observer obs(user_geo);
|
Observer obs(user_geo);
|
||||||
|
|
||||||
Timespan time_step(0, 0, 0, kPASS_TIME_STEP);
|
DateTime aos_time;
|
||||||
|
DateTime los_time;
|
||||||
|
|
||||||
bool first_run = true;
|
|
||||||
bool end_of_pass = false;
|
|
||||||
Julian previous_time = start_time;
|
|
||||||
|
|
||||||
Julian aos_time;
|
|
||||||
Julian los_time;
|
|
||||||
bool found_aos = false;
|
bool found_aos = false;
|
||||||
bool found_los = false;
|
bool found_los = false;
|
||||||
|
|
||||||
Julian current_time = start_time;
|
DateTime previous_time(start_time);
|
||||||
while (current_time < end_time) {
|
DateTime current_time(start_time);
|
||||||
|
|
||||||
// find position
|
while (current_time < end_time)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* calculate satellite position
|
||||||
|
*/
|
||||||
Eci eci = sgp4.FindPosition(current_time);
|
Eci eci = sgp4.FindPosition(current_time);
|
||||||
CoordTopographic topo = obs.GetLookAngle(eci);
|
CoordTopographic topo = obs.GetLookAngle(eci);
|
||||||
|
|
||||||
if (topo.elevation > 0.0) {
|
std::cout << std::fixed << current_time << " " << topo.elevation << std::endl;
|
||||||
|
|
||||||
|
if (topo.elevation > 0.0)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* satellite is above horizon
|
* satellite is above horizon
|
||||||
* and its the first run, so just use start_time
|
|
||||||
*/
|
*/
|
||||||
if (first_run) {
|
if (start_time == current_time)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* satellite was already above the horizon at the start time,
|
||||||
|
* so use the start time
|
||||||
|
*/
|
||||||
aos_time = start_time;
|
aos_time = start_time;
|
||||||
found_aos = true;
|
}
|
||||||
found_los = false;
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* not the first iteration and satellite has
|
* find the point at which the satellite crossed the horizon
|
||||||
* gone above horizon, so find AOS
|
|
||||||
*/
|
*/
|
||||||
} else if (!found_aos) {
|
aos_time = FindCrossingPoint(
|
||||||
|
user_geo,
|
||||||
|
sgp4,
|
||||||
|
previous_time,
|
||||||
|
current_time,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
aos_time = FindCrossingPoint(user_geo, sgp4, previous_time, current_time, true);
|
|
||||||
found_aos = true;
|
found_aos = true;
|
||||||
found_los = false;
|
found_los = false;
|
||||||
}
|
}
|
||||||
} else {
|
else if (found_aos)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* if satellite now below horizon and have previously
|
* satellite now below horizon and we have an AOS, so record the
|
||||||
* found AOS, find LOS
|
* pass
|
||||||
*/
|
*/
|
||||||
if (found_aos) {
|
los_time = FindCrossingPoint(
|
||||||
|
user_geo,
|
||||||
|
sgp4,
|
||||||
|
previous_time,
|
||||||
|
current_time,
|
||||||
|
false);
|
||||||
|
|
||||||
los_time = FindCrossingPoint(user_geo, sgp4, previous_time, current_time, false);
|
|
||||||
found_aos = false;
|
found_aos = false;
|
||||||
found_los = false;
|
found_los = true;
|
||||||
end_of_pass = true;
|
|
||||||
double max_elevation = FindMaxElevation(user_geo, sgp4, aos_time, los_time);
|
|
||||||
std::cout << "AOS: " << aos_time << ", LOS: " << los_time << ", Max El: " << Util::RadiansToDegrees(max_elevation) << std::endl;
|
|
||||||
|
|
||||||
}
|
struct PassDetails pd;
|
||||||
|
pd.aos = aos_time;
|
||||||
|
pd.los = los_time;
|
||||||
|
pd.max_elevation = FindMaxElevation(
|
||||||
|
user_geo,
|
||||||
|
sgp4,
|
||||||
|
aos_time,
|
||||||
|
los_time);
|
||||||
|
|
||||||
|
pass_list.push_back(pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
first_run = false;
|
|
||||||
previous_time = current_time;
|
previous_time = current_time;
|
||||||
|
|
||||||
// at end of pass, move time along by 20 minutes
|
if (found_los)
|
||||||
if (end_of_pass)
|
{
|
||||||
current_time += Timespan(0, 0, 20, 0);
|
/*
|
||||||
|
* at the end of the pass move the time along by 20mins
|
||||||
|
*/
|
||||||
|
current_time = current_time + TimeSpan(0, 20, 0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
current_time += time_step;
|
{
|
||||||
|
/*
|
||||||
|
* move the time along by the time step value
|
||||||
|
*/
|
||||||
|
current_time = current_time + TimeSpan(0, 0, time_step);
|
||||||
|
}
|
||||||
|
|
||||||
// check we dont go past end time
|
|
||||||
if (current_time > end_time)
|
if (current_time > end_time)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* dont go past end time
|
||||||
|
*/
|
||||||
current_time = end_time;
|
current_time = end_time;
|
||||||
|
}
|
||||||
|
|
||||||
end_of_pass = false;
|
found_los = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (found_aos)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* is satellite still above horizon at end of search period
|
* satellite still above horizon at end of search period, so use end
|
||||||
|
* time as los
|
||||||
*/
|
*/
|
||||||
if (found_aos && !found_los) {
|
struct PassDetails pd;
|
||||||
|
pd.aos = aos_time;
|
||||||
|
pd.los = end_time;
|
||||||
|
pd.max_elevation = FindMaxElevation(user_geo, sgp4, aos_time, los_time);
|
||||||
|
|
||||||
los_time = end_time;
|
pass_list.push_back(pd);
|
||||||
double max_elevation = FindMaxElevation(user_geo, sgp4, aos_time, los_time);
|
|
||||||
std::cout << "AOS: " << aos_time << ", LOS: " << los_time << ", Max El: " << Util::RadiansToDegrees(max_elevation) << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pass_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
CoordGeodetic geo(51.507406923983446, -0.12773752212524414, 0.05);
|
CoordGeodetic geo(51.507406923983446, -0.12773752212524414, 0.05);
|
||||||
Tle tle("GIOVE-B ",
|
Tle tle("UK-DMC 2 ",
|
||||||
"1 32781U 08020A 11158.03814084 .00000088 00000-0 10000-3 0 4620",
|
"1 25544U 98067A 12285.65009259 .00017228 00000-0 30018-3 0 4501",
|
||||||
"2 32781 55.9142 172.9458 0022365 228.3743 131.4697 1.70953903 19437");
|
"2 25544 051.6477 262.7396 0017757 155.0745 185.1532 15.50683239796101");
|
||||||
SGP4 sgp4(tle);
|
SGP4 sgp4(tle);
|
||||||
|
|
||||||
Julian start_date;
|
std::cout << tle << std::endl;
|
||||||
Julian end_date(start_date);
|
|
||||||
end_date.AddDay(10.0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* generate 10 day schedule
|
* generate 1 day schedule
|
||||||
*/
|
*/
|
||||||
AOSLOS(geo, sgp4, start_date, end_date);
|
DateTime start_date = DateTime::Now();
|
||||||
|
DateTime end_date(start_date.AddDays(1.0));
|
||||||
|
|
||||||
|
std::list<struct PassDetails> pass_list;
|
||||||
|
std::list<struct PassDetails>::const_iterator itr;
|
||||||
|
|
||||||
|
std::cout << "Start time: " << start_date << std::endl;
|
||||||
|
std::cout << "End time : " << end_date << std::endl << std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* generate passes
|
||||||
|
*/
|
||||||
|
pass_list = GeneratePassList(geo, sgp4, start_date, end_date, 180);
|
||||||
|
|
||||||
|
if (pass_list.begin() == pass_list.end())
|
||||||
|
{
|
||||||
|
std::cout << "No passes found" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
itr = pass_list.begin();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::cout
|
||||||
|
<< "AOS: " << itr->aos
|
||||||
|
<< ", LOS: " << itr->los
|
||||||
|
<< ", Max El: " << Util::RadiansToDegrees(itr->max_elevation)
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
while (++itr != pass_list.end());
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
#include <Julian.h>
|
|
||||||
#include <Tle.h>
|
#include <Tle.h>
|
||||||
#include <SGP4.h>
|
#include <SGP4.h>
|
||||||
#include <Globals.h>
|
|
||||||
#include <Util.h>
|
|
||||||
#include <Observer.h>
|
#include <Observer.h>
|
||||||
#include <CoordGeodetic.h>
|
#include <CoordGeodetic.h>
|
||||||
#include <CoordTopographic.h>
|
#include <CoordTopographic.h>
|
||||||
|
|
@ -187,7 +184,7 @@ void RunTest(const char* infile)
|
||||||
{
|
{
|
||||||
if (line.length() >= Tle::GetLineLength())
|
if (line.length() >= Tle::GetLineLength())
|
||||||
{
|
{
|
||||||
Tle::IsValidLine(line.substr(0, Tle::GetLineLength()), 1);
|
//Tle::IsValidLine(line.substr(0, Tle::GetLineLength()), 1);
|
||||||
/*
|
/*
|
||||||
* store line and now read in second line
|
* store line and now read in second line
|
||||||
*/
|
*/
|
||||||
|
|
@ -236,7 +233,7 @@ void RunTest(const char* infile)
|
||||||
{
|
{
|
||||||
if (line.length() >= Tle::GetLineLength())
|
if (line.length() >= Tle::GetLineLength())
|
||||||
{
|
{
|
||||||
Tle::IsValidLine(line.substr(0, Tle::GetLineLength()), 2);
|
//Tle::IsValidLine(line.substr(0, Tle::GetLineLength()), 2);
|
||||||
Tle tle("Test", line1, line2);
|
Tle tle("Test", line1, line2);
|
||||||
RunTle(tle, start, end, inc);
|
RunTle(tle, start, end, inc);
|
||||||
}
|
}
|
||||||
|
|
@ -265,6 +262,3 @@ int main()
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <CoordTopographic.h>
|
||||||
|
#include <CoordGeodetic.h>
|
||||||
#include <Observer.h>
|
#include <Observer.h>
|
||||||
#include <SGP4.h>
|
#include <SGP4.h>
|
||||||
|
|
||||||
|
|
@ -6,20 +8,31 @@
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Observer obs(51.507406923983446, -0.12773752212524414, 0.05);
|
Observer obs(51.507406923983446, -0.12773752212524414, 0.05);
|
||||||
Tle tle = Tle("UK-DMC 2 ",
|
Tle tle = Tle("MASAT 1 ",
|
||||||
"1 35683U 09041C 11356.17214994 .00000411 00000-0 77254-4 0 6826",
|
"1 25544U 98067A 12285.65009259 .00017228 00000-0 30018-3 0 4501",
|
||||||
"2 35683 98.0512 251.8127 0001492 79.4611 280.6776 14.69611889128518");
|
"2 25544 051.6477 262.7396 0017757 155.0745 185.1532 15.50683239796101");
|
||||||
SGP4 sgp4(tle);
|
SGP4 sgp4(tle);
|
||||||
|
|
||||||
while(1)
|
while (true)
|
||||||
{
|
{
|
||||||
Julian now;
|
/*
|
||||||
|
* current time
|
||||||
|
*/
|
||||||
|
DateTime now = DateTime::Now(true);
|
||||||
|
/*
|
||||||
|
* calculate satellite position
|
||||||
|
*/
|
||||||
Eci eci = sgp4.FindPosition(now);
|
Eci eci = sgp4.FindPosition(now);
|
||||||
|
/*
|
||||||
|
* get look angle for observer to satellite
|
||||||
|
*/
|
||||||
CoordTopographic topo = obs.GetLookAngle(eci);
|
CoordTopographic topo = obs.GetLookAngle(eci);
|
||||||
|
/*
|
||||||
|
* convert satellite position to geodetic coordinates
|
||||||
|
*/
|
||||||
CoordGeodetic geo = eci.ToGeodetic();
|
CoordGeodetic geo = eci.ToGeodetic();
|
||||||
std::cout << now << " ";
|
|
||||||
std::cout << topo << " ";
|
std::cout << now << " " << topo << " " << geo << std::endl;
|
||||||
std::cout << geo << std::endl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue