mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-03-25 05:38:39 -04:00
Satellite Tracker updates.
Add support for replaying of passes in the past, where current time is determined from File Input device. Add latitude and longitude to satellite data table. Update ground track generation to better work with 3D map. Add support for 3D models. Add Cubesat image for 2D map. Send LOS to other plugins, when no device settings are setup. Pass TLEs to other plugins, so they can use a consistent copy for replays.
This commit is contained in:
parent
635dbe4571
commit
04aed0b3b3
@ -81,3 +81,8 @@ if(WIN32)
|
||||
include(DeployQt)
|
||||
windeployqt(${TARGET_NAME} ${SDRANGEL_BINARY_BIN_DIR} ${PROJECT_SOURCE_DIR}/aprs)
|
||||
endif()
|
||||
|
||||
# Install debug symbols
|
||||
if (WIN32)
|
||||
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
|
||||
endif()
|
||||
|
@ -103,6 +103,8 @@ On the Settings tab, you can set:
|
||||
|
||||
On the TLEs tab, you can provide a list of URL from which satellite Two Line Element files can be downloaded from.
|
||||
TLE files contain the orbital parameters for a satellite and are required in order to be able to calculate a satellites position.
|
||||
TLEs for may satellites can be obtained from https://www.celestrak.com/NORAD/elements/
|
||||
To use a TLE file on a local disk, use a URL such as file:my_tle.txt
|
||||
|
||||

|
||||
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "dsp/dspengine.h"
|
||||
#include "util/httpdownloadmanager.h"
|
||||
#include "settings/serializable.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "feature/featurewebapiutils.h"
|
||||
|
||||
#include "satellitetrackerworker.h"
|
||||
#include "satellitetracker.h"
|
||||
@ -76,6 +78,14 @@ void SatelliteTracker::start()
|
||||
{
|
||||
qDebug("SatelliteTracker::start");
|
||||
|
||||
if (m_settings.m_replayEnabled)
|
||||
{
|
||||
m_startedDateTime = QDateTime::currentDateTimeUtc();
|
||||
if (m_settings.m_sendTimeToMap) {
|
||||
FeatureWebAPIUtils::mapSetDateTime(currentDateTime());
|
||||
}
|
||||
}
|
||||
|
||||
m_worker->reset();
|
||||
m_worker->setMessageQueueToFeature(getInputMessageQueue());
|
||||
m_worker->setMessageQueueToGUI(getMessageQueueToGUI());
|
||||
@ -1066,18 +1076,40 @@ void SatelliteTracker::updateSatData()
|
||||
qDebug() << "SatelliteTracker::updateSatData: update in progress";
|
||||
}
|
||||
|
||||
// Redirect requests for current time via these methods, so it can be adjusted when testing
|
||||
|
||||
/// Redirect requests for current time via these methods, for replays
|
||||
QDateTime SatelliteTracker::currentDateTimeUtc()
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTimeUtc();
|
||||
//now = now.addSecs(26*60);
|
||||
return now;
|
||||
if (m_settings.m_replayEnabled)
|
||||
{
|
||||
if (m_settings.m_useFileInputTime)
|
||||
{
|
||||
QString dateTimeStr;
|
||||
if (ChannelWebAPIUtils::getDeviceReportValue(0, "absoluteTime", dateTimeStr))
|
||||
{
|
||||
return QDateTime::fromString(dateTimeStr, Qt::ISODateWithMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QDateTime::currentDateTimeUtc();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTimeUtc();
|
||||
return m_settings.m_replayStartDateTime.addSecs(m_startedDateTime.secsTo(now));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QDateTime::currentDateTimeUtc();
|
||||
}
|
||||
}
|
||||
|
||||
QDateTime SatelliteTracker::currentDateTime()
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
//now = now.addSecs(26*60);
|
||||
return now;
|
||||
if (m_settings.m_replayEnabled) {
|
||||
return currentDateTimeUtc().toLocalTime();
|
||||
} else {
|
||||
return QDateTime::currentDateTime();
|
||||
}
|
||||
}
|
||||
|
@ -162,8 +162,8 @@ public:
|
||||
const QStringList& featureSettingsKeys,
|
||||
SWGSDRangel::SWGFeatureSettings& response);
|
||||
|
||||
static QDateTime currentDateTimeUtc();
|
||||
static QDateTime currentDateTime();
|
||||
QDateTime currentDateTimeUtc();
|
||||
QDateTime currentDateTime();
|
||||
|
||||
static const char* const m_featureIdURI;
|
||||
static const char* const m_featureId;
|
||||
@ -186,6 +186,8 @@ private:
|
||||
QHash<int, SatNogsSatellite *> m_satellitesId; // Same data as m_satellites, but hashed on id, rather than name
|
||||
bool m_firstUpdateSatData;
|
||||
|
||||
QDateTime m_startedDateTime;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void applySettings(const SatelliteTrackerSettings& settings, bool force = false);
|
||||
|
@ -2,5 +2,6 @@
|
||||
<qresource prefix="/satellitetracker/">
|
||||
<file>satellitetracker/iss-32.png</file>
|
||||
<file>satellitetracker/satellite-32.png</file>
|
||||
<file>satellitetracker/cubesat-32.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
BIN
plugins/feature/satellitetracker/satellitetracker/cubesat-32.png
Normal file
BIN
plugins/feature/satellitetracker/satellitetracker/cubesat-32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 390 B |
@ -268,7 +268,7 @@ SatelliteTrackerGUI::SatelliteTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *fea
|
||||
ui->passChart->setChart(&m_emptyChart);
|
||||
ui->passChart->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
ui->dateTime->setDateTime(SatelliteTracker::currentDateTime());
|
||||
ui->dateTime->setDateTime(m_satelliteTracker->currentDateTime());
|
||||
|
||||
// Use My Position from preferences, if none set
|
||||
if ((m_settings.m_latitude == 0.0) && (m_settings.m_longitude == 0.0)) {
|
||||
@ -604,7 +604,7 @@ void SatelliteTrackerGUI::updateTimeToAOS()
|
||||
ui->aos->setText("Now");
|
||||
else if (m_nextTargetAOS.isValid())
|
||||
{
|
||||
QDateTime currentTime = SatelliteTracker::currentDateTime();
|
||||
QDateTime currentTime = m_satelliteTracker->currentDateTime(); // FIXME: UTC
|
||||
int secondsToAOS = m_nextTargetAOS.toSecsSinceEpoch() - currentTime.toSecsSinceEpoch();
|
||||
if (secondsToAOS > 0)
|
||||
{
|
||||
@ -833,7 +833,7 @@ void SatelliteTrackerGUI::plotPolarChart()
|
||||
|
||||
QDateTime currentTime;
|
||||
if (m_settings.m_dateTime == "")
|
||||
currentTime = SatelliteTracker::currentDateTimeUtc();
|
||||
currentTime = m_satelliteTracker->currentDateTimeUtc();
|
||||
else if (m_settings.m_utc)
|
||||
currentTime = QDateTime::fromString(m_settings.m_dateTime, Qt::ISODateWithMs);
|
||||
else
|
||||
@ -863,7 +863,7 @@ void SatelliteTrackerGUI::plotPolarChart()
|
||||
// Possibly geostationary, just plot current position
|
||||
QDateTime currentTime;
|
||||
if (m_settings.m_dateTime == "")
|
||||
currentTime = SatelliteTracker::currentDateTimeUtc();
|
||||
currentTime = m_satelliteTracker->currentDateTimeUtc();
|
||||
else if (m_settings.m_utc)
|
||||
currentTime = QDateTime::fromString(m_settings.m_dateTime, Qt::ISODateWithMs);
|
||||
else
|
||||
@ -1004,6 +1004,8 @@ void SatelliteTrackerGUI::resizeTable()
|
||||
ui->satTable->setItem(row, SAT_COL_LOS, new QTableWidgetItem("+1 10:17"));
|
||||
ui->satTable->setItem(row, SAT_COL_MAX_EL, new QTableWidgetItem("90"));
|
||||
ui->satTable->setItem(row, SAT_COL_DIR, new QTableWidgetItem("^"));
|
||||
ui->satTable->setItem(row, SAT_COL_LATITUDE, new QTableWidgetItem("-90.0"));
|
||||
ui->satTable->setItem(row, SAT_COL_LONGITUDE, new QTableWidgetItem("-180.0"));
|
||||
ui->satTable->setItem(row, SAT_COL_ALT, new QTableWidgetItem("50000"));
|
||||
ui->satTable->setItem(row, SAT_COL_RANGE, new QTableWidgetItem("50000"));
|
||||
ui->satTable->setItem(row, SAT_COL_RANGE_RATE, new QTableWidgetItem("10.0"));
|
||||
@ -1125,7 +1127,8 @@ void SatelliteTrackerGUI::updateTable(SatelliteState *satState)
|
||||
}
|
||||
|
||||
// Text alignment
|
||||
for( int col : {SAT_COL_AZ, SAT_COL_EL, SAT_COL_TNE, SAT_COL_DUR, SAT_COL_MAX_EL,
|
||||
for (int col : {SAT_COL_AZ, SAT_COL_EL, SAT_COL_TNE, SAT_COL_DUR, SAT_COL_MAX_EL,
|
||||
SAT_COL_LATITUDE, SAT_COL_LONGITUDE,
|
||||
SAT_COL_ALT, SAT_COL_RANGE, SAT_COL_RANGE_RATE, SAT_COL_DOPPLER,
|
||||
SAT_COL_PATH_LOSS, SAT_COL_DELAY})
|
||||
items[col]->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
||||
@ -1143,7 +1146,7 @@ void SatelliteTrackerGUI::updateTable(SatelliteState *satState)
|
||||
if (satState->m_passes.size() > 0)
|
||||
{
|
||||
// Get number of days to AOS/LOS
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
QDateTime currentDateTime = m_satelliteTracker->currentDateTime();
|
||||
int daysToAOS = currentDateTime.daysTo(satState->m_passes[0]->m_aos);
|
||||
int daysToLOS = currentDateTime.daysTo(satState->m_passes[0]->m_los);
|
||||
if( satState->m_passes[ 0 ]->m_aos > currentDateTime )
|
||||
@ -1170,6 +1173,8 @@ void SatelliteTrackerGUI::updateTable(SatelliteState *satState)
|
||||
items[SAT_COL_MAX_EL]->setData(Qt::DisplayRole, QVariant());
|
||||
items[SAT_COL_DIR]->setText("");
|
||||
}
|
||||
items[SAT_COL_LATITUDE]->setData(Qt::DisplayRole, satState->m_latitude);
|
||||
items[SAT_COL_LONGITUDE]->setData(Qt::DisplayRole, satState->m_longitude);
|
||||
items[SAT_COL_ALT]->setData(Qt::DisplayRole, (int)round(satState->m_altitude));
|
||||
items[SAT_COL_RANGE]->setData(Qt::DisplayRole, (int)round(satState->m_range));
|
||||
items[SAT_COL_RANGE_RATE]->setData(Qt::DisplayRole, QString::number(satState->m_rangeRate, 'f', 3));
|
||||
@ -1184,6 +1189,7 @@ void SatelliteTrackerGUI::on_satTable_cellDoubleClicked(int row, int column)
|
||||
|
||||
QString sat = ui->satTable->item(row, SAT_COL_NAME)->text();
|
||||
FeatureWebAPIUtils::mapFind(sat);
|
||||
|
||||
}
|
||||
|
||||
// Columns in table reordered
|
||||
|
@ -93,6 +93,8 @@ private:
|
||||
SAT_COL_LOS,
|
||||
SAT_COL_MAX_EL,
|
||||
SAT_COL_DIR,
|
||||
SAT_COL_LATITUDE,
|
||||
SAT_COL_LONGITUDE,
|
||||
SAT_COL_ALT,
|
||||
SAT_COL_RANGE,
|
||||
SAT_COL_RANGE_RATE,
|
||||
|
@ -628,6 +628,16 @@
|
||||
<string>Direction of the next pass</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Latitude (°)</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Longitude (°)</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Alt (km)</string>
|
||||
|
@ -73,7 +73,9 @@ void SatelliteTrackerSettings::resetToDefaults()
|
||||
m_reverseAPIFeatureSetIndex = 0;
|
||||
m_reverseAPIFeatureIndex = 0;
|
||||
m_chartsDarkTheme = true;
|
||||
|
||||
m_replayEnabled = false;
|
||||
m_useFileInputTime = true;
|
||||
m_sendTimeToMap = true;
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++)
|
||||
{
|
||||
m_columnIndexes[i] = i;
|
||||
@ -121,10 +123,13 @@ QByteArray SatelliteTrackerSettings::serialize() const
|
||||
s.writeU32(34, m_reverseAPIFeatureSetIndex);
|
||||
s.writeU32(35, m_reverseAPIFeatureIndex);
|
||||
s.writeBool(36, m_chartsDarkTheme);
|
||||
|
||||
if (m_rollupState) {
|
||||
s.writeBlob(37, m_rollupState->serialize());
|
||||
}
|
||||
s.writeBool(38, m_replayEnabled);
|
||||
s.writeString(39, m_replayStartDateTime.toString(Qt::ISODate));
|
||||
s.writeBool(40, m_useFileInputTime);
|
||||
s.writeBool(41, m_sendTimeToMap);
|
||||
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
s.writeS32(100 + i, m_columnIndexes[i]);
|
||||
@ -204,12 +209,16 @@ bool SatelliteTrackerSettings::deserialize(const QByteArray& data)
|
||||
d.readU32(35, &utmp, 0);
|
||||
m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp;
|
||||
d.readBool(36, &m_chartsDarkTheme, true);
|
||||
|
||||
if (m_rollupState)
|
||||
{
|
||||
d.readBlob(37, &bytetmp);
|
||||
m_rollupState->deserialize(bytetmp);
|
||||
}
|
||||
d.readBool(38, &m_replayEnabled, false);
|
||||
d.readString(39, &strtmp);
|
||||
m_replayStartDateTime = QDateTime::fromString(strtmp, Qt::ISODate);
|
||||
d.readBool(40, &m_useFileInputTime, true);
|
||||
d.readBool(41, &m_sendTimeToMap, true);
|
||||
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
d.readS32(100 + i, &m_columnIndexes[i], i);
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
class Serializable;
|
||||
|
||||
#define SAT_COL_COLUMNS 16
|
||||
#define SAT_COL_COLUMNS 18
|
||||
|
||||
struct SatelliteTrackerSettings
|
||||
{
|
||||
@ -76,6 +76,10 @@ struct SatelliteTrackerSettings
|
||||
QString m_losCommand; //!< Command/script to execute on LOS
|
||||
bool m_chartsDarkTheme; //!< Set dark theme for charts (effective for GUI only)
|
||||
QHash<QString, QList<SatelliteDeviceSettings *> *> m_deviceSettings; //!< Settings for each device set for each satellite
|
||||
bool m_replayEnabled; //!< Replay a pass in the past, by setting date and time to m_replayStartDateTime
|
||||
QDateTime m_replayStartDateTime; //!< Time to start the replay at
|
||||
bool m_useFileInputTime; //!< Get time from FileInput device
|
||||
bool m_sendTimeToMap; //!< Send time to map when start pressed
|
||||
|
||||
int m_columnIndexes[SAT_COL_COLUMNS];//!< How the columns are ordered in the table
|
||||
int m_columnSizes[SAT_COL_COLUMNS]; //!< Size of the coumns in the table
|
||||
|
@ -51,6 +51,10 @@ SatelliteTrackerSettingsDialog::SatelliteTrackerSettingsDialog(SatelliteTrackerS
|
||||
item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsEnabled);
|
||||
ui->tles->addItem(item);
|
||||
}
|
||||
ui->replayEnabled->setChecked(settings->m_replayEnabled);
|
||||
ui->replayDateTime->setDateTime(settings->m_replayStartDateTime);
|
||||
ui->useFileInputTime->setChecked(settings->m_useFileInputTime);
|
||||
ui->sendTimeToMap->setChecked(settings->m_sendTimeToMap);
|
||||
}
|
||||
|
||||
SatelliteTrackerSettingsDialog::~SatelliteTrackerSettingsDialog()
|
||||
@ -95,7 +99,12 @@ void SatelliteTrackerSettingsDialog::accept()
|
||||
m_settings->m_utc = ui->utc->isChecked();
|
||||
m_settings->m_drawOnMap = ui->drawOnMap->isChecked();
|
||||
m_settings->m_tles.clear();
|
||||
for (int i = 0; i < ui->tles->count(); i++)
|
||||
for (int i = 0; i < ui->tles->count(); i++) {
|
||||
m_settings->m_tles.append(ui->tles->item(i)->text());
|
||||
}
|
||||
m_settings->m_replayEnabled = ui->replayEnabled->isChecked();
|
||||
m_settings->m_replayStartDateTime = ui->replayDateTime->dateTime();
|
||||
m_settings->m_useFileInputTime = ui->useFileInputTime->isChecked();
|
||||
m_settings->m_sendTimeToMap = ui->sendTimeToMap->isChecked();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@ -495,6 +494,91 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="replayTab">
|
||||
<attribute name="title">
|
||||
<string>Replay</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="replaceEnabledLabel">
|
||||
<property name="text">
|
||||
<string>Enable replay</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="replayEnabled">
|
||||
<property name="toolTip">
|
||||
<string>Enable replay of a pass in the past, by starting with the chosen date and time</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="useFileInputTimeLabel">
|
||||
<property name="text">
|
||||
<string>Get time from FileInput device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="useFileInputTime">
|
||||
<property name="toolTip">
|
||||
<string>Get the time from the FileInput device</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="replayDateTimeLabel">
|
||||
<property name="text">
|
||||
<string>Start date and time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDateTimeEdit" name="replayDateTime">
|
||||
<property name="toolTip">
|
||||
<string>Set date and time to the displayed value when Satellite Tracker's start button is pressed</string>
|
||||
</property>
|
||||
<property name="date">
|
||||
<date>
|
||||
<year>2021</year>
|
||||
<month>1</month>
|
||||
<day>1</day>
|
||||
</date>
|
||||
</property>
|
||||
<property name="displayFormat">
|
||||
<string>dd/MM/yyyy HH:mm:ss</string>
|
||||
</property>
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="sendTimeToMapLabel">
|
||||
<property name="text">
|
||||
<string>Send time to map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="sendTimeToMap">
|
||||
<property name="toolTip">
|
||||
<string>Send time to Map feature when Satellite Tracker's start button is pressed</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -40,7 +40,8 @@ static DateTime qDateTimeToDateTime(QDateTime qdt)
|
||||
QDateTime utc = qdt.toUTC();
|
||||
QDate date = utc.date();
|
||||
QTime time = utc.time();
|
||||
DateTime dt(date.year(), date.month(), date.day(), time.hour(), time.minute(), time.second());
|
||||
DateTime dt;
|
||||
dt.Initialise(date.year(), date.month(), date.day(), time.hour(), time.minute(), time.second(), time.msec() * 1000);
|
||||
return dt;
|
||||
}
|
||||
|
||||
@ -49,7 +50,8 @@ static DateTime qDateTimeToDateTime(QDateTime qdt)
|
||||
void getGroundTrack(QDateTime dateTime,
|
||||
const QString& tle0, const QString& tle1, const QString& tle2,
|
||||
int steps, bool forward,
|
||||
QList<QGeoCoordinate *>& coordinates)
|
||||
QList<QGeoCoordinate *>& coordinates,
|
||||
QList<QDateTime *>& coordinateDateTimes)
|
||||
{
|
||||
Tle tle = Tle(tle0.toStdString(), tle1.toStdString(), tle2.toStdString());
|
||||
SGP4 sgp4(tle);
|
||||
@ -57,7 +59,13 @@ void getGroundTrack(QDateTime dateTime,
|
||||
double periodMins;
|
||||
double timeStep;
|
||||
|
||||
// Note map doesn't support paths wrapping around Earth
|
||||
// For 3D map, we want to quantize to minutes, so we replace previous
|
||||
// position data, rather than insert additional positions alongside the old
|
||||
// which can result is the camera view jumping around
|
||||
dateTime = QDateTime(dateTime.date(), QTime(dateTime.time().hour(), dateTime.time().minute()));
|
||||
|
||||
// Note 2D map doesn't support paths wrapping around Earth several times
|
||||
// So we just have a slight overlap here, with the future track being longer
|
||||
DateTime currentTime = qDateTimeToDateTime(dateTime);
|
||||
DateTime endTime;
|
||||
if (forward)
|
||||
@ -73,7 +81,16 @@ void getGroundTrack(QDateTime dateTime,
|
||||
timeStep = -periodMins / (steps * 0.4);
|
||||
}
|
||||
|
||||
coordinates.clear();
|
||||
// Quantize time step to 30 seconds
|
||||
timeStep *= 2.0;
|
||||
if (timeStep > 0.0) {
|
||||
timeStep = std::max(timeStep, 1.0);
|
||||
} else if (timeStep < 0.0) {
|
||||
timeStep = std::min(timeStep, -1.0);
|
||||
}
|
||||
timeStep = round(timeStep);
|
||||
timeStep /= 2.0;
|
||||
|
||||
while ((forward && (currentTime < endTime)) || (!forward && (currentTime > endTime)))
|
||||
{
|
||||
// Calculate satellite position
|
||||
@ -86,7 +103,11 @@ void getGroundTrack(QDateTime dateTime,
|
||||
Units::radiansToDegrees(geo.longitude),
|
||||
geo.altitude * 1000.0);
|
||||
coordinates.append(coord);
|
||||
// Map is stretched at poles, so use finer steps
|
||||
|
||||
QDateTime *coordDateTime = new QDateTime(dateTimeToQDateTime(currentTime));
|
||||
coordinateDateTimes.append(coordDateTime);
|
||||
|
||||
// 2D map is stretched at poles, so use finer steps
|
||||
if (std::abs(Units::radiansToDegrees(geo.latitude)) >= 70)
|
||||
currentTime = currentTime.AddMinutes(timeStep/4);
|
||||
else
|
||||
@ -485,9 +506,15 @@ void getSatelliteState(QDateTime dateTime,
|
||||
}
|
||||
|
||||
qDeleteAll(satState->m_groundTrack);
|
||||
satState->m_groundTrack.clear();
|
||||
qDeleteAll(satState->m_groundTrackDateTime);
|
||||
satState->m_groundTrackDateTime.clear();
|
||||
qDeleteAll(satState->m_predictedGroundTrack);
|
||||
getGroundTrack(dateTime, tle0, tle1, tle2, groundTrackSteps, false, satState->m_groundTrack);
|
||||
getGroundTrack(dateTime, tle0, tle1, tle2, groundTrackSteps, true, satState->m_predictedGroundTrack);
|
||||
satState->m_predictedGroundTrack.clear();
|
||||
qDeleteAll(satState->m_predictedGroundTrackDateTime);
|
||||
satState->m_predictedGroundTrackDateTime.clear();
|
||||
getGroundTrack(dateTime, tle0, tle1, tle2, groundTrackSteps, false, satState->m_groundTrack, satState->m_groundTrackDateTime);
|
||||
getGroundTrack(dateTime, tle0, tle1, tle2, groundTrackSteps, true, satState->m_predictedGroundTrack, satState->m_predictedGroundTrackDateTime);
|
||||
}
|
||||
catch (SatelliteException& se)
|
||||
{
|
||||
|
@ -47,7 +47,9 @@ struct SatelliteState {
|
||||
double m_period;
|
||||
QList<SatellitePass *> m_passes;
|
||||
QList<QGeoCoordinate *> m_groundTrack;
|
||||
QList<QDateTime *> m_groundTrackDateTime;
|
||||
QList<QGeoCoordinate *> m_predictedGroundTrack;
|
||||
QList<QDateTime *> m_predictedGroundTrackDateTime;
|
||||
};
|
||||
|
||||
void getGroundTrack(QDateTime dateTime,
|
||||
|
@ -237,13 +237,17 @@ void SatelliteTrackerWorker::removeFromMap(QString id)
|
||||
MessagePipes& messagePipes = MainCore::instance()->getMessagePipes();
|
||||
QList<MessageQueue*> *mapMessageQueues = messagePipes.getMessageQueues(m_satelliteTracker, "mapitems");
|
||||
if (mapMessageQueues)
|
||||
sendToMap(mapMessageQueues, id, "", "", 0.0, 0.0, 0.0, 0.0, nullptr, nullptr);
|
||||
sendToMap(mapMessageQueues, id, "", "", "", 0.0f, 0.0, 0.0, 0.0, 0.0, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void SatelliteTrackerWorker::sendToMap(QList<MessageQueue*> *mapMessageQueues,
|
||||
QString name, QString image, QString text,
|
||||
QString name, QString image, QString model, QString text,
|
||||
float labelOffset,
|
||||
double lat, double lon, double altitude, double rotation,
|
||||
QList<QGeoCoordinate *> *track, QList<QGeoCoordinate *> *predictedTrack)
|
||||
QList<QGeoCoordinate *> *track,
|
||||
QList<QDateTime *> *trackDateTime,
|
||||
QList<QGeoCoordinate *> *predictedTrack,
|
||||
QList<QDateTime *> *predictedTrackDateTime)
|
||||
{
|
||||
QList<MessageQueue*>::iterator it = mapMessageQueues->begin();
|
||||
|
||||
@ -257,7 +261,11 @@ void SatelliteTrackerWorker::sendToMap(QList<MessageQueue*> *mapMessageQueues,
|
||||
swgMapItem->setImage(new QString(image));
|
||||
swgMapItem->setImageRotation(rotation);
|
||||
swgMapItem->setText(new QString(text));
|
||||
swgMapItem->setImageMinZoom(0);
|
||||
swgMapItem->setModel(new QString(model));
|
||||
swgMapItem->setFixedPosition(false);
|
||||
swgMapItem->setOrientation(0);
|
||||
swgMapItem->setLabel(new QString(name));
|
||||
swgMapItem->setLabelAltitudeOffset(labelOffset);
|
||||
if (track != nullptr)
|
||||
{
|
||||
QList<SWGSDRangel::SWGMapCoordinate *> *mapTrack = new QList<SWGSDRangel::SWGMapCoordinate *>();
|
||||
@ -268,6 +276,7 @@ void SatelliteTrackerWorker::sendToMap(QList<MessageQueue*> *mapMessageQueues,
|
||||
p->setLatitude(c->latitude());
|
||||
p->setLongitude(c->longitude());
|
||||
p->setAltitude(c->altitude());
|
||||
p->setDateTime(new QString(trackDateTime->at(i)->toString(Qt::ISODate)));
|
||||
mapTrack->append(p);
|
||||
}
|
||||
swgMapItem->setTrack(mapTrack);
|
||||
@ -282,6 +291,7 @@ void SatelliteTrackerWorker::sendToMap(QList<MessageQueue*> *mapMessageQueues,
|
||||
p->setLatitude(c->latitude());
|
||||
p->setLongitude(c->longitude());
|
||||
p->setAltitude(c->altitude());
|
||||
p->setDateTime(new QString(predictedTrackDateTime->at(i)->toString(Qt::ISODate)));
|
||||
mapTrack->append(p);
|
||||
}
|
||||
swgMapItem->setPredictedTrack(mapTrack);
|
||||
@ -297,7 +307,7 @@ void SatelliteTrackerWorker::update()
|
||||
// Get date and time to calculate position at
|
||||
QDateTime qdt;
|
||||
if (m_settings.m_dateTime == "")
|
||||
qdt = SatelliteTracker::currentDateTimeUtc();
|
||||
qdt = m_satelliteTracker->currentDateTimeUtc();
|
||||
else if (m_settings.m_utc)
|
||||
qdt = QDateTime::fromString(m_settings.m_dateTime, Qt::ISODateWithMs);
|
||||
else
|
||||
@ -333,6 +343,7 @@ void SatelliteTrackerWorker::update()
|
||||
// Do we have a new AOS?
|
||||
if ((satWorkerState->m_aos != satWorkerState->m_satState.m_passes[0]->m_aos) || (satWorkerState->m_los != satWorkerState->m_satState.m_passes[0]->m_los))
|
||||
{
|
||||
qDebug() << "SatelliteTrackerWorker: Current time: " << qdt.toString(Qt::ISODateWithMs);
|
||||
qDebug() << "SatelliteTrackerWorker: New AOS: " << name << " new: " << satWorkerState->m_satState.m_passes[0]->m_aos << " old: " << satWorkerState->m_aos;
|
||||
qDebug() << "SatelliteTrackerWorker: New LOS: " << name << " new: " << satWorkerState->m_satState.m_passes[0]->m_los << " old: " << satWorkerState->m_los;
|
||||
satWorkerState->m_aos = satWorkerState->m_satState.m_passes[0]->m_aos;
|
||||
@ -356,14 +367,15 @@ void SatelliteTrackerWorker::update()
|
||||
if (satWorkerState->m_losTimer.isActive()) {
|
||||
qDebug() << "SatelliteTrackerWorker::update m_losTimer.remainingTime: " << satWorkerState->m_losTimer.remainingTime();
|
||||
}
|
||||
// We can detect a new AOS for a satellite, a little bit before the LOS has occured, presumably
|
||||
// because the calculations aren't accurate to fractions of a second. Allow for 1s here
|
||||
if (satWorkerState->m_losTimer.isActive() && (satWorkerState->m_losTimer.remainingTime() <= 1000))
|
||||
// We can detect a new AOS for a satellite, a little bit before the LOS has occured
|
||||
// Allow for 5s here (1s doesn't appear to be enough in some cases)
|
||||
if (satWorkerState->m_losTimer.isActive() && (satWorkerState->m_losTimer.remainingTime() <= 5000))
|
||||
{
|
||||
satWorkerState->m_losTimer.stop();
|
||||
// LOS hasn't been called yet - do so, before we reset timer
|
||||
los(satWorkerState);
|
||||
}
|
||||
qDebug() << "SatelliteTrackerWorker:: Interval to LOS " << (satWorkerState->m_los.toMSecsSinceEpoch() - qdt.toMSecsSinceEpoch());
|
||||
satWorkerState->m_losTimer.setInterval(satWorkerState->m_los.toMSecsSinceEpoch() - qdt.toMSecsSinceEpoch());
|
||||
satWorkerState->m_losTimer.setSingleShot(true);
|
||||
satWorkerState->m_losTimer.start();
|
||||
@ -417,11 +429,29 @@ void SatelliteTrackerWorker::update()
|
||||
QList<MessageQueue*> *mapMessageQueues = messagePipes.getMessageQueues(m_satelliteTracker, "mapitems");
|
||||
if (mapMessageQueues)
|
||||
{
|
||||
const QStringList cubeSats({"AISAT-1", "FOX-1B", "FOX-1C", "FOX-1D", "FOX-1E", "FUNCUBE-1", "NO-84"});
|
||||
QString image;
|
||||
QString model;
|
||||
float labelOffset;
|
||||
|
||||
if (sat->m_name == "ISS")
|
||||
{
|
||||
image = "qrc:///satellitetracker/satellitetracker/iss-32.png";
|
||||
model = "iss.glb";
|
||||
labelOffset = 15.0f;
|
||||
}
|
||||
else if (cubeSats.contains(sat->m_name))
|
||||
{
|
||||
image = "qrc:///satellitetracker/satellitetracker/cubesat-32.png";
|
||||
model = "cubesat.glb";
|
||||
labelOffset = 0.7f;
|
||||
}
|
||||
else
|
||||
{
|
||||
image = "qrc:///satellitetracker/satellitetracker/satellite-32.png";
|
||||
model = "satellite.glb";
|
||||
labelOffset = 2.5f;
|
||||
}
|
||||
|
||||
QString text = QString("Name: %1\nAltitude: %2 km\nRange: %3 km\nRange rate: %4 km/s\nSpeed: %5 km/h\nPeriod: %6 mins")
|
||||
.arg(sat->m_name)
|
||||
@ -456,10 +486,11 @@ void SatelliteTrackerWorker::update()
|
||||
.arg(QChar(0xb0));
|
||||
}
|
||||
|
||||
sendToMap(mapMessageQueues, sat->m_name, image, text,
|
||||
sendToMap(mapMessageQueues, sat->m_name, image, model, text, labelOffset,
|
||||
satWorkerState->m_satState.m_latitude, satWorkerState->m_satState.m_longitude,
|
||||
satWorkerState->m_satState.m_altitude * 1000.0, 0,
|
||||
&satWorkerState->m_satState.m_groundTrack, &satWorkerState->m_satState.m_predictedGroundTrack);
|
||||
&satWorkerState->m_satState.m_groundTrack, &satWorkerState->m_satState.m_groundTrackDateTime,
|
||||
&satWorkerState->m_satState.m_predictedGroundTrack, &satWorkerState->m_satState.m_predictedGroundTrackDateTime);
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,7 +526,7 @@ void SatelliteTrackerWorker::aos(SatWorkerState *satWorkerState)
|
||||
SatWorkerState *targetSatWorkerState = m_workerState.value(m_settings.m_target);
|
||||
int currentTargetIdx = m_settings.m_satellites.indexOf(m_settings.m_target);
|
||||
int newTargetIdx = m_settings.m_satellites.indexOf(satWorkerState->m_name);
|
||||
if ((newTargetIdx < currentTargetIdx) || !targetSatWorkerState->hasAOS())
|
||||
if ((newTargetIdx < currentTargetIdx) || !targetSatWorkerState->hasAOS(m_satelliteTracker->currentDateTimeUtc()))
|
||||
{
|
||||
// Stop doppler correction for current target
|
||||
if (m_workerState.contains(m_settings.m_target))
|
||||
@ -646,7 +677,12 @@ void SatelliteTrackerWorker::applyDeviceAOSSettings(const QString& name)
|
||||
|
||||
// Send AOS message to channels/features
|
||||
SatWorkerState *satWorkerState = m_workerState.value(name);
|
||||
ChannelWebAPIUtils::satelliteAOS(name, satWorkerState->m_satState.m_passes[0]->m_northToSouth);
|
||||
SatNogsSatellite *sat = m_satellites.value(satWorkerState->m_name);
|
||||
// APT needs current time, for current position of satellite, not start of pass which may be in the past
|
||||
// if the satellite was already visible when Sat Tracker was started
|
||||
ChannelWebAPIUtils::satelliteAOS(name, satWorkerState->m_satState.m_passes[0]->m_northToSouth,
|
||||
sat->m_tle->toString(),
|
||||
m_satelliteTracker->currentDateTimeUtc());
|
||||
FeatureWebAPIUtils::satelliteAOS(name, satWorkerState->m_aos, satWorkerState->m_los);
|
||||
|
||||
// Start Doppler correction, if needed
|
||||
@ -677,6 +713,7 @@ void SatelliteTrackerWorker::applyDeviceAOSSettings(const QString& name)
|
||||
}
|
||||
if (requiresDoppler)
|
||||
{
|
||||
qDebug() << "SatelliteTrackerWorker::applyDeviceAOSSettings: requiresDoppler";
|
||||
satWorkerState->m_dopplerTimer.setInterval(m_settings.m_dopplerPeriod * 1000);
|
||||
satWorkerState->m_dopplerTimer.start();
|
||||
connect(&satWorkerState->m_dopplerTimer, &QTimer::timeout, [this, satWorkerState]() {
|
||||
@ -705,7 +742,10 @@ void SatelliteTrackerWorker::applyDeviceAOSSettings(const QString& name)
|
||||
{
|
||||
// Send AOS message to channels/features
|
||||
SatWorkerState *satWorkerState = m_workerState.value(name);
|
||||
ChannelWebAPIUtils::satelliteAOS(name, satWorkerState->m_satState.m_passes[0]->m_northToSouth);
|
||||
SatNogsSatellite *sat = m_satellites.value(satWorkerState->m_name);
|
||||
ChannelWebAPIUtils::satelliteAOS(name, satWorkerState->m_satState.m_passes[0]->m_northToSouth,
|
||||
sat->m_tle->toString(),
|
||||
m_satelliteTracker->currentDateTimeUtc());
|
||||
FeatureWebAPIUtils::satelliteAOS(name, satWorkerState->m_aos, satWorkerState->m_los);
|
||||
}
|
||||
|
||||
@ -750,7 +790,7 @@ void SatelliteTrackerWorker::doppler(SatWorkerState *satWorkerState)
|
||||
|
||||
void SatelliteTrackerWorker::los(SatWorkerState *satWorkerState)
|
||||
{
|
||||
qDebug() << "SatelliteTrackerWorker::los " << satWorkerState->m_name;
|
||||
qDebug() << "SatelliteTrackerWorker::los " << satWorkerState->m_name << " target: " << m_settings.m_target;
|
||||
|
||||
// Indicate LOS to GUI
|
||||
if (getMessageQueueToGUI())
|
||||
@ -776,6 +816,10 @@ void SatelliteTrackerWorker::los(SatWorkerState *satWorkerState)
|
||||
QProcess::startDetached(program, allArgs);
|
||||
}
|
||||
|
||||
// Send LOS message to channels/features
|
||||
ChannelWebAPIUtils::satelliteLOS(satWorkerState->m_name);
|
||||
FeatureWebAPIUtils::satelliteLOS(satWorkerState->m_name);
|
||||
|
||||
if (m_settings.m_deviceSettings.contains(satWorkerState->m_name))
|
||||
{
|
||||
QList<SatelliteTrackerSettings::SatelliteDeviceSettings *> *m_deviceSettingsList = m_settings.m_deviceSettings.value(satWorkerState->m_name);
|
||||
@ -791,10 +835,6 @@ void SatelliteTrackerWorker::los(SatWorkerState *satWorkerState)
|
||||
}
|
||||
}
|
||||
|
||||
// Send LOS message to channels/features
|
||||
ChannelWebAPIUtils::satelliteLOS(satWorkerState->m_name);
|
||||
FeatureWebAPIUtils::satelliteLOS(satWorkerState->m_name);
|
||||
|
||||
// Stop acquisition
|
||||
for (int i = 0; i < m_deviceSettingsList->size(); i++)
|
||||
{
|
||||
@ -834,7 +874,7 @@ void SatelliteTrackerWorker::los(SatWorkerState *satWorkerState)
|
||||
if (m_workerState.contains(m_settings.m_satellites[i]))
|
||||
{
|
||||
SatWorkerState *newSatWorkerState = m_workerState.value(m_settings.m_satellites[i]);
|
||||
if (newSatWorkerState->hasAOS())
|
||||
if (newSatWorkerState->hasAOS(m_satelliteTracker->currentDateTimeUtc()))
|
||||
{
|
||||
qDebug() << "SatelliteTrackerWorker::los - autoTarget setting " << m_settings.m_satellites[i];
|
||||
m_settings.m_target = m_settings.m_satellites[i];
|
||||
@ -852,8 +892,7 @@ void SatelliteTrackerWorker::los(SatWorkerState *satWorkerState)
|
||||
m_recalculatePasses = true;
|
||||
}
|
||||
|
||||
bool SatWorkerState::hasAOS()
|
||||
bool SatWorkerState::hasAOS(const QDateTime& currentTime)
|
||||
{
|
||||
QDateTime currentTime = SatelliteTracker::currentDateTimeUtc();
|
||||
return (m_aos <= currentTime) && (m_los > currentTime);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
m_satState.m_name = name;
|
||||
}
|
||||
|
||||
bool hasAOS();
|
||||
bool hasAOS(const QDateTime& currentTime);
|
||||
|
||||
protected:
|
||||
QString m_name; // Name of the satellite
|
||||
@ -122,9 +122,13 @@ private:
|
||||
void applySettings(const SatelliteTrackerSettings& settings, bool force = false);
|
||||
MessageQueue *getMessageQueueToGUI() { return m_msgQueueToGUI; }
|
||||
void removeFromMap(QString id);
|
||||
void sendToMap(QList<MessageQueue*> *mapMessageQueues, QString id, QString image, QString text,
|
||||
void sendToMap(QList<MessageQueue*> *mapMessageQueues, QString id, QString image, QString model, QString text,
|
||||
float labelOffset,
|
||||
double lat, double lon, double altitude, double rotation,
|
||||
QList<QGeoCoordinate *> *track = nullptr, QList<QGeoCoordinate *> *predictedTrack = nullptr);
|
||||
QList<QGeoCoordinate *> *track = nullptr,
|
||||
QList<QDateTime *> *trackDateTime = nullptr,
|
||||
QList<QGeoCoordinate *> *predictedTrack = nullptr,
|
||||
QList<QDateTime *> *predictedTrackDateTime = nullptr);
|
||||
void applyDeviceAOSSettings(const QString& name);
|
||||
void startStopSinks(bool start);
|
||||
void calculateRotation(SatWorkerState *satWorkerState);
|
||||
|
@ -115,6 +115,11 @@ struct SatNogsTLE {
|
||||
m_tle2 = tle2;
|
||||
}
|
||||
|
||||
QString toString() const
|
||||
{
|
||||
return m_tle0 + "\n" + m_tle1 + "\n" + m_tle2 + "\n";
|
||||
}
|
||||
|
||||
static QList<SatNogsTLE *> createList(QJsonArray array)
|
||||
{
|
||||
QList<SatNogsTLE *> list;
|
||||
|
Loading…
Reference in New Issue
Block a user