From 1b94e35b8d5221ff7d6190d5cf3dc37ca6748055 Mon Sep 17 00:00:00 2001 From: A-j-K Date: Mon, 10 Jul 2023 23:03:51 +0100 Subject: [PATCH] Completed OMM and OMMDateTime objects --- plugins/Satellites/src/OMMDateTime.cpp | 2 +- plugins/Satellites/src/OMMDateTime.hpp | 5 +- plugins/Satellites/src/omm.cpp | 83 ++++++++++++------- plugins/Satellites/src/omm.hpp | 22 +++-- plugins/Satellites/src/test/testOMM.cpp | 67 +++++++++++---- plugins/Satellites/src/test/testOMM.hpp | 5 +- .../Satellites/src/test/testOMMDateTime.cpp | 13 +-- plugins/Satellites/src/test/test_data.xml | 6 +- 8 files changed, 133 insertions(+), 70 deletions(-) diff --git a/plugins/Satellites/src/OMMDateTime.cpp b/plugins/Satellites/src/OMMDateTime.cpp index 2c8f9e6bc194bc..58740c55edc18d 100644 --- a/plugins/Satellites/src/OMMDateTime.cpp +++ b/plugins/Satellites/src/OMMDateTime.cpp @@ -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: diff --git a/plugins/Satellites/src/OMMDateTime.hpp b/plugins/Satellites/src/OMMDateTime.hpp index 81230a516c609d..e88d1279bf3a71 100644 --- a/plugins/Satellites/src/OMMDateTime.hpp +++ b/plugins/Satellites/src/OMMDateTime.hpp @@ -34,10 +34,13 @@ #include #include +#include class OMMDateTime { public: + typedef QSharedPointer ShPtr; + enum Type { STR_TLE, STR_ISO8601 @@ -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; } diff --git a/plugins/Satellites/src/omm.cpp b/plugins/Satellites/src/omm.cpp index a7cb04f0986d66..51f47fa2913a4e 100644 --- a/plugins/Satellites/src/omm.cpp +++ b/plugins/Satellites/src/omm.cpp @@ -1,4 +1,5 @@ /* + * Stellarium * Copyright (C) 2023 Andy Kirkham * * This program is free software; you can redistribute it and/or @@ -23,8 +24,6 @@ #include "OMM.hpp" -namespace PluginSatellites { - OMM::OMM() { m_source_type = SourceType::Invalid; @@ -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) @@ -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() @@ -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(); @@ -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 NORAD_CAT_ID(2,5); static QPair CLASSIFICATION_TYPE(7,1); static QPair OBJECT_ID(9, 8); +static QPair EPOCH(18, 14); static QPair EPOCH_YEAR(18, 2); static QPair EPOCH_DAY(20, 12); static QPair MEAN_MOTION_DOT(33, 10); static QPair MEAN_MOTION_DDOT(44, 8); static QPair BSTAR(53, 8); +static QPair EPHEMERIS_TYPE(62, 1); +static QPair 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 INCLINATION(8, 8); @@ -153,25 +181,18 @@ static QPair MEAN_ANOMALY(43, 8); static QPair MEAN_MOTION(52, 11); static QPair 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 diff --git a/plugins/Satellites/src/omm.hpp b/plugins/Satellites/src/omm.hpp index 4106bf937fbda1..cd20477d519a99 100644 --- a/plugins/Satellites/src/omm.hpp +++ b/plugins/Satellites/src/omm.hpp @@ -26,7 +26,7 @@ #include #include -namespace PluginSatellites { +#include "OMMDateTime.hpp" class OMM { @@ -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; } @@ -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; @@ -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{}; @@ -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 diff --git a/plugins/Satellites/src/test/testOMM.cpp b/plugins/Satellites/src/test/testOMM.cpp index 22586d0c92504f..43e37611c0ca1e 100644 --- a/plugins/Satellites/src/test/testOMM.cpp +++ b/plugins/Satellites/src/test/testOMM.cpp @@ -1,4 +1,5 @@ /* + * Stellarium * Copyright (C) 2023 Andy Kirkham * * This program is free software; you can redistribute it and/or @@ -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() @@ -61,10 +99,10 @@ void TestOMM::testXMLread() QVector expectNorad = { 25544, 43557, 47853 }; - QVector expectEpoch = { - QString("2023-07-06T08:17:36.314016"), - QString("2023-07-06T01:58:30.910944"), - QString("2023-07-04T18:34:04.881504") + QVector expectEpoch = { + 2460135.906404059846, + 2460135.906404059846, + 2460135.906404059846 }; int idx = 0; bool testContinue = true; @@ -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(); diff --git a/plugins/Satellites/src/test/testOMM.hpp b/plugins/Satellites/src/test/testOMM.hpp index 32744dfad4640b..ebbe38a08b712e 100644 --- a/plugins/Satellites/src/test/testOMM.hpp +++ b/plugins/Satellites/src/test/testOMM.hpp @@ -1,4 +1,5 @@ /* + * Stellarium * Copyright (C) 2023 Andy Kirkham * * This program is free software; you can redistribute it and/or @@ -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 diff --git a/plugins/Satellites/src/test/testOMMDateTime.cpp b/plugins/Satellites/src/test/testOMMDateTime.cpp index 069a8fc5f3e05c..3b02a704a68810 100644 --- a/plugins/Satellites/src/test/testOMMDateTime.cpp +++ b/plugins/Satellites/src/test/testOMMDateTime.cpp @@ -1,4 +1,5 @@ /* + * Stellarium * Copyright (C) 2023 Andy Kirkham * * This program is free software; you can redistribute it and/or @@ -28,9 +29,9 @@ void TestOMMDateTime::testEpoch_DEFAULT() OMMDateTime dut(epoch); // Assume TLE formatted string for ctor. #ifdef _DEBUG qDebug() << "2023-07-10T09:45:13.310784"; - qDebug() << std::fixed << qSetRealNumberPrecision(16) << dut.getJulian(); + qDebug() << std::fixed << qSetRealNumberPrecision(20) << dut.getJulian(); #endif - QVERIFY(dut.getJulian() == 2460135.90640406); + QCOMPARE(dut.getJulian(), 2460135.906404059846); } void TestOMMDateTime::testEpoch_TLE() @@ -39,9 +40,9 @@ void TestOMMDateTime::testEpoch_TLE() OMMDateTime dut(epoch, OMMDateTime::STR_TLE); #ifdef _DEBUG qDebug() << "2023-07-10T09:45:13.310784"; - qDebug() << std::fixed << qSetRealNumberPrecision(16) << dut.getJulian(); + qDebug() << std::fixed << qSetRealNumberPrecision(20) << dut.getJulian(); #endif - QVERIFY(dut.getJulian() == 2460135.90640406); + QCOMPARE(dut.getJulian(), 2460135.906404059846); } void TestOMMDateTime::testEpoch_ISO() @@ -50,8 +51,8 @@ void TestOMMDateTime::testEpoch_ISO() OMMDateTime dut(epoch, OMMDateTime::STR_ISO8601); #ifdef _DEBUG qDebug() << "2023-07-10T09:45:13.310784"; - qDebug() << std::fixed << qSetRealNumberPrecision(16) << dut.getJulian(); + qDebug() << std::fixed << qSetRealNumberPrecision(20) << dut.getJulian(); #endif - QVERIFY(dut.getJulian() == 2460135.90640406); + QCOMPARE(dut.getJulian(), 2460135.906404059846); } diff --git a/plugins/Satellites/src/test/test_data.xml b/plugins/Satellites/src/test/test_data.xml index 7cc453bad1c39c..60a80c44ceafdd 100644 --- a/plugins/Satellites/src/test/test_data.xml +++ b/plugins/Satellites/src/test/test_data.xml @@ -16,7 +16,7 @@ - 2023-07-06T08:17:36.314016 + 2023-07-10T09:45:13.310784 15.49560249 .0000373 51.6398 @@ -55,7 +55,7 @@ - 2023-07-06T01:58:30.910944 + 2023-07-10T09:45:13.310784 15.80461782 .0001004 51.6230 @@ -94,7 +94,7 @@ - 2023-07-04T18:34:04.881504 + 2023-07-10T09:45:13.310784 15.68894735 .0002499 51.6338