Skip to content

Commit

Permalink
Completed OMM and OMMDateTime objects
Browse files Browse the repository at this point in the history
  • Loading branch information
A-j-K committed Jul 10, 2023
1 parent a954bab commit 1b94e35
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 70 deletions.
2 changes: 1 addition & 1 deletion plugins/Satellites/src/OMMDateTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ OMMDateTime::OMMDateTime()
OMMDateTime::~OMMDateTime()
{}

OMMDateTime::OMMDateTime(QString & s, Type t)
OMMDateTime::OMMDateTime(const QString & s, Type t)
{
switch(t) {
case STR_TLE:
Expand Down
5 changes: 4 additions & 1 deletion plugins/Satellites/src/OMMDateTime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@

#include <QString>
#include <QDateTime>
#include <QSharedPointer>

class OMMDateTime
{
public:
typedef QSharedPointer<OMMDateTime> ShPtr;

enum Type {
STR_TLE,
STR_ISO8601
Expand All @@ -46,7 +49,7 @@ class OMMDateTime
OMMDateTime();
~OMMDateTime();

OMMDateTime(QString& s, Type t = STR_TLE);
OMMDateTime(const QString& s, Type t = STR_TLE);

double getJulianDay() { return m_epoch_jd; }

Expand Down
83 changes: 52 additions & 31 deletions plugins/Satellites/src/omm.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Stellarium
* Copyright (C) 2023 Andy Kirkham
*
* This program is free software; you can redistribute it and/or
Expand All @@ -23,8 +24,6 @@

#include "OMM.hpp"

namespace PluginSatellites {

OMM::OMM()
{
m_source_type = SourceType::Invalid;
Expand All @@ -44,7 +43,8 @@ OMM::OMM(QString & l1, QString & l2)
m_source_type = SourceType::LegacyTle;
m_line1 = l1;
m_line2 = l2;
processTleLegacy();
processTleLegacyLine1();
processTleLegacyLine2();
}

OMM::OMM(QString& l0, QString& l1, QString& l2)
Expand All @@ -53,7 +53,9 @@ OMM::OMM(QString& l0, QString& l1, QString& l2)
m_line0 = l0;
m_line1 = l1;
m_line2 = l2;
processTleLegacy();
processTleLegacyLine0();
processTleLegacyLine1();
processTleLegacyLine2();
}

bool OMM::hasValidLegacyTleData()
Expand Down Expand Up @@ -108,10 +110,7 @@ bool OMM::setFromXML(QXmlStreamReader & r)

void OMM::processXmlElement(const QString & tag, const QString & val)
{
if (tag == "EPOCH") {
m_epoch_str = val;
m_epoch = QDateTime::fromString(val, "yyyy-MM-ddThh:mm:ss.zzzzzz");
}
if (tag == "EPOCH") m_sp_epoch = OMMDateTime::ShPtr(new OMMDateTime(val, OMMDateTime::STR_ISO8601));
else if (tag == "OBJECT_NAME") m_object_name = val;
else if (tag == "OBJECT_ID") m_object_id = val;
else if (tag == "MEAN_MOTION") m_mean_motion = val.toDouble();
Expand All @@ -122,27 +121,56 @@ void OMM::processXmlElement(const QString & tag, const QString & val)
else if (tag == "MEAN_ANOMALY") m_mean_anomoly = val.toDouble();
else if (tag == "CLASSIFICATION_TYPE") m_classification = val.at(0).toUpper();
else if (tag == "NORAD_CAT_ID") m_norad_cat_id = val.toInt();
else if (tag == "ELEMENT_SET_NO") m_element_set_no = val.toInt();
else if (tag == "ELEMENT_SET_NO") m_element_number = val.toInt();
else if (tag == "REV_AT_EPOCH") m_rev_at_epoch = val.toInt();
else if (tag == "BSTAR") m_bstar = val.toDouble();
else if (tag == "MEAN_MOTION_DOT") m_mean_motion_dot = val.toDouble();
else if (tag == "MEAN_MOTION_DDOT") m_mean_motion_ddot = val.toDouble();
}

// Everything below here is for extracting the data from the two TLE lines.
// Everything below here is for extracting the data from the legacy two line TLE format.

// J F M A M J J A S O N D
static int month_lens[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
void OMM::processTleLegacyLine0(void)
{
if (!m_line0.isEmpty()) {
m_object_name = m_line0.trimmed();
}
}

// TLE Line1 field positions and lengths.
static QPair<int, int> NORAD_CAT_ID(2,5);
static QPair<int, int> CLASSIFICATION_TYPE(7,1);
static QPair<int, int> OBJECT_ID(9, 8);
static QPair<int, int> EPOCH(18, 14);
static QPair<int, int> EPOCH_YEAR(18, 2);
static QPair<int, int> EPOCH_DAY(20, 12);
static QPair<int, int> MEAN_MOTION_DOT(33, 10);
static QPair<int, int> MEAN_MOTION_DDOT(44, 8);
static QPair<int, int> BSTAR(53, 8);
static QPair<int, int> EPHEMERIS_TYPE(62, 1);
static QPair<int, int> ELEMENT_NUMBER(64, 4);

void OMM::processTleLegacyLine1(void)
{
if (!m_line1.isEmpty() && m_line1.at(0) == '1') {
auto epoch_str = m_line1.mid(EPOCH.first, EPOCH.second).trimmed();
m_sp_epoch = OMMDateTime::ShPtr(new OMMDateTime(epoch_str));
m_norad_cat_id = m_line1.mid(NORAD_CAT_ID.first, NORAD_CAT_ID.second).toInt();
m_classification = m_line1.at(CLASSIFICATION_TYPE.first);
m_object_id = m_line1.mid(OBJECT_ID.first, OBJECT_ID.second).trimmed();
m_mean_motion_dot = m_line1.mid(33, 10).toDouble();
QString ddot(".");
ddot.append(m_line1.mid(44, 5));
ddot.replace(QChar('-'), QString("e-"));
m_mean_motion_ddot = ddot.toDouble();
QString bstar(".");
bstar.append(m_line1.mid(BSTAR.first, BSTAR.second).trimmed());
bstar.replace(QChar('-'), QString("e-"));
m_bstar = bstar.toDouble();
m_ephermeris_type = m_line1.mid(EPHEMERIS_TYPE.first, EPHEMERIS_TYPE.second).trimmed().toInt();
m_element_number = m_line1.mid(ELEMENT_NUMBER.first, ELEMENT_NUMBER.second).trimmed().toInt();
}
}

// TLE Line2 field positions and lengths.
static QPair<int, int> INCLINATION(8, 8);
Expand All @@ -153,25 +181,18 @@ static QPair<int, int> MEAN_ANOMALY(43, 8);
static QPair<int, int> MEAN_MOTION(52, 11);
static QPair<int, int> REV_AT_EPOCH(63, 5);

void OMM::processTleLegacy(void)
void OMM::processTleLegacyLine2(void)
{
if (m_line1.at(0) == '1') {
m_norad_cat_id = m_line1.mid(NORAD_CAT_ID.first, NORAD_CAT_ID.second).toInt();
m_classification = m_line1.at(CLASSIFICATION_TYPE.first);
m_object_id = m_line1.mid(OBJECT_ID.first, OBJECT_ID.second).trimmed();
int epoch_year = m_line1.mid(EPOCH_YEAR.first, EPOCH_YEAR.second).toInt();
if (epoch_year < 57) epoch_year += 2000;
else epoch_year += 1900;
QDate year = QDate(epoch_year, 1, 1);
double epoch_day = m_line1.mid(EPOCH_DAY.first, EPOCH_DAY.second).toDouble();
int day = std::floor(epoch_day);

// 18-31 Epoch. Element Set Epoch (UTC) *Note: spaces are acceptable in columns 20 & 21
m_mean_motion_dot = m_line1.mid(33, 10).toDouble();
QString dec(".");
dec.append(m_line1.mid(44, 5));
m_mean_motion_ddot = dec.toDouble();
if(!m_line2.isEmpty() && m_line2.at(0) == '2') {
m_inclination = m_line2.mid(INCLINATION.first, INCLINATION.second).trimmed().toDouble();
m_ascending_node = m_line2.mid(RA_OF_ASC_NODE.first, RA_OF_ASC_NODE.second).trimmed().toDouble();
m_argument_perigee = m_line2.mid(ARG_OF_PERICENTER.first, ARG_OF_PERICENTER.second).trimmed().toDouble();
QString ecc_s(".");
ecc_s.append(m_line2.mid(ECCENTRICITY.first, ECCENTRICITY.second));
m_eccentricity = ecc_s.trimmed().toDouble();
m_mean_anomoly = m_line2.mid(MEAN_ANOMALY.first, MEAN_ANOMALY.second).trimmed().toDouble();
m_mean_motion = m_line2.mid(MEAN_MOTION.first, MEAN_MOTION.second).trimmed().toDouble();
m_rev_at_epoch = m_line2.mid(REV_AT_EPOCH.first, REV_AT_EPOCH.second).trimmed().toInt();

}
}

} // end namespace PluginSatellites
22 changes: 10 additions & 12 deletions plugins/Satellites/src/omm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include <QSharedPointer>
#include <QXmlStreamReader>

namespace PluginSatellites {
#include "OMMDateTime.hpp"

class OMM
{
Expand Down Expand Up @@ -61,18 +61,18 @@ class OMM

virtual SourceType getSourceType() { return m_source_type; }

virtual QDateTime getEpoch() { return m_epoch; }
virtual const QString& getEpochStr() { return m_epoch_str; }
virtual OMMDateTime::ShPtr getEpoch() { return m_sp_epoch; }
virtual double getMeanMotion() { return m_mean_motion; }
virtual double getEccentricity() { return m_eccentricity; }
virtual double getInclination() { return m_inclination; }
virtual double getAscendingNode() { return m_ascending_node; }
virtual double getArgumentOfPerigee() { return m_argument_perigee; }
virtual double getMeanAnomoly() { return m_mean_anomoly; }
virtual int getEphermisType() { return m_ephermeris_type; }
virtual int getElementNumber() { return m_element_number; }

virtual QChar getClassification() { return m_classification; }
virtual int getNoradcatId() { return m_norad_cat_id; }
virtual int getElementSetNo() { return m_element_set_no; }
virtual int getRevAtEpoch() { return m_rev_at_epoch; }
virtual double getBstar() { return m_bstar; }
virtual double getMeanMotionDot() { return m_mean_motion_dot; }
Expand All @@ -82,7 +82,9 @@ class OMM
virtual const QString& getObjectId() { return m_object_id; }

private:
void processTleLegacy(void);
void processTleLegacyLine0(void);
void processTleLegacyLine1(void);
void processTleLegacyLine2(void);
void processXmlElement(const QString& tag, const QString& val);

SourceType m_source_type;
Expand All @@ -93,7 +95,7 @@ class OMM
QString m_line2{};

// Mean elements.
QDateTime m_epoch{};
OMMDateTime::ShPtr m_sp_epoch{};
double m_mean_motion{};
double m_eccentricity{};
double m_inclination{};
Expand All @@ -104,20 +106,16 @@ class OMM
// TLE parameters.
QChar m_classification{};
int m_norad_cat_id{};
int m_element_set_no{};
int m_rev_at_epoch{};
double m_bstar{};
double m_mean_motion_dot{};
double m_mean_motion_ddot{};
int m_ephermeris_type{};
int m_element_number{};

// Metadata
QString m_object_name{};
QString m_object_id{};

// Misc data.
QString m_epoch_str;
};

} // end namespace PluginSatellites

#endif
67 changes: 52 additions & 15 deletions plugins/Satellites/src/test/testOMM.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Stellarium
* Copyright (C) 2023 Andy Kirkham
*
* This program is free software; you can redistribute it and/or
Expand Down Expand Up @@ -27,28 +28,65 @@ QTEST_GUILESS_MAIN(TestOMM)
void TestOMM::testLegacyTle()
{
QString l0("ISS (ZARYA)");
QString l1("1 25544U 98067A 23187.34555919 .00007611 00000+0 14335-3 0 9995");
// 1 2 3 4 5 6 7
// 01234567890123456789012345678901234567890123456789012345678901234567890
QString l1("1 25544U 98067A 23191.40640406 .00007611 00000+0 14335-3 0 9995");
QString l2("2 25544 51.6398 233.5611 0000373 12.3897 91.4664 15.49560249404764");
PluginSatellites::OMM::ShPtr dut(new PluginSatellites::OMM(l0, l1, l2));
QVERIFY(dut->getSourceType() == PluginSatellites::OMM::SourceType::LegacyTle);
OMM::ShPtr dut(new OMM(l0, l1, l2));
QVERIFY(dut->getSourceType() == OMM::SourceType::LegacyTle);
QVERIFY(dut->hasValidLegacyTleData() == true);
QVERIFY(dut->getLine0() == l0);
QVERIFY(dut->getLine1() == l1);
QVERIFY(dut->getLine2() == l2);
}

void TestOMM::testProcessTleLegacy()
void TestOMM::testProcessTleLegacyLine0()
{
QString l0("ISS (ZARYA)");
QString l1("1 25544U 98067A 23187.34555919 .00007611 00000+0 14335-3 0 9995");
// 1 2 3 4 5 6 7
// 01234567890123456789012345678901234567890123456789012345678901234567890
QString l1("1 25544U 98067A 23191.40640406 .00007611 00000+0 14335-3 0 9995");
QString l2("2 25544 51.6398 233.5611 0000373 12.3897 91.4664 15.49560249404764");
PluginSatellites::OMM::ShPtr dut(new PluginSatellites::OMM(l0, l1, l2));
OMM::ShPtr dut(new OMM(l0, l1, l2));
QCOMPARE(dut->getObjectName(), "ISS (ZARYA)");
}

void TestOMM::testProcessTleLegacyLine1()
{
QString l0("ISS (ZARYA)");
// 1 2 3 4 5 6 7
// 01234567890123456789012345678901234567890123456789012345678901234567890
QString l1("1 25544U 98067A 23191.40640406 .00007611 00000+0 14335-3 0 9995");
QString l2("2 25544 51.6398 233.5611 0000373 12.3897 91.4664 15.49560249404764");
OMM::ShPtr dut(new OMM(l0, l1, l2));
QVERIFY(dut->getNoradcatId() == 25544);
QVERIFY(dut->getClassification() == 'U');
QCOMPARE(dut->getObjectId(), QString("98067A"));
// ToDo, Epoch
QCOMPARE(dut->getMeanMotionDot(), 0.00007611);
QCOMPARE(dut->getMeanMotionDDot(), 0.0);

auto jd_of_epoch = dut->getEpoch()->getJulian();
QCOMPARE(jd_of_epoch, 2460135.906404059846);
QCOMPARE(dut->getBstar(), 0.00014334999999999998785);
QVERIFY(dut->getEphermisType() == 0);
QVERIFY(dut->getElementNumber() == 999);
}

void TestOMM::testProcessTleLegacyLine2()
{
QString l0("ISS (ZARYA)");
// 1 2 3 4 5 6 7
// 01234567890123456789012345678901234567890123456789012345678901234567890
QString l1("1 25544U 98067A 23191.40640406 .00007611 00000+0 14335-3 0 9995");
QString l2("2 25544 51.6398 233.5611 0000373 12.3897 91.4664 15.49560249404764");
OMM::ShPtr dut(new OMM(l0, l1, l2));
QCOMPARE(dut->getInclination(), 51.6398);
QCOMPARE(dut->getAscendingNode(), 233.5611);
QCOMPARE(dut->getArgumentOfPerigee(), 12.3897);
QCOMPARE(dut->getEccentricity(), 0.0000373);
QCOMPARE(dut->getMeanAnomoly(), 91.4664);
QCOMPARE(dut->getMeanMotion(), 15.49560249);
QCOMPARE(dut->getRevAtEpoch(), 40476);
}

void TestOMM::testXMLread()
Expand All @@ -61,10 +99,10 @@ void TestOMM::testXMLread()
QVector<int> expectNorad = {
25544, 43557, 47853
};
QVector<QString> expectEpoch = {
QString("2023-07-06T08:17:36.314016"),
QString("2023-07-06T01:58:30.910944"),
QString("2023-07-04T18:34:04.881504")
QVector<double> expectEpoch = {
2460135.906404059846,
2460135.906404059846,
2460135.906404059846
};
int idx = 0;
bool testContinue = true;
Expand All @@ -79,12 +117,11 @@ void TestOMM::testXMLread()
while (testContinue && !r.atEnd()) {
QString tag = r.name().toString();
if (r.isStartElement() && tag.toLower() == "omm") {
PluginSatellites::OMM::ShPtr dut(new PluginSatellites::OMM(r));
OMM::ShPtr dut(new OMM(r));
QVERIFY(dut->getObjectId() == expectOjectId[idx]);
QVERIFY(dut->getNoradcatId() == expectNorad[idx]);
QVERIFY(dut->getEpochStr() == expectEpoch[idx]);
QDateTime ep = QDateTime::fromString(expectEpoch[idx]);
QVERIFY(dut->getEpoch() == ep);
auto jd_of_epoch = dut->getEpoch()->getJulian();
QCOMPARE(jd_of_epoch, expectEpoch[idx]);
idx++;
}
r.readNext();
Expand Down
5 changes: 4 additions & 1 deletion plugins/Satellites/src/test/testOMM.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Stellarium
* Copyright (C) 2023 Andy Kirkham
*
* This program is free software; you can redistribute it and/or
Expand Down Expand Up @@ -29,7 +30,9 @@ class TestOMM : public QObject
private slots:
void testLegacyTle();
void testXMLread();
void testProcessTleLegacy();
void testProcessTleLegacyLine0();
void testProcessTleLegacyLine1();
void testProcessTleLegacyLine2();
};

#endif // TESTOMM_HPP
Loading

0 comments on commit 1b94e35

Please sign in to comment.