Code comments, renaming of methods. Updated test programs.

feature/19
Daniel Warner 2012-10-24 18:01:17 +01:00
parent d8cd6e682b
commit 62da021303
24 changed files with 518 additions and 383 deletions

View File

@ -1,8 +1,8 @@
# Exact paths to config junk
^INSTALL$
^aclocal.m4$
^(config.guess|config.sub|depcomp|install-sh|ltmain.sh|missing)$
^config.(log|status)$
^(stamp-h1|depcomp|install-sh|ltmain.sh|missing)$
^config.(h|log|status|guess|sub)$
^autom4te.cache$
# Build artifacts

View File

@ -1,25 +0,0 @@
/* 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

285
configure vendored
View File

@ -579,6 +579,7 @@ CC
am__fastdepCXX_FALSE
am__fastdepCXX_TRUE
CXXDEPMODE
am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@ -595,6 +596,8 @@ CXX
RANLIB
AM_BACKSLASH
AM_DEFAULT_VERBOSITY
AM_DEFAULT_V
AM_V
am__untar
am__tar
AMTAR
@ -2358,11 +2361,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
# Always define AMTAR for backward compatibility.
# Always define AMTAR for backward compatibility. Yes, it's still used
# in the wild :-( We should find a proper way to deprecate it ...
AMTAR='$${TAR-tar}'
AMTAR=${AMTAR-"${am_missing_run}tar"}
am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
@ -2378,13 +2381,37 @@ yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=0;;
esac
am_make=${MAKE-make}
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
if ${am_cv_make_support_nested_variables+:} false; then :
$as_echo_n "(cached) " >&6
else
if $as_echo 'TRUE=$(BAR$(V))
BAR0=false
BAR1=true
V=1
am__doit:
@$(TRUE)
.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
am_cv_make_support_nested_variables=yes
else
am_cv_make_support_nested_variables=no
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
$as_echo "$am_cv_make_support_nested_variables" >&6; }
if test $am_cv_make_support_nested_variables = yes; then
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
AM_BACKSLASH='\'
#AC_CANONICAL_BUILD
ac_config_headers="$ac_config_headers config.h"
CFLAGS=" $CFLAGS"
CXXFLAGS=" $CXXFLAGS"
@ -3039,6 +3066,7 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@ -3063,6 +3091,7 @@ else
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@ -3122,7 +3151,7 @@ else
break
fi
;;
msvisualcpp | msvcmsys)
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@ -3187,9 +3216,9 @@ fi
if test x$enable_debug = xyes; then
AM_CXXFLAGS="-g -O0 -Werror -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
AM_CXXFLAGS="-g -O0 -Werror -Wextra -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long -Wconversion"
else
AM_CXXFLAGS="-DNDEBUG -O2 -fomit-frame-pointer -Werror -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
AM_CXXFLAGS="-DNDEBUG -O2 -fomit-frame-pointer -Wextra -Werror -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long -Wconversion"
fi
ac_ext=c
@ -3745,6 +3774,7 @@ else
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@ -3804,7 +3834,7 @@ else
break
fi
;;
msvisualcpp | msvcmsys)
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@ -3914,6 +3944,8 @@ ac_res=$ac_cv_search_clock_gettime
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
fi
@ -4012,7 +4044,43 @@ test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
DEFS=-DHAVE_CONFIG_H
# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
#
# If the first sed substitution is executed (which looks for macros that
# take arguments), then branch to the quote section. Otherwise,
# look for a macro that doesn't take arguments.
ac_script='
:mline
/\\$/{
N
s,\\\n,,
b mline
}
t clear
:clear
s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
t quote
s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
t quote
b any
:quote
s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/\[/\\&/g
s/\]/\\&/g
s/\$/$$/g
H
:any
${
g
s/^\n//
s/\n/ /g
p
}
'
DEFS=`sed -n "$ac_script" confdefs.h`
ac_libobjs=
ac_ltlibobjs=
@ -4478,15 +4546,11 @@ case $ac_config_files in *"
"*) set x $ac_config_files; shift; ac_config_files=$*;;
esac
case $ac_config_headers in *"
"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
esac
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"
config_headers="$ac_config_headers"
config_commands="$ac_config_commands"
_ACEOF
@ -4508,15 +4572,10 @@ Usage: $0 [OPTION]... [TAG]...
--recheck update $as_me by reconfiguring in the same conditions
--file=FILE[:TEMPLATE]
instantiate the configuration file FILE
--header=FILE[:TEMPLATE]
instantiate the configuration header FILE
Configuration files:
$config_files
Configuration headers:
$config_headers
Configuration commands:
$config_commands
@ -4583,18 +4642,7 @@ do
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
as_fn_append CONFIG_HEADERS " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h)
# Conflict between --help and --header
as_fn_error $? "ambiguous option: \`$1'
Try \`$0 --help' for more information.";;
--help | --hel | -h )
--he | --h | --help | --hel | -h )
$as_echo "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
@ -4655,7 +4703,6 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
"depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"libsgp4/Makefile") CONFIG_FILES="$CONFIG_FILES libsgp4/Makefile" ;;
@ -4674,7 +4721,6 @@ done
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
fi
@ -4863,116 +4909,8 @@ fi
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_FILES"
# Set up the scripts for CONFIG_HEADERS section.
# No need to generate them if there are no CONFIG_HEADERS.
# This happens for instance with `./config.status Makefile'.
if test -n "$CONFIG_HEADERS"; then
cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
BEGIN {
_ACEOF
# Transform confdefs.h into an awk script `defines.awk', embedded as
# here-document in config.status, that substitutes the proper values into
# config.h.in to produce config.h.
# Create a delimiter string that does not exist in confdefs.h, to ease
# handling of long lines.
ac_delim='%!_!# '
for ac_last_try in false false :; do
ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
if test -z "$ac_tt"; then
break
elif $ac_last_try; then
as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
done
# For the awk script, D is an array of macro values keyed by name,
# likewise P contains macro parameters if any. Preserve backslash
# newline sequences.
ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
sed -n '
s/.\{148\}/&'"$ac_delim"'/g
t rset
:rset
s/^[ ]*#[ ]*define[ ][ ]*/ /
t def
d
:def
s/\\$//
t bsnl
s/["\\]/\\&/g
s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
D["\1"]=" \3"/p
s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
d
:bsnl
s/["\\]/\\&/g
s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
D["\1"]=" \3\\\\\\n"\\/p
t cont
s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
t cont
d
:cont
n
s/.\{148\}/&'"$ac_delim"'/g
t clear
:clear
s/\\$//
t bsnlc
s/["\\]/\\&/g; s/^/"/; s/$/"/p
d
:bsnlc
s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
b cont
' <confdefs.h | sed '
s/'"$ac_delim"'/"\\\
"/g' >>$CONFIG_STATUS || ac_write_fail=1
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
for (key in D) D_is_set[key] = 1
FS = ""
}
/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
line = \$ 0
split(line, arg, " ")
if (arg[1] == "#") {
defundef = arg[2]
mac1 = arg[3]
} else {
defundef = substr(arg[1], 2)
mac1 = arg[2]
}
split(mac1, mac2, "(") #)
macro = mac2[1]
prefix = substr(line, 1, index(line, defundef) - 1)
if (D_is_set[macro]) {
# Preserve the white space surrounding the "#".
print prefix "define", macro P[macro] D[macro]
next
} else {
# Replace #undef with comments. This is necessary, for example,
# in the case of _POSIX_SOURCE, which is predefined and required
# on some systems where configure will not decide to define it.
if (defundef == "undef") {
print "/*", prefix defundef, macro, "*/"
next
}
}
}
{ print }
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
fi # test -n "$CONFIG_HEADERS"
eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS"
shift
for ac_tag
do
@ -5191,64 +5129,7 @@ which seems to be undefined. Please make sure it is defined" >&2;}
esac \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;
:H)
#
# CONFIG_HEADER
#
if test x"$ac_file" != x-; then
{
$as_echo "/* $configure_input */" \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
} >"$ac_tmp/config.h" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
$as_echo "$as_me: $ac_file is unchanged" >&6;}
else
rm -f "$ac_file"
mv "$ac_tmp/config.h" "$ac_file" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
fi
else
$as_echo "/* $configure_input */" \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
|| as_fn_error $? "could not create -" "$LINENO" 5
fi
# Compute "$ac_file"'s index in $config_headers.
_am_arg="$ac_file"
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$_am_arg" : 'X\(//\)[^/]' \| \
X"$_am_arg" : 'X\(//\)$' \| \
X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$_am_arg" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`/stamp-h$_am_stamp_count
;;
:C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
$as_echo "$as_me: executing $ac_file commands" >&6;}

View File

@ -2,10 +2,8 @@ AC_PREREQ([2.61])
AC_INIT([sgp4], 1.0, [info@danrw.com])
AM_INIT_AUTOMAKE
AM_SILENT_RULES([yes])
#AC_CANONICAL_BUILD
AC_CONFIG_SRCDIR([libsgp4/Tle.cpp])
AM_CONFIG_HEADER([config.h])
CFLAGS=" $CFLAGS"
CXXFLAGS=" $CXXFLAGS"
@ -21,12 +19,16 @@ AC_ARG_ENABLE(debug,
enable_debug=no)
if test x$enable_debug = xyes; then
AM_CXXFLAGS="-g -O0 -Werror -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
AM_CXXFLAGS="-g -O0 -Werror -Wextra -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long -Wconversion"
else
AM_CXXFLAGS="-DNDEBUG -O2 -fomit-frame-pointer -Werror -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long"
AM_CXXFLAGS="-DNDEBUG -O2 -fomit-frame-pointer -Wextra -Werror -W -Wall -ansi -pedantic -Wpointer-arith -Wwrite-strings -Wno-long-long -Wconversion"
fi
AC_SEARCH_LIBS(clock_gettime, [rt])
AC_SEARCH_LIBS([clock_gettime],
[rt],
[AC_DEFINE(HAVE_CLOCK_GETTIME,
[1],
[Define if clock_gettime is available.])])
AC_SUBST(AM_CXXFLAGS)

View File

@ -0,0 +1 @@
#include "CoordGeodetic.h"

View File

@ -25,18 +25,28 @@ public:
/**
* 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
* @param[in] lat the latitude (degrees by default)
* @param[in] lon the longitude (degrees by default)
* @param[in] alt the altitude in kilometers
* @param[in] is_radians whether the latitude/longitude is in radians
*/
CoordGeodetic(
double arg_latitude,
double arg_longitude,
double arg_altitude)
double lat,
double lon,
double alt,
bool is_radians = false)
{
latitude = Util::DegreesToRadians(arg_latitude);
longitude = Util::DegreesToRadians(arg_longitude);
altitude = arg_altitude;
if (is_radians)
{
latitude = lat;
longitude = lon;
}
else
{
latitude = Util::DegreesToRadians(lat);
longitude = Util::DegreesToRadians(lon);
}
altitude = alt;
}
/**
@ -127,6 +137,11 @@ private:
}
};
/**
* Dump a Coordgeodetic to a stream
* @params[in,out] strm stream to output to
* @params[in] g the CoordGeodetic to print
*/
inline std::ostream& operator<<(std::ostream& strm, const CoordGeodetic& g)
{
return strm << g.ToString();

View File

@ -0,0 +1 @@
#include "CoordTopographic.h"

View File

@ -24,42 +24,69 @@ namespace
class DateTime
{
public:
/**
* Default contructor
* Initialise to 0001/01/01 00:00:00.000000
*/
DateTime()
{
Initialise(1, 1, 1, 0, 0, 0, 0);
}
/**
* Constructor
* @param[in] ticks raw tick value
*/
DateTime(unsigned long long ticks)
: m_encoded(ticks)
{
}
/**
* Constructor
* @param[in] year the year
* @param[in] doy the day of the year
*/
DateTime(int year, double doy)
{
m_encoded = TimeSpan(AbsoluteDays(year, doy) * TicksPerDay).Ticks();
m_encoded = TimeSpan(static_cast<long long int>(AbsoluteDays(year, doy) * TicksPerDay)).Ticks();
}
/**
* Constructor
* @param[in] year the year
* @param[in] month the month
* @param[in] day the day
*/
DateTime(int year, int month, int day)
{
Initialise(year, month, day, 0, 0, 0, 0);
}
/**
* Constructor
* @param[in] year the year
* @param[in] month the month
* @param[in] day the day
* @param[in] hour the hour
* @param[in] minute the minute
* @param[in] second the second
*/
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);
}
/**
* Constructor
* @param[in] year the year
* @param[in] month the month
* @param[in] day the day
* @param[in] hour the hour
* @param[in] minute the minute
* @param[in] second the second
* @param[in] microsecond the microsecond
*/
void Initialise(int year,
int month,
int day,
@ -84,6 +111,11 @@ public:
microsecond).Ticks();
}
/**
* Return the current time
* @param[in] microseconds whether to set the microsecond component
* @returns a DateTime object set to the current date and time
*/
static DateTime Now(bool microseconds = false)
{
DateTime dt;
@ -111,6 +143,11 @@ public:
return dt;
}
/**
* Find whether a year is a leap year
* @param[in] year the year to check
* @returns whether the year is a leap year
*/
static bool IsLeapYear(int year)
{
if (!IsValidYear(year))
@ -121,6 +158,11 @@ public:
return (((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0);
}
/**
* Checks whether the given year is valid
* @param[in] year the year to check
* @returns whether the year is valid
*/
static bool IsValidYear(int year)
{
bool valid = true;
@ -131,6 +173,12 @@ public:
return valid;
}
/**
* Check whether the year/month is valid
* @param[in] year the year to check
* @param[in] month the month to check
* @returns whether the year/month is valid
*/
static bool IsValidYearMonth(int year, int month)
{
bool valid = true;
@ -148,6 +196,13 @@ public:
return valid;
}
/**
* Check whether the year/month/day is valid
* @param[in] year the year to check
* @param[in] month the month to check
* @param[in] day the day to check
* @returns whether the year/month/day is valid
*/
static bool IsValidYearMonthDay(int year, int month, int day)
{
bool valid = true;
@ -165,6 +220,12 @@ public:
return valid;
}
/**
* Find the number of days in a month given the year/month
* @param[in] year the year
* @param[in] month the month
* @returns the days in the given month
*/
static int DaysInMonth(int year, int month)
{
if (!IsValidYearMonth(year, month))
@ -186,6 +247,13 @@ public:
return daysInMonthPtr[month];
}
/**
* Find the day of the year given the year/month/day
* @param[in] year the year
* @param[in] month the month
* @param[in] day the day
* @returns the day of the year
*/
int DayOfYear(int year, int month, int day) const
{
if (!IsValidYearMonthDay(year, month, day))
@ -207,6 +275,9 @@ public:
return daysThisYear;
}
/**
*
*/
double AbsoluteDays(int year, double doy) const
{
@ -223,7 +294,7 @@ public:
- previousYear / 100
+ previousYear / 400;
return daysSoFar + doy - 1.0;
return static_cast<double>(daysSoFar) + doy - 1.0;
}
int AbsoluteDays(int year, int month, int day) const
@ -263,7 +334,7 @@ public:
* 5 Friday
* 6 Saturday
*/
return (((m_encoded / TicksPerDay) + 1) % 7);
return static_cast<int>(((m_encoded / TicksPerDay) + 1LL) % 7LL);
}
bool Equals(const DateTime& dt) const
@ -318,6 +389,11 @@ public:
return DateTime(year, month, day).Add(TimeOfDay());
}
/**
* Add a TimeSpan to this DateTime
* @param[in] t the TimeSpan to add
* @returns a DateTime which has the given TimeSpan added
*/
DateTime Add(const TimeSpan& t) const
{
return AddTicks(t.Ticks());
@ -345,7 +421,7 @@ public:
DateTime AddMicroseconds(const double microseconds) const
{
long long ticks = microseconds * TicksPerMicrosecond;
long long ticks = static_cast<long long>(microseconds * TicksPerMicrosecond);
return AddTicks(ticks);
}
@ -354,6 +430,10 @@ public:
return DateTime(m_encoded + ticks);
}
/**
* Get the number of ticks
* @returns the number of ticks
*/
long long Ticks() const
{
return m_encoded;
@ -361,7 +441,7 @@ public:
void FromTicks(int& year, int& month, int& day) const
{
int totalDays = m_encoded / TicksPerDay;
int totalDays = static_cast<int>(m_encoded / TicksPerDay);
/*
* number of 400 year cycles
@ -452,36 +532,60 @@ public:
return day;
}
/**
* Hour component
* @returns the hour component
*/
int Hour() const
{
return m_encoded % TicksPerDay / TicksPerHour;
return static_cast<int>(m_encoded % TicksPerDay / TicksPerHour);
}
/**
* Minute component
* @returns the minute component
*/
int Minute() const
{
return m_encoded % TicksPerHour / TicksPerMinute;
return static_cast<int>(m_encoded % TicksPerHour / TicksPerMinute);
}
/**
* Second component
* @returns the Second component
*/
int Second() const
{
return m_encoded % TicksPerMinute / TicksPerSecond;
return static_cast<int>(m_encoded % TicksPerMinute / TicksPerSecond);
}
/**
* Microsecond component
* @returns the microsecond component
*/
int Microsecond() const
{
return m_encoded % TicksPerSecond / TicksPerMicrosecond;
return static_cast<int>(m_encoded % TicksPerSecond / TicksPerMicrosecond);
}
double Julian() const
/**
* Convert to a julian date
* @returns the julian date
*/
double ToJulian() const
{
TimeSpan ts = TimeSpan(Ticks());
return ts.TotalDays() + 1721425.5;
}
/**
* Convert to greenwich sidereal time
* @returns the greenwich sidereal time
*/
double ToGreenwichSiderealTime() const
{
// t = Julian centuries from 2000 Jan. 1 12h UT1
const double t = (Julian() - 2451545.0) / 36525.0;
const double t = (ToJulian() - 2451545.0) / 36525.0;
// Rotation angle in arcseconds
double theta = 67310.54841
@ -493,7 +597,12 @@ public:
return Util::WrapTwoPI(Util::DegreesToRadians(theta / 240.0));
}
double ToLocalMeanSiderealTime(const double& lon) const
/**
* Convert to local mean sidereal time (GMST plus the observer's longitude)
* @param[in] lon observers longitude
* @returns the local mean sidereal time
*/
double ToLocalMeanSiderealTime(const double lon) const
{
return Util::WrapTwoPI(ToGreenwichSiderealTime() + lon);
}

View File

@ -1,11 +1,11 @@
#ifndef DECAYEDEXCEPTION_H_
#define DECAYEDEXCEPTION_H_
#include <exception>
#include "DateTime.h"
#include "Vector.h"
#include <exception>
class DecayedException : public std::exception
{
public:
@ -38,7 +38,7 @@ public:
/**
* @returns the date
*/
DateTime GetDateTime() const
DateTime Decayed() const
{
return _dt;
}
@ -46,7 +46,7 @@ public:
/**
* @returns the position
*/
Vector GetPosition() const
Vector Position() const
{
return _pos;
}
@ -54,7 +54,7 @@ public:
/**
* @returns the velocity
*/
Vector GetVelocity() const
Vector Velocity() const
{
return _vel;
}

View File

@ -39,7 +39,7 @@ void Eci::ToEci(const DateTime& dt, const CoordGeodetic &geo)
m_position.x = achcp * cos(theta);
m_position.y = achcp * sin(theta);
m_position.z = (kXKMPER * s + geo.altitude) * sin(geo.latitude);
m_position.w = m_position.GetMagnitude();
m_position.w = m_position.Magnitude();
/*
* X velocity in km/s
@ -50,7 +50,7 @@ void Eci::ToEci(const DateTime& dt, const CoordGeodetic &geo)
m_velocity.x = -mfactor * m_position.y;
m_velocity.y = mfactor * m_position.x;
m_velocity.z = 0.0;
m_velocity.w = m_velocity.GetMagnitude();
m_velocity.w = m_velocity.Magnitude();
}
/**
@ -85,5 +85,5 @@ CoordGeodetic Eci::ToGeodetic() const
const double alt = r / cos(lat) - kXKMPER * c;
return CoordGeodetic(lat, lon, alt);
return CoordGeodetic(lat, lon, alt, true);
}

View File

@ -98,7 +98,7 @@ public:
/**
* @returns the position
*/
Vector GetPosition() const
Vector Position() const
{
return m_position;
}
@ -106,7 +106,7 @@ public:
/**
* @returns the velocity
*/
Vector GetVelocity() const
Vector Velocity() const
{
return m_velocity;
}

1
libsgp4/Globals.cpp Normal file
View File

@ -0,0 +1 @@
#include "Globals.h"

View File

@ -1,12 +1,17 @@
lib_LIBRARIES = libsgp4.a
libsgp4_a_SOURCES = Tle.cpp \
OrbitalElements.cpp \
Observer.cpp \
Util.cpp \
libsgp4_a_SOURCES = \
CoordGeodetic.cpp \
CoordTopographic.cpp \
DateTime.cpp \
Eci.cpp \
Globals.cpp \
Observer.cpp \
OrbitalElements.cpp \
SGP4.cpp \
TimeSpan.cpp \
DateTime.cpp
Tle.cpp \
Util.cpp \
Vector.cpp
include_HEADERS = CoordGeodetic.h \
Eci.h \
OrbitalElements.h \

View File

@ -16,10 +16,10 @@ CoordTopographic Observer::GetLookAngle(const Eci &eci)
/*
* calculate differences
*/
Vector range_rate = eci.GetVelocity() - m_eci.GetVelocity();
Vector range = eci.GetPosition() - m_eci.GetPosition();
Vector range_rate = eci.Velocity() - m_eci.Velocity();
Vector range = eci.Position() - m_eci.Position();
range.w = range.GetMagnitude();
range.w = range.Magnitude();
/*
* Calculate Local Mean Sidereal Time for observers longitude

View File

@ -698,7 +698,7 @@ void SGP4::DeepSpaceInitialise(
/*
* initialize lunar / solar terms
*/
const double jday = elements_.Epoch().Julian() - kEPOCH_JAN1_12H_2000;
const double jday = elements_.Epoch().ToJulian() - kEPOCH_JAN1_12H_2000;
const double xnodce = 4.5236020 - 9.2422029e-4 * jday;
const double xnodce_temp = fmod(xnodce, kTWOPI);

View File

@ -7,6 +7,12 @@
#include "SatelliteException.h"
#include "DecayedException.h"
/**
* @mainpage
*
* This documents the SGP4 tracking library.
*/
class SGP4
{
public:

View File

@ -1,6 +1,11 @@
#ifndef TIMESPAN_H_
#define TIMESPAN_H_
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cmath>
namespace
{
static const long long TicksPerDay = 86400000000LL;
@ -71,34 +76,34 @@ public:
return m_ticks == ts.m_ticks;
}
int Days()
int Days() const
{
return m_ticks / TicksPerDay;
return static_cast<int>(m_ticks / TicksPerDay);
}
int Hours()
int Hours() const
{
return (m_ticks % TicksPerDay / TicksPerHour);
return static_cast<int>(m_ticks % TicksPerDay / TicksPerHour);
}
int Minutes() const
{
return (m_ticks % TicksPerHour / TicksPerMinute);
return static_cast<int>(m_ticks % TicksPerHour / TicksPerMinute);
}
int Seconds() const
{
return (m_ticks % TicksPerMinute / TicksPerSecond);
return static_cast<int>(m_ticks % TicksPerMinute / TicksPerSecond);
}
int Milliseconds() const
{
return (m_ticks % TicksPerSecond / TicksPerMillisecond);
return static_cast<int>(m_ticks % TicksPerSecond / TicksPerMillisecond);
}
int Microseconds() const
{
return (m_ticks % TicksPerSecond / TicksPerMicrosecond);
return static_cast<int>(m_ticks % TicksPerSecond / TicksPerMicrosecond);
}
long long Ticks() const
@ -108,32 +113,60 @@ public:
double TotalDays() const
{
return m_ticks / static_cast<double>(TicksPerDay);
return static_cast<double>(m_ticks) / TicksPerDay;
}
double TotalHours() const
{
return m_ticks / static_cast<double>(TicksPerHour);
return static_cast<double>(m_ticks) / TicksPerHour;
}
double TotalMinutes() const
{
return m_ticks / static_cast<double>(TicksPerMinute);
return static_cast<double>(m_ticks) / TicksPerMinute;
}
double TotalSeconds() const
{
return m_ticks / static_cast<double>(TicksPerSecond);
return static_cast<double>(m_ticks) / TicksPerSecond;
}
double TotalMilliseconds() const
{
return m_ticks / static_cast<double>(TicksPerMillisecond);
return static_cast<double>(m_ticks) / TicksPerMillisecond;
}
double TotalMicroseconds() const
{
return m_ticks / static_cast<double>(TicksPerMicrosecond);
return static_cast<double>(m_ticks) / TicksPerMicrosecond;
}
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::setfill('0');
if (m_ticks < 0)
{
ss << '-';
}
if (Days() != 0)
{
ss << std::setw(2) << std::abs(Days()) << '.';
}
ss << std::setw(2) << std::abs(Hours()) << ':';
ss << std::setw(2) << std::abs(Minutes()) << ':';
ss << std::setw(2) << std::abs(Seconds());
if (Microseconds() != 0)
{
ss << '.' << std::setw(6) << std::abs(Microseconds());
}
return ss.str();
}
private:
@ -151,6 +184,11 @@ private:
}
};
inline std::ostream& operator<<(std::ostream& strm, const TimeSpan& t)
{
return strm << t.ToString();
}
inline TimeSpan operator+(const TimeSpan& ts1, const TimeSpan& ts2)
{
return ts1.Add(ts2);

View File

@ -140,7 +140,7 @@ void Tle::Initialize()
*/
bool Tle::IsValidLineLength(const std::string& str)
{
return str.length() == GetLineLength() ? true : false;
return str.length() == LineLength() ? true : false;
}
/**

View File

@ -77,7 +77,7 @@ public:
* Get the satellite name
* @returns the satellite name
*/
std::string GetName() const
std::string Name() const
{
return name_;
}
@ -86,7 +86,7 @@ public:
* Get the first line of the tle
* @returns the first line of the tle
*/
std::string GetLine1() const
std::string Line1() const
{
return line_one_;
}
@ -95,7 +95,7 @@ public:
* Get the second line of the tle
* @returns the second line of the tle
*/
std::string GetLine2() const
std::string Line2() const
{
return line_two_;
}
@ -253,7 +253,7 @@ public:
* Get the expected tle line length
* @returns the tle line length
*/
static unsigned int GetLineLength()
static unsigned int LineLength()
{
return TLE_LEN_LINE_DATA;
}

1
libsgp4/Vector.cpp Normal file
View File

@ -0,0 +1 @@
#include "Vector.h"

View File

@ -97,7 +97,7 @@ public:
* Calculates the magnitude of the vector
* @returns magnitude of the vector
*/
double GetMagnitude() const
double Magnitude() const
{
return sqrt(x * x + y * y + z * z);
}

View File

@ -15,6 +15,7 @@ struct PassDetails
double max_elevation;
};
#if 0
double FindMaxElevation(
const CoordGeodetic& user_geo,
SGP4& sgp4,
@ -101,6 +102,88 @@ double FindMaxElevation(
return max_elevation;
}
#endif
double FindMaxElevation(
const CoordGeodetic& user_geo,
SGP4& sgp4,
const DateTime& aos,
const DateTime& los)
{
Observer obs(user_geo);
bool running;
int cnt;
double time_step = (los - aos).TotalSeconds() / 9.0;
DateTime current_time(aos); //! current time
DateTime time1(aos); //! start time of search period
DateTime time2(los); //! end time of search period
double max_elevation; //! max elevation
running = true;
cnt = 0;
do
{
running = true;
max_elevation = -99999999999999.0;
while (running && current_time < time2)
{
/*
* find position
*/
Eci eci = sgp4.FindPosition(current_time);
CoordTopographic topo = obs.GetLookAngle(eci);
if (topo.elevation > max_elevation)
{
/*
* still going up
*/
max_elevation = topo.elevation;
/*
* move time along
*/
current_time = current_time.AddSeconds(time_step);
if (current_time > time2)
{
/*
* dont go past end time
*/
current_time = time2;
}
}
else
{
/*
* stop
*/
running = false;
}
}
/*
* make start time to 2 time steps back
*/
time1 = current_time.AddSeconds(-2.0 * time_step);
/*
* make end time to current time
*/
time2 = current_time;
/*
* current time to start time
*/
current_time = time1;
/*
* recalculate time step
*/
time_step = (time2 - time1).TotalSeconds() / 9.0;
}
while (time_step > 1.0);
return max_elevation;
}
DateTime FindCrossingPoint(
const CoordGeodetic& user_geo,
@ -111,25 +194,18 @@ DateTime FindCrossingPoint(
{
Observer obs(user_geo);
bool searching = true;
int cnt = 0;
bool running;
int cnt;
DateTime time1(initial_time1);
DateTime time2(initial_time2);
DateTime middle_time;
double diff = (time2 - time1).TotalSeconds();
if (finding_aos)
{
diff = std::floor(diff);
}
else
{
diff = std::ceil(diff);
}
DateTime middle_time(time1.AddSeconds(diff));
while (searching && cnt < 25)
running = true;
cnt = 0;
while (running && cnt++ < 16)
{
middle_time = time1.AddSeconds((time2 - time1).TotalSeconds() / 2.0);
/*
* calculate satellite position
*/
@ -138,6 +214,9 @@ DateTime FindCrossingPoint(
if (topo.elevation > 0.0)
{
/*
* satellite above horizon
*/
if (finding_aos)
{
time2 = middle_time;
@ -159,28 +238,41 @@ DateTime FindCrossingPoint(
}
}
/*
* when two times are within a second, stop
*/
if ((time2 - time1).TotalSeconds() < 1.5)
if ((time2 - time1).TotalSeconds() < 1.0)
{
searching = false;
/*
* two times are within a second, stop
*/
running = false;
/*
* remove microseconds
*/
int us = middle_time.Microsecond();
middle_time = middle_time.AddMicroseconds(-us);
/*
* step back into the pass by 1 second
*/
middle_time = middle_time.AddSeconds(finding_aos ? 1 : -1);
}
}
/*
* go back/forward 1second until below the horizon
*/
running = true;
cnt = 0;
while (running && cnt++ < 6)
{
Eci eci = sgp4.FindPosition(middle_time);
CoordTopographic topo = obs.GetLookAngle(eci);
if (topo.elevation > 0)
{
middle_time = middle_time.AddSeconds(finding_aos ? -1 : 1);
}
else
{
diff = (time2 - time1).TotalSeconds();
if (finding_aos)
{
diff = std::floor(diff);
}
else
{
diff = std::ceil(diff);
}
middle_time = time1.AddSeconds(diff);
running = false;
}
cnt++;
}
return middle_time;
@ -201,30 +293,30 @@ std::list<struct PassDetails> GeneratePassList(
DateTime los_time;
bool found_aos = false;
bool found_los = false;
DateTime previous_time(start_time);
DateTime current_time(start_time);
while (current_time < end_time)
{
bool end_of_pass = false;
/*
* calculate satellite position
*/
Eci eci = sgp4.FindPosition(current_time);
CoordTopographic topo = obs.GetLookAngle(eci);
std::cout << std::fixed << current_time << " " << topo.elevation << std::endl;
if (topo.elevation > 0.0)
if (!found_aos && topo.elevation > 0.0)
{
/*
* satellite is above horizon
* aos hasnt occured yet, but the satellite is now above horizon
* this must have occured within the last time_step
*/
if (start_time == current_time)
{
/*
* satellite was already above the horizon at the start time,
* satellite was already above the horizon at the start,
* so use the start time
*/
aos_time = start_time;
@ -241,15 +333,18 @@ std::list<struct PassDetails> GeneratePassList(
current_time,
true);
}
found_aos = true;
found_los = false;
}
else if (found_aos)
else if (found_aos && topo.elevation < 0.0)
{
found_aos = false;
/*
* satellite now below horizon and we have an AOS, so record the
* pass
* end of pass, so move along more than time_step
*/
end_of_pass = true;
/*
* already have the aos, but now the satellite is below the horizon,
* so find the los
*/
los_time = FindCrossingPoint(
user_geo,
@ -258,9 +353,6 @@ std::list<struct PassDetails> GeneratePassList(
current_time,
false);
found_aos = false;
found_los = true;
struct PassDetails pd;
pd.aos = aos_time;
pd.los = los_time;
@ -273,14 +365,17 @@ std::list<struct PassDetails> GeneratePassList(
pass_list.push_back(pd);
}
/*
* save current time
*/
previous_time = current_time;
if (found_los)
if (end_of_pass)
{
/*
* at the end of the pass move the time along by 20mins
* at the end of the pass move the time along by 30mins
*/
current_time = current_time + TimeSpan(0, 20, 0);
current_time = current_time + TimeSpan(0, 30, 0);
}
else
{
@ -297,8 +392,6 @@ std::list<struct PassDetails> GeneratePassList(
*/
current_time = end_time;
}
found_los = false;
};
if (found_aos)
@ -310,7 +403,7 @@ std::list<struct PassDetails> GeneratePassList(
struct PassDetails pd;
pd.aos = aos_time;
pd.los = end_time;
pd.max_elevation = FindMaxElevation(user_geo, sgp4, aos_time, los_time);
pd.max_elevation = FindMaxElevation(user_geo, sgp4, aos_time, end_time);
pass_list.push_back(pd);
}
@ -318,24 +411,23 @@ std::list<struct PassDetails> GeneratePassList(
return pass_list;
}
int main() {
int main()
{
CoordGeodetic geo(51.507406923983446, -0.12773752212524414, 0.05);
Tle tle("UK-DMC 2 ",
"1 25544U 98067A 12285.65009259 .00017228 00000-0 30018-3 0 4501",
"2 25544 051.6477 262.7396 0017757 155.0745 185.1532 15.50683239796101");
Tle tle("GALILEO-PFM (GSAT0101) ",
"1 37846U 11060A 12293.53312491 .00000049 00000-0 00000-0 0 1435",
"2 37846 54.7963 119.5777 0000994 319.0618 40.9779 1.70474628 6204");
SGP4 sgp4(tle);
std::cout << tle << std::endl;
/*
* generate 1 day schedule
* generate 7 day schedule
*/
DateTime start_date = DateTime::Now();
DateTime end_date(start_date.AddDays(1.0));
DateTime start_date = DateTime::Now(true);
DateTime end_date(start_date.AddDays(7.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;
@ -351,16 +443,22 @@ int main() {
}
else
{
itr = pass_list.begin();
std::stringstream ss;
ss << std::right << std::setprecision(1) << std::fixed;
std::list<struct PassDetails>::const_iterator itr = pass_list.begin();
do
{
std::cout
<< "AOS: " << itr->aos
ss << "AOS: " << itr->aos
<< ", LOS: " << itr->los
<< ", Max El: " << Util::RadiansToDegrees(itr->max_elevation)
<< ", Max El: " << std::setw(4) << Util::RadiansToDegrees(itr->max_elevation)
<< ", Duration: " << (itr->los - itr->aos)
<< std::endl;
}
while (++itr != pass_list.end());
std::cout << ss.str();
}
return 0;

View File

@ -47,8 +47,8 @@ void RunTle(Tle tle, double start, double end, double inc)
}
Eci eci = model.FindPosition(tsince);
position = eci.GetPosition();
velocity = eci.GetVelocity();
position = eci.Position();
velocity = eci.Velocity();
}
catch (SatelliteException& e)
{
@ -60,8 +60,8 @@ void RunTle(Tle tle, double start, double end, double inc)
{
std::cerr << e.what() << std::endl;
position = e.GetPosition();
velocity = e.GetVelocity();
position = e.Position();
velocity = e.Velocity();
if (!first_run)
{
@ -182,9 +182,9 @@ void RunTest(const char* infile)
{
try
{
if (line.length() >= Tle::GetLineLength())
if (line.length() >= Tle::LineLength())
{
//Tle::IsValidLine(line.substr(0, Tle::GetLineLength()), 1);
//Tle::IsValidLine(line.substr(0, Tle::LineLength()), 1);
/*
* store line and now read in second line
*/
@ -208,15 +208,15 @@ void RunTest(const char* infile)
* split line, first 69 is the second line of the tle
* the rest is the test parameters, if there is any
*/
line2 = line.substr(0, Tle::GetLineLength());
line2 = line.substr(0, Tle::LineLength());
double start = 0.0;
double end = 1440.0;
double inc = 120.0;
if (line.length() > 69)
{
std::vector<std::string> tokens;
parameters = line.substr(Tle::GetLineLength() + 1,
line.length() - Tle::GetLineLength());
parameters = line.substr(Tle::LineLength() + 1,
line.length() - Tle::LineLength());
tokenize(parameters, tokens);
if (tokens.size() >= 3)
{
@ -231,9 +231,9 @@ void RunTest(const char* infile)
*/
try
{
if (line.length() >= Tle::GetLineLength())
if (line.length() >= Tle::LineLength())
{
//Tle::IsValidLine(line.substr(0, Tle::GetLineLength()), 2);
//Tle::IsValidLine(line.substr(0, Tle::LineLength()), 2);
Tle tle("Test", line1, line2);
RunTle(tle, start, end, inc);
}

View File

@ -8,11 +8,13 @@
int main()
{
Observer obs(51.507406923983446, -0.12773752212524414, 0.05);
Tle tle = Tle("MASAT 1 ",
"1 25544U 98067A 12285.65009259 .00017228 00000-0 30018-3 0 4501",
"2 25544 051.6477 262.7396 0017757 155.0745 185.1532 15.50683239796101");
Tle tle = Tle("UK-DMC 2 ",
"1 35683U 09041C 12289.23158813 .00000484 00000-0 89219-4 0 5863",
"2 35683 98.0221 185.3682 0001499 100.5295 259.6088 14.69819587172294");
SGP4 sgp4(tle);
std::cout << tle << std::endl;
while (true)
{
/*