satdump/src-interface/recorder/tracking/tracking_widget_autotrack.cpp

402 lines
19 KiB
C++

#include "tracking_widget.h"
#include "common/utils.h"
#include "logger.h"
#include "imgui/imgui.h"
#include "common/tracking/tle.h"
#include "core/module.h"
#include "core/style.h"
#include "main_ui.h"
namespace satdump
{
void TrackingWidget::processAutotrack()
{
if (autotrack_engaged)
{
upcoming_satellite_passes_mtx.lock();
if (upcoming_satellite_passes_sel.size() > 0)
{
if (!autotrack_pass_has_started && getTime() > upcoming_satellite_passes_sel[0].aos_time)
{
logger->critical("AOS!!!!!!!!!!!!!! %d", upcoming_satellite_passes_sel[0].norad);
tracking::TrackedObject obj;
for (auto &v : enabled_satellites)
if (v.norad == upcoming_satellite_passes_sel[0].norad)
obj = v;
aos_callback(upcoming_satellite_passes_sel[0], obj);
autotrack_pass_has_started = true;
}
}
if (getTime() > upcoming_satellite_passes_sel[0].los_time && upcoming_satellite_passes_sel.size() > 0)
{
if (autotrack_pass_has_started)
{
logger->critical("LOS!!!!!!!!!!!!!! %d", upcoming_satellite_passes_sel[0].norad);
tracking::TrackedObject obj;
for (auto &v : enabled_satellites)
if (v.norad == upcoming_satellite_passes_sel[0].norad)
obj = v;
los_callback(upcoming_satellite_passes_sel[0], obj);
}
autotrack_pass_has_started = false;
updateAutotrackPasses(); // upcoming_satellite_passes_sel.erase(upcoming_satellite_passes_sel.begin());
for (int i = 0; i < (int)general_tle_registry.size(); i++)
if (general_tle_registry[i].norad == upcoming_satellite_passes_sel[0].norad)
current_satellite = i;
backend_needs_update = true;
}
upcoming_satellite_passes_mtx.unlock();
}
}
void TrackingWidget::updateAutotrackPasses()
{
upcoming_satellite_passes_all.clear();
double initial_time = getTime();
for (tracking::TrackedObject &obj : enabled_satellites)
{
auto tle = general_tle_registry.get_from_norad(obj.norad).value();
predict_orbital_elements_t *satellite_object_ = predict_parse_tle(tle.line1.c_str(), tle.line2.c_str());
double current_time = initial_time;
while (current_time < initial_time + 12 * 3600)
{
predict_observation next_aos, next_los;
next_aos = next_los = predict_next_los(observer_station, satellite_object_, predict_to_julian_double(current_time));
// Calculate the AOS before that LOS
double next_aos_time_, next_los_time_;
next_aos_time_ = next_los_time_ = predict_from_julian(next_los.time);
do
{
next_aos = predict_next_aos(observer_station, satellite_object_, predict_to_julian_double(next_aos_time_));
next_aos_time_ -= 10;
} while (predict_from_julian(next_aos.time) >= next_los_time_);
next_los_time_ = predict_from_julian(next_los.time);
next_aos_time_ = predict_from_julian(next_aos.time);
float max_el = 0;
predict_position satellite_orbit2;
predict_observation observation_pos2;
double time_step = abs(next_los_time_ - next_aos_time_) / 50.0;
for (double ctime = next_aos_time_; ctime <= next_los_time_; ctime += time_step)
{
predict_orbit(satellite_object_, &satellite_orbit2, predict_to_julian_double(ctime));
predict_observe_orbit(observer_station, &satellite_orbit2, &observation_pos2);
if (observation_pos2.elevation * RAD_TO_DEG > max_el)
max_el = observation_pos2.elevation * RAD_TO_DEG;
}
if (max_el >= autotrack_min_elevation)
upcoming_satellite_passes_all.push_back({obj.norad,
next_aos_time_,
next_los_time_,
max_el});
// logger->info("Pass of %s at AOS %s LOS %s elevation %.2f", tle.name.c_str(),
// timestamp_to_string(next_aos_time_).c_str(),
// timestamp_to_string(next_los_time_).c_str(),
// max_el);
current_time = next_los_time_ + 1;
}
predict_destroy_orbital_elements(satellite_object_);
}
std::sort(upcoming_satellite_passes_all.begin(), upcoming_satellite_passes_all.end(),
[](tracking::SatellitePass &el1,
tracking::SatellitePass &el2)
{
return el1.aos_time < el2.aos_time;
});
upcoming_satellite_passes_sel.clear();
for (int i = 0; i < (int)upcoming_satellite_passes_all.size() - 1; i++)
{
auto &pass1 = upcoming_satellite_passes_all[i];
auto &pass2 = upcoming_satellite_passes_all[i + 1];
if (pass1.los_time > pass2.aos_time)
{
// logger->critical("Overlap : ");
// logPass(pass1);
// logPass(pass2);
if (pass1.max_elevation > pass2.max_elevation)
upcoming_satellite_passes_sel.push_back(pass1);
else
upcoming_satellite_passes_sel.push_back(pass2);
}
else
{
upcoming_satellite_passes_sel.push_back(pass1);
}
}
// for (auto ppp : upcoming_satellite_passes_sel)
// logger->debug("Pass of %s at AOS %s LOS %s elevation %.2f",
// general_tle_registry.get_from_norad(ppp.norad).value().name.c_str(),
// timestamp_to_string(ppp.aos_time).c_str(),
// timestamp_to_string(ppp.los_time).c_str(),
// ppp.max_elevation);
}
void TrackingWidget::renderAutotrackConfig()
{
upcoming_satellite_passes_mtx.lock();
if (autotrack_engaged)
style::beginDisabled();
ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 2 - 220 * ui_scale);
ImGui::BeginGroup();
ImGui::SetNextItemWidth(200 * ui_scale);
if (ImGui::BeginListBox("##trackingavailablesatsbox"))
{
for (int i = 0; i < (int)satoptions.size(); i++)
if (std::find_if(enabled_satellites.begin(), enabled_satellites.end(), [i](tracking::TrackedObject &c)
{ return c.norad == general_tle_registry[i].norad; }) == enabled_satellites.end())
if (ImGui::Selectable(satoptions[i].c_str(), i == tracking_sats_menu_selected_1))
tracking_sats_menu_selected_1 = i;
ImGui::EndListBox();
}
ImGui::SameLine();
int curpos = ImGui::GetCursorPosY();
ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 2 - 15 * ui_scale);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 50 * ui_scale);
ImGui::BeginGroup();
if (ImGui::Button(">>>"))
{
auto it = std::find_if(enabled_satellites.begin(), enabled_satellites.end(), [this](tracking::TrackedObject &t)
{ return t.norad == general_tle_registry[tracking_sats_menu_selected_1].norad; });
if (it == enabled_satellites.end())
enabled_satellites.push_back({general_tle_registry[tracking_sats_menu_selected_1].norad});
}
if (ImGui::Button("<<<"))
{
auto it = std::find_if(enabled_satellites.begin(), enabled_satellites.end(), [this](tracking::TrackedObject &t)
{ return t.norad == general_tle_registry[tracking_sats_menu_selected_2].norad; });
if (it != enabled_satellites.end())
enabled_satellites.erase(it);
}
ImGui::EndGroup();
ImGui::SameLine();
ImGui::SetCursorPosY(curpos);
ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 2 + 20 * ui_scale);
ImGui::SetNextItemWidth(200 * ui_scale);
if (ImGui::BeginListBox("##trackingselectedsatsbox"))
{
for (int i = 0; i < (int)satoptions.size(); i++)
if (std::find_if(enabled_satellites.begin(), enabled_satellites.end(), [i](tracking::TrackedObject &c)
{ return c.norad == general_tle_registry[i].norad; }) != enabled_satellites.end())
if (ImGui::Selectable(satoptions[i].c_str(), i == tracking_sats_menu_selected_2))
tracking_sats_menu_selected_2 = i;
ImGui::EndListBox();
}
ImGui::EndGroup();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 45 * ui_scale);
ImGui::Separator();
ImGui::Spacing();
ImGui::SetNextItemWidth(150 * ui_scale);
ImGui::InputFloat("Minimum Elevation", &autotrack_min_elevation);
if (ImGui::Button("Update Passes"))
{
updateAutotrackPasses();
}
if (autotrack_engaged)
style::endDisabled();
ImGui::SameLine();
if (ImGui::Checkbox("Engage Autotrack", &autotrack_engaged))
{
updateAutotrackPasses();
if (upcoming_satellite_passes_sel.size() > 0)
{
for (int i = 0; i < (int)general_tle_registry.size(); i++)
if (general_tle_registry[i].norad == upcoming_satellite_passes_sel[0].norad)
current_satellite = i;
horizons_mode = false;
backend_needs_update = true;
autotrack_pass_has_started = false;
}
else
{
autotrack_engaged = false;
}
saveConfig();
}
#if 1
{
ImGui::Spacing();
int d_pplot_height = (enabled_satellites.size() * 20) * ui_scale;
int d_pplot_size = ImGui::GetWindowContentRegionWidth();
ImDrawList *draw_list = ImGui::GetWindowDrawList();
draw_list->AddRectFilled(ImGui::GetCursorScreenPos(),
ImVec2(ImGui::GetCursorScreenPos().x + d_pplot_size, ImGui::GetCursorScreenPos().y + d_pplot_height + 20 * ui_scale),
light_theme ? ImColor(255, 255, 255, 255) : ImColor::HSV(0, 0, 0));
double current_time = getTime();
time_t tttime = current_time;
std::tm *timeReadable = gmtime(&tttime);
int curr_hour = timeReadable->tm_hour;
int offset = d_pplot_size / 12 * (timeReadable->tm_min/60.0);
ImGui::Dummy(ImVec2(0, 0));
for (int i = (timeReadable->tm_min < 30 ? 1 : 0); i < (timeReadable->tm_min < 30 ? 12 : 13); i++)
{
ImGui::SameLine();
ImGui::SetCursorPosX(i * d_pplot_size / 12 - offset);
ImGui::Text("%s%s%s", (curr_hour + i)%24 < 10 ? "0" : "", std::to_string((curr_hour + i) % 24).c_str(), ":00");
}
float sat_blk_height = ((float)d_pplot_height / (float)enabled_satellites.size());
for (int i = 0; i < (int)enabled_satellites.size(); i++)
{
auto &norad = enabled_satellites[i].norad;
int thsat_ys = sat_blk_height * i;
int thsat_ye = sat_blk_height * i + sat_blk_height;
bool first_pass = true;
for (auto &cpass : upcoming_satellite_passes_all)
{
if (cpass.norad == norad)
{
double cpass_xs = ((cpass.aos_time - current_time) / (12.0 * 3600.0)) * d_pplot_size;
double cpass_xe = ((cpass.los_time - current_time) / (12.0 * 3600.0)) * d_pplot_size;
std::string name = general_tle_registry.get_from_norad(norad)->name;
if (cpass_xs < 0)
cpass_xs = 0;
if (cpass_xe > d_pplot_size)
cpass_xe = d_pplot_size;
if (cpass_xs > d_pplot_size)
cpass_xs = d_pplot_size;
auto color = ImColor::HSV(fmod(norad, 10) / 10.0, 1, 1);
draw_list->AddRectFilled(ImVec2(ImGui::GetCursorScreenPos().x + cpass_xs, ImGui::GetCursorScreenPos().y + thsat_ys + 1),
ImVec2(ImGui::GetCursorScreenPos().x + cpass_xe, ImGui::GetCursorScreenPos().y + thsat_ye),
color, 3);
if (first_pass)
{
draw_list->AddText(ImVec2(ImGui::GetCursorScreenPos().x + cpass_xe + 5 * ui_scale,
ImGui::GetCursorScreenPos().y + thsat_ys + (sat_blk_height / 2) - 8 * ui_scale),
color, name.c_str());
first_pass = false;
}
if (ImGui::IsMouseHoveringRect(ImVec2(ImGui::GetCursorScreenPos().x + cpass_xs, ImGui::GetCursorScreenPos().y + thsat_ys),
ImVec2(ImGui::GetCursorScreenPos().x + cpass_xe, ImGui::GetCursorScreenPos().y + thsat_ye)))
ImGui::SetTooltip("%s\nAOS : %s\nLOS : %s\nEl : %.2f",
name.c_str(),
timestamp_to_string(cpass.aos_time).c_str(),
timestamp_to_string(cpass.los_time).c_str(),
cpass.max_elevation);
}
}
draw_list->AddLine(ImVec2(ImGui::GetCursorScreenPos().x + 0, ImGui::GetCursorScreenPos().y + thsat_ys),
ImVec2(ImGui::GetCursorScreenPos().x + d_pplot_size, ImGui::GetCursorScreenPos().y + thsat_ys),
ImColor(100, 100, 100, 255));
draw_list->AddLine(ImVec2(ImGui::GetCursorScreenPos().x + 0, ImGui::GetCursorScreenPos().y + thsat_ye),
ImVec2(ImGui::GetCursorScreenPos().x + d_pplot_size, ImGui::GetCursorScreenPos().y + thsat_ye),
ImColor(100, 100, 100, 255));
if (autotrack_engaged)
{
for (auto &cpass : upcoming_satellite_passes_sel)
{
if (cpass.norad == norad)
{
double cpass_xs = ((cpass.aos_time - current_time) / (12.0 * 3600.0)) * d_pplot_size;
double cpass_xe = ((cpass.los_time - current_time) / (12.0 * 3600.0)) * d_pplot_size;
if (cpass_xs < 0)
cpass_xs = 0;
if (cpass_xe > d_pplot_size)
cpass_xe = d_pplot_size;
if (cpass_xs > d_pplot_size)
cpass_xs = d_pplot_size;
auto color = ImColor(255, 255, 255, 255);
draw_list->AddRect(ImVec2(ImGui::GetCursorScreenPos().x + cpass_xs, ImGui::GetCursorScreenPos().y + thsat_ys),
ImVec2(ImGui::GetCursorScreenPos().x + cpass_xe, ImGui::GetCursorScreenPos().y + thsat_ye),
color, 3);
}
}
}
}
ImGui::Dummy(ImVec2(d_pplot_size + 3 * ui_scale, d_pplot_height + 3 * ui_scale));
}
#endif
if (autotrack_engaged)
style::beginDisabled();
if (ImGui::BeginTable("##trackingwidgettrackeobjectsconfig", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit))
{
for (auto &cpass : enabled_satellites)
{
auto color = ImColor::HSV(fmod(cpass.norad, 10) / 10.0, 1, 1);
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::SetNextItemWidth(100*ui_scale);
ImGui::TextColored(color, "%s", general_tle_registry.get_from_norad(cpass.norad)->name.c_str());
ImGui::TableSetColumnIndex(1);
ImGui::SetNextItemWidth(120*ui_scale);
ImGui::InputDouble(((std::string) "Frequency##objcfgfreq1" + std::to_string(cpass.norad)).c_str(), &cpass.frequency, 0, 0, "%f MHz");
ImGui::TableSetColumnIndex(2);
ImGui::SetNextItemWidth(100*ui_scale);
ImGui::Checkbox(((std::string) "Record##objcfgfreq2" + std::to_string(cpass.norad)).c_str(), &cpass.record);
// ImGui::TableSetColumnIndex(3);
ImGui::Checkbox(((std::string) "Live##objcfgfreq3" + std::to_string(cpass.norad)).c_str(), &cpass.live);
ImGui::TableSetColumnIndex(3);
ImGui::SetNextItemWidth(300*ui_scale);
ImGui::PushID(cpass.norad);
if (ImGui::BeginCombo("##pipelinesel", cpass.pipeline_selector->get_name(cpass.pipeline_selector->pipeline_id).c_str(), ImGuiComboFlags_HeightLarge))
{
cpass.pipeline_selector->renderSelectionBox(300 * ui_scale);
ImGui::EndCombo();
}
if (ImGui::BeginCombo("##params", "Configure..."))
{
cpass.pipeline_selector->renderParamTable();
ImGui::EndCombo();
}
ImGui::PopID();
// ImGui::InputText(((std::string) "Pipeline##objcfgfreq4" + std::to_string(cpass.norad)).c_str(), &cpass.pipeline_name);
}
ImGui::EndTable();
}
if (autotrack_engaged)
style::endDisabled();
#if 0
if (ImGui::BeginTable("##trackingwidgettable", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
{
for (auto &cpass : upcoming_satellite_passes_all)
{
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("%s", general_tle_registry.get_from_norad(cpass.norad)->name.c_str());
ImGui::TableSetColumnIndex(1);
ImGui::Text("%.2f", cpass.max_elevation);
}
ImGui::EndTable();
}
#endif
upcoming_satellite_passes_mtx.unlock();
}
}