增加了基于SPG4模型与两行根数的,卫星轨道点生成代码

pull/13/head
陈增辉 2025-03-08 17:24:38 +08:00
parent c55953aa7c
commit 44a5db3168
39 changed files with 5653 additions and 0 deletions

View File

@ -38,6 +38,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RasterMainWidgetGUI", "Rast
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageshowTool", "ImageshowTool\ImageshowTool.vcxproj", "{8C8CA066-A93A-4098-9A46-B855EFEAADF2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPG4Tool", "SPG4Tool\SPG4Tool.vcxproj", "{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@ -168,6 +170,18 @@ Global
{8C8CA066-A93A-4098-9A46-B855EFEAADF2}.Release|x64.Build.0 = Release|x64
{8C8CA066-A93A-4098-9A46-B855EFEAADF2}.Release|x86.ActiveCfg = Release|x64
{8C8CA066-A93A-4098-9A46-B855EFEAADF2}.Release|x86.Build.0 = Release|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Debug|ARM.ActiveCfg = Debug|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Debug|ARM.Build.0 = Debug|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Debug|x64.ActiveCfg = Debug|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Debug|x64.Build.0 = Debug|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Debug|x86.ActiveCfg = Debug|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Debug|x86.Build.0 = Debug|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Release|ARM.ActiveCfg = Release|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Release|ARM.Build.0 = Release|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Release|x64.ActiveCfg = Release|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Release|x64.Build.0 = Release|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Release|x86.ActiveCfg = Release|x64
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}.Release|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -181,6 +195,7 @@ Global
{B8B40C54-F7FE-4809-B6FB-8BC014570D7B} = {2768F9D6-D410-4E88-A479-8336DAF97072}
{E56B3878-A3DC-41A4-ABF3-B628816D0D64} = {6505E2BA-06A2-447B-BC85-8CF1A81359BC}
{8C8CA066-A93A-4098-9A46-B855EFEAADF2} = {2768F9D6-D410-4E88-A479-8336DAF97072}
{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E} = {2768F9D6-D410-4E88-A479-8336DAF97072}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {179F0A62-C631-4667-AD03-3780ADE09F41}

135
SPG4Tool/SPG4Function.cpp Normal file
View File

@ -0,0 +1,135 @@
#include "SPG4Function.h"
#include <Tle.h>
#include <SGP4.h>
#include <Observer.h>
#include <CoordGeodetic.h>
#include <CoordTopocentric.h>
#include <list>
#include <string>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdlib>
std::vector<SatelliteAntPos> RunTle(libsgp4::Tle tle, double start, double end, double inc, bool printfinfoflag)
{
std::vector<SatelliteAntPos> resultpos(0);
double current = start;
libsgp4::SGP4 model(tle);
bool running = true;
bool first_run = true;
std::cout << std::setprecision(0) << tle.NoradNumber() << " xx"
<< std::endl;
while (running)
{
bool error = false;
libsgp4::Vector position;
libsgp4::Vector velocity;
double tsince;
try
{
if (first_run && current != 0.0)
{
/*
* make sure first run is always as zero
*/
tsince = 0.0;
}
else
{
/*
* otherwise run as normal
*/
tsince = current;
}
libsgp4::Eci eci = model.FindPosition(tsince);
position = eci.Position();
velocity = eci.Velocity();
}
catch (libsgp4::SatelliteException& e)
{
std::cerr << e.what() << std::endl;
error = true;
running = false;
}
catch (libsgp4::DecayedException& e)
{
std::cerr << e.what() << std::endl;
position = e.Position();
velocity = e.Velocity();
if (!first_run)
{
// print out position on first run
error = true;
}
running = false;
}
if (!error)
{
SatelliteAntPos antpos{};
antpos.time = tsince;
antpos.Px = position.x;
antpos.Py = position.y;
antpos.Pz = position.z;
antpos.Vx = velocity.z;
antpos.Vy = velocity.z;
antpos.Vz = velocity.z;
resultpos.push_back(antpos);
if (printfinfoflag) {
std::cout << std::setprecision(8) << std::fixed;
std::cout.width(17);
std::cout << tsince << " ";
std::cout.width(16);
std::cout << position.x << " ";
std::cout.width(16);
std::cout << position.y << " ";
std::cout.width(16);
std::cout << position.z << " ";
std::cout << std::setprecision(9) << std::fixed;
std::cout.width(14);
std::cout << velocity.x << " ";
std::cout.width(14);
std::cout << velocity.y << " ";
std::cout.width(14);
std::cout << velocity.z << std::endl;
}
}
if ((first_run && current == 0.0) || !first_run)
{
if (current == end)
{
running = false;
}
else if (current + inc > end)
{
current = end;
}
else
{
current += inc;
}
}
first_run = false;
}
return resultpos;
}

17
SPG4Tool/SPG4Function.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#ifndef __SPG4FUNCTION__H__
#define __SPG4FUNCTION__H__
#include "Tle.h"
#include "SGP4.h"
#include "Observer.h"
#include "BaseConstVariable.h"
#include <vector>
//void RunTle(libsgp4::Tle tle, double start, double end, double inc);
std::vector<SatelliteAntPos> RunTle(libsgp4::Tle tle, double start, double end, double inc,bool printfinfoflag=false);
#endif

145
SPG4Tool/SPG4Tool.vcxproj Normal file
View File

@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{80A5854F-6F80-4EC2-9F73-84E0F4DB8D7E}</ProjectGuid>
<Keyword>QtVS_v304</Keyword>
<WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">10.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">10.0</WindowsTargetPlatformVersion>
<QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')">
<Import Project="$(QtMsBuild)\qt_defaults.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
<QtInstall>tools_qt5</QtInstall>
<QtModules>core</QtModules>
<QtBuildConfig>debug</QtBuildConfig>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
<QtInstall>tools_qt5</QtInstall>
<QtModules>core</QtModules>
<QtBuildConfig>release</QtBuildConfig>
</PropertyGroup>
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
<Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
</Target>
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="Shared" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(QtMsBuild)\Qt.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(QtMsBuild)\Qt.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<IncludePath>.\libsgp4;..\BaseCommonLibrary\BaseTool;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration">
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration">
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="libsgp4\CoordGeodetic.cc" />
<ClCompile Include="libsgp4\CoordTopocentric.cc" />
<ClCompile Include="libsgp4\DateTime.cc" />
<ClCompile Include="libsgp4\DecayedException.cc" />
<ClCompile Include="libsgp4\Eci.cc" />
<ClCompile Include="libsgp4\Globals.cc" />
<ClCompile Include="libsgp4\Observer.cc" />
<ClCompile Include="libsgp4\OrbitalElements.cc" />
<ClCompile Include="libsgp4\SatelliteException.cc" />
<ClCompile Include="libsgp4\SGP4.cc" />
<ClCompile Include="libsgp4\SolarPosition.cc" />
<ClCompile Include="libsgp4\TimeSpan.cc" />
<ClCompile Include="libsgp4\Tle.cc" />
<ClCompile Include="libsgp4\TleException.cc" />
<ClCompile Include="libsgp4\Util.cc" />
<ClCompile Include="libsgp4\Vector.cc" />
<ClCompile Include="SPG4Toolmain.cpp" />
<ClCompile Include="SPG4Function.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="libsgp4\CoordGeodetic.h" />
<ClInclude Include="libsgp4\CoordTopocentric.h" />
<ClInclude Include="libsgp4\DateTime.h" />
<ClInclude Include="libsgp4\DecayedException.h" />
<ClInclude Include="libsgp4\Eci.h" />
<ClInclude Include="libsgp4\Globals.h" />
<ClInclude Include="libsgp4\Observer.h" />
<ClInclude Include="libsgp4\OrbitalElements.h" />
<ClInclude Include="libsgp4\SatelliteException.h" />
<ClInclude Include="libsgp4\SGP4.h" />
<ClInclude Include="libsgp4\SolarPosition.h" />
<ClInclude Include="libsgp4\TimeSpan.h" />
<ClInclude Include="libsgp4\Tle.h" />
<ClInclude Include="libsgp4\TleException.h" />
<ClInclude Include="libsgp4\Util.h" />
<ClInclude Include="libsgp4\Vector.h" />
<ClInclude Include="SPG4Function.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BaseCommonLibrary\BaseCommonLibrary.vcxproj">
<Project>{872ecd6f-30e3-4a1b-b17c-15e87d373ff6}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />
</ImportGroup>
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Form Files">
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
<Extensions>ui</Extensions>
</Filter>
<Filter Include="Translation Files">
<UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier>
<Extensions>ts</Extensions>
</Filter>
<Filter Include="libsgp4">
<UniqueIdentifier>{fd21014a-ae49-484d-bbcf-92b5b994c075}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SPG4Toolmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libsgp4\CoordGeodetic.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\CoordTopocentric.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\DateTime.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\DecayedException.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\Eci.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\Globals.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\Observer.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\OrbitalElements.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\SatelliteException.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\SGP4.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\SolarPosition.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\TimeSpan.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\Tle.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\TleException.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\Util.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="libsgp4\Vector.cc">
<Filter>libsgp4</Filter>
</ClCompile>
<ClCompile Include="SPG4Function.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="libsgp4\CoordGeodetic.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\CoordTopocentric.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\DateTime.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\DecayedException.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\Eci.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\Globals.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\Observer.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\OrbitalElements.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\SatelliteException.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\SGP4.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\SolarPosition.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\TimeSpan.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\Tle.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\TleException.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\Util.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="libsgp4\Vector.h">
<Filter>libsgp4</Filter>
</ClInclude>
<ClInclude Include="SPG4Function.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

38
SPG4Tool/SPG4Toolmain.cpp Normal file
View File

@ -0,0 +1,38 @@
#include <QtCore/QCoreApplication>
#include <iostream>
#include <fstream>
#include "Tle.h"
#include "SGP4.h"
#include "Observer.h"
#include "CoordGeodetic.h"
#include "CoordTopocentric.h"
#include <string>
#include "SPG4Function.h"
/**
½̽ËĺÅ01ÐÇÎÀÐǹìµÀ
1 57624U 23120A 25064.58152700 -.00000191 00000-0 00000+0 0 9998
2 57624 15.4792 205.4597 0004587 123.7538 133.1804 1.00272901 5837
*/
//
//int main(int argc, char *argv[])
//{
//
// std::string line1="1 57624U 23120A 25064.58152700 -.00000191 00000-0 00000+0 0 9998";
// std::string line2="2 57624 15.4792 205.4597 0004587 123.7538 133.1804 1.00272901 5837";
//
// libsgp4::Tle tle("GF3", line1, line2);
//
// double start = 0;
// double end = 10;
// double inc = 1;
//
// RunTle(tle, start, end, inc);
// //QCoreApplication a(argc, argv);
//
// //return a.exec();
//}

View File

@ -0,0 +1,41 @@
set(SRCS
CoordGeodetic.cc
CoordTopocentric.cc
DateTime.cc
DecayedException.cc
Eci.cc
Globals.cc
Observer.cc
OrbitalElements.cc
SGP4.cc
SatelliteException.cc
SolarPosition.cc
TimeSpan.cc
Tle.cc
TleException.cc
Util.cc
Vector.cc)
set(INCS
CoordGeodetic.h
CoordTopocentric.h
DateTime.h
DecayedException.h
Eci.h
Globals.h
Observer.h
OrbitalElements.h
SatelliteException.h
SGP4.h
SolarPosition.h
TimeSpan.h
TleException.h
Tle.h
Util.h
Vector.h
)
add_library(sgp4 STATIC ${SRCS} ${INCS})
add_library(sgp4s SHARED ${SRCS} ${INCS})
install( TARGETS sgp4s LIBRARY DESTINATION lib )
install( FILES ${INCS} DESTINATION include/libsgp4 )

View File

@ -0,0 +1,18 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "CoordGeodetic.h"

View File

@ -0,0 +1,126 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "Util.h"
#include <string>
#include <sstream>
#include <iomanip>
namespace libsgp4
{
/**
* @brief Stores a geodetic location (latitude, longitude, altitude).
*
* Internally the values are stored in radians and kilometres.
*/
struct CoordGeodetic
{
public:
/**
* Default constructor
*/
CoordGeodetic() = default;
/**
* Constructor
* @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 lat,
double lon,
double alt,
bool is_radians = false)
{
if (is_radians)
{
latitude = lat;
longitude = lon;
}
else
{
latitude = Util::DegreesToRadians(lat);
longitude = Util::DegreesToRadians(lon);
}
altitude = alt;
}
/**
* Copy constructor
* @param[in] geo object to copy from
*/
CoordGeodetic(const CoordGeodetic& geo)
{
latitude = geo.latitude;
longitude = geo.longitude;
altitude = geo.altitude;
}
/**
* Assignment operator
* @param[in] geo object to copy from
*/
CoordGeodetic& operator=(const CoordGeodetic& geo)
{
if (this != &geo)
{
latitude = geo.latitude;
longitude = geo.longitude;
altitude = geo.altitude;
}
return *this;
}
/**
* Dump this object to a string
* @returns string
*/
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(3);
ss << "Lat: " << std::setw(8) << Util::RadiansToDegrees(latitude);
ss << ", Lon: " << std::setw(8) << Util::RadiansToDegrees(longitude);
ss << ", Alt: " << std::setw(10) << altitude;
return ss.str();
}
/** latitude in radians (-PI >= latitude < PI) */
double latitude{};
/** latitude in radians (-PI/2 >= latitude <= PI/2) */
double longitude{};
/** altitude in kilometers */
double altitude{};
};
/**
* Dump a Coordgeodetic to a stream
* @param[in,out] strm stream to output to
* @param[in] g the CoordGeodetic to print
*/
inline std::ostream& operator<<(std::ostream& strm, const CoordGeodetic& g)
{
return strm << g.ToString();
}
} // namespace libsgp4

View File

@ -0,0 +1,18 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "CoordTopocentric.h"

View File

@ -0,0 +1,122 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "Util.h"
#include <string>
#include <sstream>
#include <iomanip>
namespace libsgp4
{
/**
* @brief Stores a topocentric location (azimuth, elevation, range and range
* rate).
*
* Azimuth and elevation are stored in radians. Range in kilometres. Range
* rate in kilometres/second.
*/
struct CoordTopocentric
{
public:
/**
* Default constructor
*/
CoordTopocentric() = default;
/**
* Constructor
* @param[in] az azimuth in radians
* @param[in] el elevation in radians
* @param[in] rnge range in kilometers
* @param[in] rnge_rate range rate in kilometers per second
*/
CoordTopocentric(
double az,
double el,
double rnge,
double rnge_rate)
: azimuth(az)
, elevation(el)
, range(rnge)
, range_rate(rnge_rate)
{
}
/**
* Copy constructor
* @param[in] topo object to copy from
*/
CoordTopocentric(const CoordTopocentric& topo)
{
azimuth = topo.azimuth;
elevation = topo.elevation;
range = topo.range;
range_rate = topo.range_rate;
}
/**
* Assignment operator
* @param[in] topo object to copy from
*/
CoordTopocentric& operator=(const CoordTopocentric& topo)
{
if (this != &topo)
{
azimuth = topo.azimuth;
elevation = topo.elevation;
range = topo.range;
range_rate = topo.range_rate;
}
return *this;
}
/**
* Dump this object to a string
* @returns string
*/
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(3);
ss << "Az: " << std::setw(8) << Util::RadiansToDegrees(azimuth);
ss << ", El: " << std::setw(8) << Util::RadiansToDegrees(elevation);
ss << ", Rng: " << std::setw(10) << range;
ss << ", Rng Rt: " << std::setw(7) << range_rate;
return ss.str();
}
/** azimuth in radians */
double azimuth{};
/** elevations in radians */
double elevation{};
/** range in kilometers */
double range{};
/** range rate in kilometers per second */
double range_rate{};
};
inline std::ostream& operator<<(std::ostream& strm, const CoordTopocentric& t)
{
return strm << t.ToString();
}
} // namespace libsgp4

View File

@ -0,0 +1,149 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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

721
SPG4Tool/libsgp4/DateTime.h Normal file
View File

@ -0,0 +1,721 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <iomanip>
#include <iostream>
#include <sstream>
#include <chrono>
#include <algorithm>
#include <cassert>
#include "TimeSpan.h"
#include "Util.h"
namespace libsgp4
{
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}
};
}
/**
* @brief Represents an instance in time.
*/
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
*/
explicit DateTime(int64_t ticks)
: m_encoded(ticks)
{
}
/**
* Constructor
* @param[in] year the year
* @param[in] doy the day of the year
*/
DateTime(unsigned int year, double doy)
{
m_encoded = TimeSpan(
static_cast<int64_t>(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);
}
/**
* 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
*/
DateTime(int year, int month, int day, int hour, int minute, int second, int microsecond)
{
Initialise(year, month, day, hour, minute, second, microsecond);
}
/**
* Initialise to the given data and time.
* @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,
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)
{
assert(false && "Invalid date");
}
m_encoded = TimeSpan(
AbsoluteDays(year, month, day),
hour,
minute,
second,
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 useMicroseconds = false)
{
using namespace std::chrono;
if (useMicroseconds)
{
return DateTime(UnixEpoch +
duration_cast<microseconds>(system_clock::now()
.time_since_epoch()).count() * TicksPerMicrosecond);
}
else
{
return DateTime(UnixEpoch +
duration_cast<seconds>(system_clock::now()
.time_since_epoch()).count() * TicksPerSecond);
}
}
/**
* 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))
{
assert(false && "Invalid year");
}
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;
if (year < 1 || year > 9999)
{
valid = false;
}
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;
if (IsValidYear(year))
{
if (month < 1 || month > 12)
{
valid = false;
}
}
else
{
valid = false;
}
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;
if (IsValidYearMonth(year, month))
{
if (day < 1 || day > DaysInMonth(year, month))
{
valid = false;
}
}
else
{
valid = false;
}
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))
{
assert(false && "Invalid year and month");
}
const int* daysInMonthPtr;
if (IsLeapYear(year))
{
daysInMonthPtr = daysInMonth[1];
}
else
{
daysInMonthPtr = daysInMonth[0];
}
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))
{
assert(false && "Invalid year, month and day");
}
int daysThisYear = day;
if (IsLeapYear(year))
{
daysThisYear += cumulDaysInMonth[1][month];
}
else
{
daysThisYear += cumulDaysInMonth[0][month];
}
return daysThisYear;
}
/**
*
*/
double AbsoluteDays(unsigned int year, double doy) const
{
int64_t 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
*/
int64_t daysSoFar = 365 * previousYear
+ previousYear / 4LL
- previousYear / 100LL
+ previousYear / 400LL;
return static_cast<double>(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 static_cast<int>(((m_encoded / TicksPerDay) + 1LL) % 7LL);
}
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());
}
/**
* 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());
}
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
{
auto ticks = static_cast<int64_t>(microseconds * TicksPerMicrosecond);
return AddTicks(ticks);
}
DateTime AddTicks(int64_t ticks) const
{
return DateTime(m_encoded + ticks);
}
/**
* Get the number of ticks
* @returns the number of ticks
*/
int64_t Ticks() const
{
return m_encoded;
}
void FromTicks(int& year, int& month, int& day) const
{
int totalDays = static_cast<int>(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;
}
/**
* Hour component
* @returns the hour component
*/
int Hour() const
{
return static_cast<int>(m_encoded % TicksPerDay / TicksPerHour);
}
/**
* Minute component
* @returns the minute component
*/
int Minute() const
{
return static_cast<int>(m_encoded % TicksPerHour / TicksPerMinute);
}
/**
* Second component
* @returns the Second component
*/
int Second() const
{
return static_cast<int>(m_encoded % TicksPerMinute / TicksPerSecond);
}
/**
* Microsecond component
* @returns the microsecond component
*/
int Microsecond() const
{
return static_cast<int>(m_encoded % TicksPerSecond / TicksPerMicrosecond);
}
/**
* Convert to a julian date
* @returns the julian date
*/
double ToJulian() const
{
auto ts = TimeSpan(Ticks());
return ts.TotalDays() + 1721425.5;
}
/**
* Convert to greenwich sidereal time
* @returns the greenwich sidereal time
*/
double ToGreenwichSiderealTime() const
{
// julian date of previous midnight
double jd0 = floor(ToJulian() + 0.5) - 0.5;
// julian centuries since epoch
double t = (jd0 - 2451545.0) / 36525.0;
double jdf = ToJulian() - jd0;
double gt = 24110.54841 + t * (8640184.812866 + t * (0.093104 - t * 6.2E-6));
gt += jdf * 1.00273790935 * 86400.0;
// 360.0 / 86400.0 = 1.0 / 240.0
return Util::WrapTwoPI(Util::DegreesToRadians(gt / 240.0));
}
/**
* Return the modified julian date since the j2000 epoch
* January 1, 2000, at 12:00 TT
* @returns the modified julian date
*/
double ToJ2000() const
{
return ToJulian() - 2415020.0;
}
/**
* 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);
}
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:
int64_t m_encoded{};
};
inline std::ostream& operator<<(std::ostream& strm, const DateTime& dt)
{
return strm << dt.ToString();
}
inline DateTime operator+(const DateTime& dt, TimeSpan ts)
{
return DateTime(dt.Ticks() + ts.Ticks());
}
inline DateTime operator-(const DateTime& dt, const TimeSpan& ts)
{
return DateTime(dt.Ticks() - ts.Ticks());
}
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);
}
} // namespace libsgp4

View File

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

View File

@ -0,0 +1,79 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "DateTime.h"
#include "Vector.h"
#include <stdexcept>
#include <string>
namespace libsgp4
{
/**
* @brief The exception that the SGP4 class throws when a satellite decays.
*/
class DecayedException : public std::runtime_error
{
public:
/**
* 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)
: runtime_error("Satellite decayed")
, _dt(dt)
, _pos(pos)
, _vel(vel)
{
}
/**
* @returns the date
*/
DateTime Decayed() const
{
return _dt;
}
/**
* @returns the position
*/
Vector Position() const
{
return _pos;
}
/**
* @returns the velocity
*/
Vector Velocity() const
{
return _vel;
}
private:
DateTime _dt;
Vector _pos;
Vector _vel;
};
} // namespace libsgp4

111
SPG4Tool/libsgp4/Eci.cc Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Eci.h"
#include "Globals.h"
#include "Util.h"
namespace libsgp4
{
/**
* 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
*/
m_dt = dt;
static const double mfactor = kTWOPI * (kOMEGA_E / kSECONDS_PER_DAY);
/*
* Calculate Local Mean Sidereal Time for observers longitude
*/
const double theta = m_dt.ToLocalMeanSiderealTime(geo.longitude);
/*
* take into account earth flattening
*/
const double c = 1.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 achcp = (kXKMPER * c + geo.altitude) * cos(geo.latitude);
/*
* X position in km
* Y position in km
* Z position in km
* W magnitude in km
*/
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.Magnitude();
/*
* X velocity in km/s
* Y velocity in km/s
* Z velocity in km/s
* W magnitude in km/s
*/
m_velocity.x = -mfactor * m_position.y;
m_velocity.y = mfactor * m_position.x;
m_velocity.z = 0.0;
m_velocity.w = m_velocity.Magnitude();
}
/**
* @returns the position in geodetic form
*/
CoordGeodetic Eci::ToGeodetic() const
{
const double theta = Util::AcTan(m_position.y, m_position.x);
const double lon = Util::WrapNegPosPI(theta
- m_dt.ToGreenwichSiderealTime());
const double r = sqrt((m_position.x * m_position.x)
+ (m_position.y * m_position.y));
static const double e2 = kF * (2.0 - kF);
double lat = Util::AcTan(m_position.z, r);
double phi = 0.0;
double c = 0.0;
int cnt = 0;
do
{
phi = lat;
const double sinphi = sin(phi);
c = 1.0 / sqrt(1.0 - e2 * sinphi * sinphi);
lat = Util::AcTan(m_position.z + kXKMPER * c * e2 * sinphi, r);
cnt++;
}
while (fabs(lat - phi) >= 1e-10 && cnt < 10);
const double alt = r / cos(lat) - kXKMPER * c;
return CoordGeodetic(lat, lon, alt, true);
}
} // namespace libsgp4

146
SPG4Tool/libsgp4/Eci.h Normal file
View File

@ -0,0 +1,146 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "CoordGeodetic.h"
#include "Vector.h"
#include "DateTime.h"
namespace libsgp4
{
/**
* @brief Stores an Earth-centered inertial position for a particular time.
*/
class Eci
{
public:
/**
* @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 DateTime& dt,
const double latitude,
const double longitude,
const double altitude)
{
ToEci(dt, CoordGeodetic(latitude, longitude, altitude));
}
/**
* @param[in] dt the date to be used for this position
* @param[in] geo the position
*/
Eci(const DateTime& dt, const CoordGeodetic& geo)
{
ToEci(dt, geo);
}
/**
* @param[in] dt the date to be used for this position
* @param[in] position the position
*/
Eci(const DateTime &dt, const Vector &position)
: m_dt(dt)
, m_position(position)
{
}
/**
* @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)
{
}
/**
* 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 Position() const
{
return m_position;
}
/**
* @returns the velocity
*/
Vector Velocity() const
{
return m_velocity;
}
/**
* @returns the date
*/
DateTime GetDateTime() const
{
return m_dt;
}
/**
* @returns the position in geodetic form
*/
CoordGeodetic ToGeodetic() const;
private:
void ToEci(const DateTime& dt, const CoordGeodetic& geo);
DateTime m_dt;
Vector m_position;
Vector m_velocity;
};
} // namespace libsgp4

View File

@ -0,0 +1,18 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Globals.h"

View File

@ -0,0 +1,77 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cmath>
namespace libsgp4
{
const double kAE = 1.0;
const double kQ0 = 120.0;
const double kS0 = 78.0;
const double kMU = 398600.8;
const double kXKMPER = 6378.135;
const double kXJ2 = 1.082616e-3;
const double kXJ3 = -2.53881e-6;
const double kXJ4 = -1.65597e-6;
/*
* alternative XKE
* affects final results
* aiaa-2006-6573
* const double kXKE = 60.0 / sqrt(kXKMPER * kXKMPER * kXKMPER / kMU);
* dundee
* const double kXKE = 7.43669161331734132e-2;
*/
const double kXKE = 60.0 / sqrt(kXKMPER * kXKMPER * kXKMPER / kMU);
const double kCK2 = 0.5 * kXJ2 * kAE * kAE;
const double kCK4 = -0.375 * kXJ4 * kAE * kAE * kAE * kAE;
/*
* alternative QOMS2T
* affects final results
* aiaa-2006-6573
* #define QOMS2T (pow(((Q0 - S0) / XKMPER), 4.0))
* dundee
* #define QOMS2T (1.880279159015270643865e-9)
*/
const double kQOMS2T = pow(((kQ0 - kS0) / kXKMPER), 4.0);
const double kS = kAE * (1.0 + kS0 / kXKMPER);
const double kPI = 3.14159265358979323846264338327950288419716939937510582;
const double kTWOPI = 2.0 * kPI;
const double kTWOTHIRD = 2.0 / 3.0;
const double kTHDT = 4.37526908801129966e-3;
/*
* earth flattening
*/
const double kF = 1.0 / 298.26;
/*
* earth rotation per sideral day
*/
const double kOMEGA_E = 1.00273790934;
const double kAU = 1.49597870691e8;
const double kSECONDS_PER_DAY = 86400.0;
const double kMINUTES_PER_DAY = 1440.0;
const double kHOURS_PER_DAY = 24.0;
const double kA3OVK2 = -kXJ3 / kCK2 * kAE * kAE * kAE;
} // namespace libsgp4

View File

@ -0,0 +1,86 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Observer.h"
#include "CoordTopocentric.h"
namespace libsgp4
{
/*
* calculate lookangle between the observer and the passed in Eci object
*/
CoordTopocentric Observer::GetLookAngle(const Eci &eci)
{
/*
* update the observers Eci to match the time of the Eci passed in
* if necessary
*/
Update(eci.GetDateTime());
/*
* calculate differences
*/
Vector range_rate = eci.Velocity() - m_eci.Velocity();
Vector range = eci.Position() - m_eci.Position();
range.w = range.Magnitude();
/*
* Calculate Local Mean Sidereal Time for observers longitude
*/
double theta = eci.GetDateTime().ToLocalMeanSiderealTime(m_geo.longitude);
double sin_lat = sin(m_geo.latitude);
double cos_lat = cos(m_geo.latitude);
double sin_theta = sin(theta);
double cos_theta = cos(theta);
double top_s = sin_lat * cos_theta * range.x
+ sin_lat * sin_theta * range.y - cos_lat * range.z;
double top_e = -sin_theta * range.x
+ cos_theta * range.y;
double top_z = cos_lat * cos_theta * range.x
+ cos_lat * sin_theta * range.y + sin_lat * range.z;
double az = atan(-top_e / top_s);
if (top_s > 0.0)
{
az += kPI;
}
if (az < 0.0)
{
az += 2.0 * kPI;
}
double el = asin(top_z / range.w);
double rate = range.Dot(range_rate) / range.w;
/*
* azimuth in radians
* elevation in radians
* range in km
* range rate in km/s
*/
return CoordTopocentric(az,
el,
range.w,
rate);
}
} // namespace libsgp4

103
SPG4Tool/libsgp4/Observer.h Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "CoordGeodetic.h"
#include "Eci.h"
namespace libsgp4
{
class DateTime;
struct CoordTopocentric;
/**
* @brief Stores an observers location in Eci coordinates.
*/
class Observer
{
public:
/**
* Constructor
* @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)
{
}
/**
* Constructor
* @param[in] geo the observers position
*/
explicit Observer(const CoordGeodetic &geo)
: m_geo(geo)
, m_eci(DateTime(), geo)
{
}
/**
* Set the observers location
* @param[in] geo the observers position
*/
void SetLocation(const CoordGeodetic& geo)
{
m_geo = geo;
m_eci.Update(m_eci.GetDateTime(), m_geo);
}
/**
* Get the observers location
* @returns the observers position
*/
CoordGeodetic GetLocation() const
{
return m_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
*/
CoordTopocentric GetLookAngle(const Eci &eci);
private:
/**
* @param[in] dt the date to update the observers position for
*/
void Update(const DateTime &dt)
{
if (m_eci != dt)
{
m_eci.Update(dt, m_geo);
}
}
/** the observers position */
CoordGeodetic m_geo;
/** the observers Eci for a particular time */
Eci m_eci;
};
} // namespace libsgp4

View File

@ -0,0 +1,70 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "OrbitalElements.h"
#include "Tle.h"
namespace libsgp4
{
OrbitalElements::OrbitalElements(const Tle& tle)
{
/*
* extract and format tle data
*/
mean_anomoly_ = tle.MeanAnomaly(false);
ascending_node_ = tle.RightAscendingNode(false);
argument_perigee_ = tle.ArgumentPerigee(false);
eccentricity_ = tle.Eccentricity();
inclination_ = tle.Inclination(false);
mean_motion_ = tle.MeanMotion() * kTWOPI / kMINUTES_PER_DAY;
bstar_ = tle.BStar();
epoch_ = tle.Epoch();
/*
* recover original mean motion (xnodp) and semimajor axis (aodp)
* from input elements
*/
const double a1 = pow(kXKE / MeanMotion(), kTWOTHIRD);
const double cosio = cos(Inclination());
const double theta2 = cosio * cosio;
const double x3thm1 = 3.0 * theta2 - 1.0;
const double eosq = Eccentricity() * Eccentricity();
const double betao2 = 1.0 - eosq;
const double betao = sqrt(betao2);
const double temp = (1.5 * kCK2) * x3thm1 / (betao * betao2);
const double del1 = temp / (a1 * a1);
const double a0 = a1 * (1.0 - del1 * (1.0 / 3.0 + del1 * (1.0 + del1 * 134.0 / 81.0)));
const double del0 = temp / (a0 * a0);
recovered_mean_motion_ = MeanMotion() / (1.0 + del0);
/*
* alternative way to calculate
* doesnt affect final results
* recovered_semi_major_axis_ = pow(XKE / RecoveredMeanMotion(), TWOTHIRD);
*/
recovered_semi_major_axis_ = a0 / (1.0 - del0);
/*
* find perigee and period
*/
perigee_ = (RecoveredSemiMajorAxis() * (1.0 - Eccentricity()) - kAE) * kXKMPER;
period_ = kTWOPI / RecoveredMeanMotion();
}
} // namespace libsgp4

View File

@ -0,0 +1,147 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "Util.h"
#include "DateTime.h"
namespace libsgp4
{
class Tle;
/**
* @brief The extracted orbital elements used by the SGP4 propagator.
*/
class OrbitalElements
{
public:
explicit OrbitalElements(const Tle& tle);
/*
* XMO
*/
double MeanAnomoly() const
{
return mean_anomoly_;
}
/*
* XNODEO
*/
double AscendingNode() const
{
return ascending_node_;
}
/*
* OMEGAO
*/
double ArgumentPerigee() const
{
return argument_perigee_;
}
/*
* EO
*/
double Eccentricity() const
{
return eccentricity_;
}
/*
* XINCL
*/
double Inclination() const
{
return inclination_;
}
/*
* XNO
*/
double MeanMotion() const
{
return mean_motion_;
}
/*
* BSTAR
*/
double BStar() const
{
return bstar_;
}
/*
* AODP
*/
double RecoveredSemiMajorAxis() const
{
return recovered_semi_major_axis_;
}
/*
* XNODP
*/
double RecoveredMeanMotion() const
{
return recovered_mean_motion_;
}
/*
* PERIGE
*/
double Perigee() const
{
return perigee_;
}
/*
* Period in minutes
*/
double Period() const
{
return period_;
}
/*
* EPOCH
*/
DateTime Epoch() const
{
return epoch_;
}
private:
double mean_anomoly_;
double ascending_node_;
double argument_perigee_;
double eccentricity_;
double inclination_;
double mean_motion_;
double bstar_;
double recovered_semi_major_axis_;
double recovered_mean_motion_;
double perigee_;
double period_;
DateTime epoch_;
};
} // namespace libsgp4

1353
SPG4Tool/libsgp4/SGP4.cc Normal file

File diff suppressed because it is too large Load Diff

260
SPG4Tool/libsgp4/SGP4.h Normal file
View File

@ -0,0 +1,260 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "Tle.h"
#include "OrbitalElements.h"
#include "Eci.h"
#include "SatelliteException.h"
#include "DecayedException.h"
namespace libsgp4
{
/**
* @mainpage
*
* This documents the SGP4 tracking library.
*/
/**
* @brief The simplified perturbations model 4 propagater.
*/
class SGP4
{
public:
explicit SGP4(const Tle& tle)
: elements_(tle)
{
Initialise();
}
void SetTle(const Tle& tle);
Eci FindPosition(double tsince) const;
Eci FindPosition(const DateTime& date) const;
private:
struct CommonConstants
{
double cosio;
double sinio;
double eta;
double t2cof;
double x1mth2;
double x3thm1;
double x7thm1;
double aycof;
double xlcof;
double xnodcf;
double c1;
double c4;
double omgdot; // secular rate of omega (radians/sec)
double xnodot; // secular rate of xnode (radians/sec)
double xmdot; // secular rate of xmo (radians/sec)
};
struct NearSpaceConstants
{
double c5;
double omgcof;
double xmcof;
double delmo;
double sinmo;
double d2;
double d3;
double d4;
double t3cof;
double t4cof;
double t5cof;
};
struct DeepSpaceConstants
{
double gsto;
double zmol;
double zmos;
/*
* lunar / solar constants for epoch
* applied during DeepSpaceSecular()
*/
double sse;
double ssi;
double ssl;
double ssg;
double ssh;
/*
* lunar / solar constants
* used during DeepSpaceCalculateLunarSolarTerms()
*/
double se2;
double si2;
double sl2;
double sgh2;
double sh2;
double se3;
double si3;
double sl3;
double sgh3;
double sh3;
double sl4;
double sgh4;
double ee2;
double e3;
double xi2;
double xi3;
double xl2;
double xl3;
double xl4;
double xgh2;
double xgh3;
double xgh4;
double xh2;
double xh3;
/*
* used during DeepSpaceCalcDotTerms()
*/
double d2201;
double d2211;
double d3210;
double d3222;
double d4410;
double d4422;
double d5220;
double d5232;
double d5421;
double d5433;
double del1;
double del2;
double del3;
/*
* integrator constants
*/
double xfact;
double xlamo;
enum TOrbitShape
{
NONE,
RESONANCE,
SYNCHRONOUS
} shape;
};
struct IntegratorParams
{
/*
* integrator values
*/
double xli;
double xni;
double atime;
};
void Initialise();
static void RecomputeConstants(const double xinc,
double& sinio,
double& cosio,
double& x3thm1,
double& x1mth2,
double& x7thm1,
double& xlcof,
double& aycof);
Eci FindPositionSDP4(const double tsince) const;
Eci FindPositionSGP4(double tsince) const;
static Eci CalculateFinalPositionVelocity(
const DateTime& date,
const double e,
const double a,
const double omega,
const double xl,
const double xnode,
const double xinc,
const double xlcof,
const double aycof,
const double x3thm1,
const double x1mth2,
const double x7thm1,
const double cosio,
const double sinio);
/**
* Deep space initialisation
*/
void DeepSpaceInitialise(
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);
/**
* Calculate lunar / solar periodics and apply
*/
static void DeepSpacePeriodics(
const double tsince,
const DeepSpaceConstants& ds_constants,
double& em,
double& xinc,
double& omgasm,
double& xnodes,
double& xll);
/**
* Deep space secular effects
*/
static void DeepSpaceSecular(
const double tsince,
const OrbitalElements& elements,
const CommonConstants& c_constants,
const DeepSpaceConstants& ds_constants,
IntegratorParams& integ_params,
double& xll,
double& omgasm,
double& xnodes,
double& em,
double& xinc,
double& xn);
/**
* Reset
*/
void Reset();
/*
* the constants used
*/
struct CommonConstants common_consts_;
struct NearSpaceConstants nearspace_consts_;
struct DeepSpaceConstants deepspace_consts_;
mutable struct IntegratorParams integrator_params_;
/*
* the orbit data
*/
OrbitalElements elements_;
/*
* flags
*/
bool use_simple_model_;
bool use_deep_space_;
};
} // namespace libsgp4

View File

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

View File

@ -0,0 +1,38 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdexcept>
#include <string>
namespace libsgp4
{
/**
* @brief The exception that the SGP4 class throws upon an error.
*/
class SatelliteException : public std::runtime_error
{
public:
explicit SatelliteException(const char* message)
: runtime_error(message)
{
}
};
} // namespace libsgp4

View File

@ -0,0 +1,68 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SolarPosition.h"
#include "Globals.h"
#include "Util.h"
#include <cmath>
namespace libsgp4
{
Eci SolarPosition::FindPosition(const DateTime& dt)
{
const double mjd = dt.ToJ2000();
const double year = 1900 + mjd / 365.25;
const double T = (mjd + Delta_ET(year) / kSECONDS_PER_DAY) / 36525.0;
const double M = Util::DegreesToRadians(Util::Wrap360(358.47583
+ Util::Wrap360(35999.04975 * T)
- (0.000150 + 0.0000033 * T) * T * T));
const double L = Util::DegreesToRadians(Util::Wrap360(279.69668
+ Util::Wrap360(36000.76892 * T)
+ 0.0003025 * T*T));
const double e = 0.01675104 - (0.0000418 + 0.000000126 * T) * T;
const double C = Util::DegreesToRadians((1.919460
- (0.004789 + 0.000014 * T) * T) * sin(M)
+ (0.020094 - 0.000100 * T) * sin(2 * M)
+ 0.000293 * sin(3 * M));
const double O = Util::DegreesToRadians(
Util::Wrap360(259.18 - 1934.142 * T));
const double Lsa = Util::WrapTwoPI(L + C
- Util::DegreesToRadians(0.00569 - 0.00479 * sin(O)));
const double nu = Util::WrapTwoPI(M + C);
double R = 1.0000002 * (1 - e * e) / (1 + e * cos(nu));
const double eps = Util::DegreesToRadians(23.452294 - (0.0130125
+ (0.00000164 - 0.000000503 * T) * T) * T + 0.00256 * cos(O));
R = R * kAU;
Vector solar_position(R * cos(Lsa),
R * sin(Lsa) * cos(eps),
R * sin(Lsa) * sin(eps),
R);
return Eci(dt, solar_position);
}
double SolarPosition::Delta_ET(double year) const
{
return 26.465 + 0.747622 * (year - 1950) + 1.886913
* sin(kTWOPI * (year - 1975) / 33);
}
} // namespace libsgp4

View File

@ -0,0 +1,40 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "DateTime.h"
#include "Eci.h"
namespace libsgp4
{
/**
* @brief Find the position of the sun
*/
class SolarPosition
{
public:
SolarPosition() = default;
Eci FindPosition(const DateTime& dt);
private:
double Delta_ET(double year) const;
};
} // namespace libsgp4

View File

@ -0,0 +1,18 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "TimeSpan.h"

259
SPG4Tool/libsgp4/TimeSpan.h Normal file
View File

@ -0,0 +1,259 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdint>
namespace libsgp4
{
namespace
{
static const int64_t TicksPerDay = 86400000000LL;
static const int64_t TicksPerHour = 3600000000LL;
static const int64_t TicksPerMinute = 60000000LL;
static const int64_t TicksPerSecond = 1000000LL;
static const int64_t TicksPerMillisecond = 1000LL;
static const int64_t TicksPerMicrosecond = 1LL;
static const int64_t UnixEpoch = 62135596800000000LL;
static const int64_t MaxValueTicks = 315537897599999999LL;
// 1582-Oct-15
static const int64_t GregorianStart = 49916304000000000LL;
}
/**
* @brief Represents a time interval.
*
* Represents a time interval (duration/elapsed) that is measured as a positive
* or negative number of days, hours, minutes, seconds, and fractions
* of a second.
*/
class TimeSpan
{
public:
explicit TimeSpan(int64_t 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() const
{
return static_cast<int>(m_ticks / TicksPerDay);
}
int Hours() const
{
return static_cast<int>(m_ticks % TicksPerDay / TicksPerHour);
}
int Minutes() const
{
return static_cast<int>(m_ticks % TicksPerHour / TicksPerMinute);
}
int Seconds() const
{
return static_cast<int>(m_ticks % TicksPerMinute / TicksPerSecond);
}
int Milliseconds() const
{
return static_cast<int>(m_ticks % TicksPerSecond / TicksPerMillisecond);
}
int Microseconds() const
{
return static_cast<int>(m_ticks % TicksPerSecond / TicksPerMicrosecond);
}
int64_t Ticks() const
{
return m_ticks;
}
double TotalDays() const
{
return static_cast<double>(m_ticks) / TicksPerDay;
}
double TotalHours() const
{
return static_cast<double>(m_ticks) / TicksPerHour;
}
double TotalMinutes() const
{
return static_cast<double>(m_ticks) / TicksPerMinute;
}
double TotalSeconds() const
{
return static_cast<double>(m_ticks) / TicksPerSecond;
}
double TotalMilliseconds() const
{
return static_cast<double>(m_ticks) / TicksPerMillisecond;
}
double TotalMicroseconds() const
{
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:
int64_t 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 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);
}
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);
}
} // namespace libsgp4

376
SPG4Tool/libsgp4/Tle.cc Normal file
View File

@ -0,0 +1,376 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Tle.h"
#include <locale>
namespace libsgp4
{
namespace
{
static const unsigned int TLE1_COL_NORADNUM = 2;
static const unsigned int TLE1_LEN_NORADNUM = 5;
static const unsigned int TLE1_COL_INTLDESC_A = 9;
static const unsigned int TLE1_LEN_INTLDESC_A = 2;
// static const unsigned int TLE1_COL_INTLDESC_B = 11;
static const unsigned int TLE1_LEN_INTLDESC_B = 3;
// static const unsigned int TLE1_COL_INTLDESC_C = 14;
static const unsigned int TLE1_LEN_INTLDESC_C = 3;
static const unsigned int TLE1_COL_EPOCH_A = 18;
static const unsigned int TLE1_LEN_EPOCH_A = 2;
static const unsigned int TLE1_COL_EPOCH_B = 20;
static const unsigned int TLE1_LEN_EPOCH_B = 12;
static const unsigned int TLE1_COL_MEANMOTIONDT2 = 33;
static const unsigned int TLE1_LEN_MEANMOTIONDT2 = 10;
static const unsigned int TLE1_COL_MEANMOTIONDDT6 = 44;
static const unsigned int TLE1_LEN_MEANMOTIONDDT6 = 8;
static const unsigned int TLE1_COL_BSTAR = 53;
static const unsigned int TLE1_LEN_BSTAR = 8;
// static const unsigned int TLE1_COL_EPHEMTYPE = 62;
// static const unsigned int TLE1_LEN_EPHEMTYPE = 1;
// static const unsigned int TLE1_COL_ELNUM = 64;
// static const unsigned int TLE1_LEN_ELNUM = 4;
static const unsigned int TLE2_COL_NORADNUM = 2;
static const unsigned int TLE2_LEN_NORADNUM = 5;
static const unsigned int TLE2_COL_INCLINATION = 8;
static const unsigned int TLE2_LEN_INCLINATION = 8;
static const unsigned int TLE2_COL_RAASCENDNODE = 17;
static const unsigned int TLE2_LEN_RAASCENDNODE = 8;
static const unsigned int TLE2_COL_ECCENTRICITY = 26;
static const unsigned int TLE2_LEN_ECCENTRICITY = 7;
static const unsigned int TLE2_COL_ARGPERIGEE = 34;
static const unsigned int TLE2_LEN_ARGPERIGEE = 8;
static const unsigned int TLE2_COL_MEANANOMALY = 43;
static const unsigned int TLE2_LEN_MEANANOMALY = 8;
static const unsigned int TLE2_COL_MEANMOTION = 52;
static const unsigned int TLE2_LEN_MEANMOTION = 11;
static const unsigned int TLE2_COL_REVATEPOCH = 63;
static const unsigned int TLE2_LEN_REVATEPOCH = 5;
}
/**
* Initialise the tle object.
* @exception TleException
*/
void Tle::Initialize()
{
if (!IsValidLineLength(line_one_))
{
throw TleException("Invalid length for line one");
}
if (!IsValidLineLength(line_two_))
{
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())
{
name_ = line_one_.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM);
}
int_designator_ = line_one_.substr(TLE1_COL_INTLDESC_A,
TLE1_LEN_INTLDESC_A + TLE1_LEN_INTLDESC_B + TLE1_LEN_INTLDESC_C);
unsigned int year = 0;
double day = 0.0;
ExtractInteger(line_one_.substr(TLE1_COL_EPOCH_A,
TLE1_LEN_EPOCH_A), year);
ExtractDouble(line_one_.substr(TLE1_COL_EPOCH_B,
TLE1_LEN_EPOCH_B), 4, day);
ExtractDouble(line_one_.substr(TLE1_COL_MEANMOTIONDT2,
TLE1_LEN_MEANMOTIONDT2), 2, mean_motion_dt2_);
ExtractExponential(line_one_.substr(TLE1_COL_MEANMOTIONDDT6,
TLE1_LEN_MEANMOTIONDDT6), mean_motion_ddt6_);
ExtractExponential(line_one_.substr(TLE1_COL_BSTAR,
TLE1_LEN_BSTAR), bstar_);
/*
* 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_);
if (year < 57)
{
year += 2000;
}
else
{
year += 1900;
}
epoch_ = DateTime(year, day);
}
/**
* Check
* @param str The string to check
* @returns Whether true of the string has a valid length
*/
bool Tle::IsValidLineLength(const std::string& str)
{
return str.length() == LineLength() ? true : false;
}
/**
* 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::ExtractInteger(const std::string& str, unsigned int& val)
{
bool found_digit = false;
unsigned int temp = 0;
for (auto& i : str)
{
if (isdigit(i))
{
found_digit = true;
temp = (temp * 10) + static_cast<unsigned int>(i - '0');
}
else if (found_digit)
{
throw TleException("Unexpected non digit");
}
else if (i != ' ')
{
throw TleException("Invalid character");
}
}
if (!found_digit)
{
val = 0;
}
else
{
val = temp;
}
}
/**
* 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)
{
/*
* integer part
*/
if (point_pos >= 0 && 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");
}
}
}
/*
* decimal point
*/
else if (point_pos >= 0 && i == str.begin() + point_pos - 1)
{
if (temp.length() == 0)
{
/*
* integer part is blank, so add a '0'
*/
temp += '0';
}
if (*i == '.')
{
/*
* decimal point found
*/
temp += *i;
}
else
{
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 += '.';
}
/*
* 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.end() - 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");
}
}
} // namespace libsgp4

341
SPG4Tool/libsgp4/Tle.h Normal file
View File

@ -0,0 +1,341 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "Util.h"
#include "DateTime.h"
#include "TleException.h"
namespace libsgp4
{
/**
* @brief Processes a two-line element set used to convey OrbitalElements.
*
* Used to extract the various raw fields from a two-line element set.
*/
class Tle
{
public:
/**
* @details Initialise given the two lines of a tle
* @param[in] line_one Tle line one
* @param[in] line_two Tle line two
*/
Tle(std::string line_one, std::string line_two)
: line_one_(std::move(line_one))
, line_two_(std::move(line_two))
{
Initialize();
}
/**
* @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(std::string name, std::string line_one, std::string line_two)
: name_(std::move(name))
, line_one_(std::move(line_one))
, line_two_(std::move(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_;
}
/**
* Get the satellite name
* @returns the satellite name
*/
std::string Name() const
{
return name_;
}
/**
* Get the first line of the tle
* @returns the first line of the tle
*/
std::string Line1() const
{
return line_one_;
}
/**
* Get the second line of the tle
* @returns the second line of the tle
*/
std::string Line2() const
{
return line_two_;
}
/**
* Get the norad number
* @returns the norad number
*/
unsigned int NoradNumber() const
{
return norad_number_;
}
/**
* Get the international designator
* @returns the international designator
*/
std::string IntDesignator() const
{
return int_designator_;
}
/**
* Get the tle epoch
* @returns the tle epoch
*/
DateTime Epoch() const
{
return epoch_;
}
/**
* 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_dt2_;
}
/**
* 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_ddt6_;
}
/**
* Get the BSTAR drag term
* @returns the BSTAR drag term
*/
double BStar() const
{
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
{
if (in_degrees)
{
return inclination_;
}
else
{
return Util::DegreesToRadians(inclination_);
}
}
/**
* 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
{
if (in_degrees)
{
return right_ascending_node_;
}
else
{
return Util::DegreesToRadians(right_ascending_node_);
}
}
/**
* Get the eccentricity
* @returns the eccentricity
*/
double Eccentricity() const
{
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
{
if (in_degrees)
{
return argument_perigee_;
}
else
{
return Util::DegreesToRadians(argument_perigee_);
}
}
/**
* 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
{
if (in_degrees)
{
return mean_anomaly_;
}
else
{
return Util::DegreesToRadians(mean_anomaly_);
}
}
/**
* Get the mean motion
* @returns the mean motion (revolutions per day)
*/
double MeanMotion() const
{
return mean_motion_;
}
/**
* Get the orbit number
* @returns the orbit number
*/
unsigned int OrbitNumber() const
{
return orbit_number_;
}
/**
* Get the expected tle line length
* @returns the tle line length
*/
static unsigned int LineLength()
{
return TLE_LEN_LINE_DATA;
}
/**
* 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:
void Initialize();
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:
std::string name_;
std::string line_one_;
std::string line_two_;
std::string int_designator_;
DateTime epoch_;
double mean_motion_dt2_{};
double mean_motion_ddt6_{};
double bstar_{};
double inclination_{};
double right_ascending_node_{};
double eccentricity_{};
double argument_perigee_{};
double mean_anomaly_{};
double mean_motion_{};
unsigned int norad_number_{};
unsigned int orbit_number_{};
static const unsigned int TLE_LEN_LINE_DATA = 69;
static const unsigned int TLE_LEN_LINE_NAME = 22;
};
inline std::ostream& operator<<(std::ostream& strm, const Tle& t)
{
return strm << t.ToString();
}
} // namespace libsgp4

View File

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

View File

@ -0,0 +1,44 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdexcept>
#include <string>
namespace libsgp4
{
/**
* @brief The exception that the Tle class throws on an error.
*
* The exception that the Tle decoder will throw on an error.
*/
class TleException : public std::runtime_error
{
public:
/**
* Constructor
* @param message Exception message
*/
explicit TleException(const char* message)
: runtime_error(message)
{
}
};
} // namespace libsgp4

45
SPG4Tool/libsgp4/Util.cc Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Util.h"
#include <algorithm>
#include <locale>
#include <functional>
namespace libsgp4
{
namespace Util {
void TrimLeft(std::string& s)
{
s.erase(s.begin(),
std::find_if(s.begin(), s.end(), [](unsigned char c) { return std::isgraph(c) != 0; }));
}
void TrimRight(std::string& s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c) { return std::isgraph(c) != 0; }).base(),
s.end());
}
void Trim(std::string& s)
{
TrimLeft(s);
TrimRight(s);
}
}
} // namespace libsgp4::Util

111
SPG4Tool/libsgp4/Util.h Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "Globals.h"
#include <sstream>
namespace libsgp4
{
namespace Util
{
template
<typename T>
bool FromString(const std::string& str, T& val)
{
std::stringstream ss(str);
return !(ss >> val).fail();
}
/*
* always positive result
* Mod(-3,4)= 1 fmod(-3,4)= -3
*/
inline double Mod(const double x, const double y)
{
if (y == 0.0)
{
return x;
}
return x - y * floor(x / y);
}
inline double WrapNegPosPI(const double a)
{
return Mod(a + kPI, kTWOPI) - kPI;
}
inline double WrapTwoPI(const double a)
{
return Mod(a, kTWOPI);
}
inline double WrapNegPos180(const double a)
{
return Mod(a + 180.0, 360.0) - 180.0;
}
inline double Wrap360(const double a)
{
return Mod(a, 360.0);
}
inline double DegreesToRadians(const double degrees)
{
return degrees * kPI / 180.0;
}
inline double RadiansToDegrees(const double radians)
{
return radians * 180.0 / kPI;
}
inline double AcTan(const double sinx, const double cosx)
{
if (cosx == 0.0)
{
if (sinx > 0.0)
{
return kPI / 2.0;
}
else
{
return 3.0 * kPI / 2.0;
}
}
else
{
if (cosx > 0.0)
{
return atan(sinx / cosx);
}
else
{
return kPI + atan(sinx / cosx);
}
}
}
void TrimLeft(std::string& s);
void TrimRight(std::string& s);
void Trim(std::string& s);
} // namespace Util
} // namespace libsgp4

View File

@ -0,0 +1,18 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Vector.h"

160
SPG4Tool/libsgp4/Vector.h Normal file
View File

@ -0,0 +1,160 @@
/*
* Copyright 2013 Daniel Warner <contact@danrw.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cmath>
#include <string>
#include <sstream>
#include <iomanip>
namespace libsgp4
{
/**
* @brief Generic vector
*
* Stores x, y, z, w
*/
struct Vector
{
public:
/**
* Default constructor
*/
Vector() = default;
/**
* 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)
{
}
/**
* 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)
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
/**
* Assignment operator
* @param v value to copy from
*/
Vector& operator=(const Vector& v)
{
if (this != &v)
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
return *this;
}
/**
* Subtract operator
* @param v value to suctract from
*/
Vector operator-(const Vector& v)
{
return Vector(x - v.x,
y - v.y,
z - v.z,
0.0);
}
/**
* Calculates the magnitude of the vector
* @returns magnitude of the vector
*/
double Magnitude() const
{
return sqrt(x * x + y * y + z * z);
}
/**
* Calculates the dot product
* @returns dot product
*/
double Dot(const Vector& vec) const
{
return (x * vec.x) +
(y * vec.y) +
(z * vec.z);
}
/**
* Converts this vector to a string
* @returns this vector as a string
*/
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(3);
ss << "X: " << std::setw(9) << x;
ss << ", Y: " << std::setw(9) << y;
ss << ", Z: " << std::setw(9) << z;
ss << ", W: " << std::setw(9) << w;
return ss.str();
}
/** x value */
double x{};
/** y value */
double y{};
/** z value */
double z{};
/** w value */
double w{};
};
inline std::ostream& operator<<(std::ostream& strm, const Vector& v)
{
return strm << v.ToString();
}
} // namespace libsgp4