satdump/src-interface/recorder/tracking_widget.cpp

312 lines
13 KiB
C++
Raw Normal View History

2023-07-17 23:11:13 +02:00
#include "tracking_widget.h"
#include "common/tracking/tle.h"
#include "imgui/imgui.h"
#include "core/module.h"
#include "core/config.h"
2023-07-18 12:27:58 +02:00
#include "main_ui.h"
2023-07-17 23:11:13 +02:00
namespace satdump
{
TrackingWidget::TrackingWidget()
{
try
{
qth_lon = config::main_cfg["satdump_general"]["qth_lon"]["value"].get<double>();
qth_lat = config::main_cfg["satdump_general"]["qth_lat"]["value"].get<double>();
qth_alt = config::main_cfg["satdump_general"]["qth_alt"]["value"].get<double>();
}
catch (std::exception &e)
{
logger->error("Could not get QTH lon/lat! %s", e.what());
}
logger->trace("Using QTH %f %f Alt %f", qth_lon, qth_lat, qth_alt);
2023-07-18 18:12:04 +02:00
if (general_tle_registry.size() > 0)
2023-07-18 16:59:32 +02:00
has_tle = true;
2023-07-17 23:11:13 +02:00
for (auto &tle : general_tle_registry)
satoptionstr += tle.name + '\0';
observer_station = predict_create_observer("Main", qth_lat * DEG_TO_RAD, qth_lon * DEG_TO_RAD, qth_alt);
for (auto &hid : horizons_ids)
horizonsoptionstr += hid + '\0';
2023-07-18 21:31:13 +02:00
// Updates on registry updates
eventBus->register_handler<TLEsUpdatedEvent>([this](TLEsUpdatedEvent)
{
tle_update_mutex.lock();
if (general_tle_registry.size() > 0)
has_tle = true;
satoptionstr = "";
for (auto &tle : general_tle_registry)
satoptionstr += tle.name + '\0';
tle_update_mutex.unlock(); });
2023-07-20 01:02:57 +02:00
backend_thread = std::thread(&TrackingWidget::backend_run, this);
2023-07-17 23:11:13 +02:00
}
TrackingWidget::~TrackingWidget()
{
predict_destroy_observer(observer_station);
2023-07-20 01:02:57 +02:00
backend_should_run = false;
if (backend_thread.joinable())
backend_thread.join();
2023-07-17 23:11:13 +02:00
}
void TrackingWidget::render()
{
2023-07-18 16:59:32 +02:00
if (!has_tle)
return;
2023-07-20 01:02:57 +02:00
// tle_update_mutex.lock();
2023-07-17 23:11:13 +02:00
{
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_size),
2023-07-18 12:27:58 +02:00
light_theme ? ImColor(255, 255, 255, 255) : ImColor::HSV(0, 0, 0));
2023-07-17 23:11:13 +02:00
float radius = 0.45;
float radius1 = d_pplot_size * radius * (3.0 / 9.0);
float radius2 = d_pplot_size * radius * (6.0 / 9.0);
float radius3 = d_pplot_size * radius * (9.0 / 9.0);
draw_list->AddCircle({ImGui::GetCursorScreenPos().x + (d_pplot_size / 2),
ImGui::GetCursorScreenPos().y + (d_pplot_size / 2)},
2023-07-18 18:13:21 +02:00
radius1, ImColor(0, 255, 0, 255), 0, 2);
2023-07-17 23:11:13 +02:00
draw_list->AddCircle({ImGui::GetCursorScreenPos().x + (d_pplot_size / 2),
ImGui::GetCursorScreenPos().y + (d_pplot_size / 2)},
2023-07-18 18:13:21 +02:00
radius2, ImColor(0, 255, 0, 255), 0, 2);
2023-07-17 23:11:13 +02:00
draw_list->AddCircle({ImGui::GetCursorScreenPos().x + (d_pplot_size / 2),
ImGui::GetCursorScreenPos().y + (d_pplot_size / 2)},
2023-07-18 18:13:21 +02:00
radius3, ImColor(0, 255, 0, 255), 0, 2);
2023-07-17 23:11:13 +02:00
draw_list->AddLine({ImGui::GetCursorScreenPos().x + (d_pplot_size / 2),
ImGui::GetCursorScreenPos().y},
{ImGui::GetCursorScreenPos().x + (d_pplot_size / 2),
ImGui::GetCursorScreenPos().y + d_pplot_size},
2023-07-18 18:13:39 +02:00
ImColor(0, 255, 0, 255), 2);
2023-07-17 23:11:13 +02:00
draw_list->AddLine({ImGui::GetCursorScreenPos().x,
ImGui::GetCursorScreenPos().y + (d_pplot_size / 2)},
{ImGui::GetCursorScreenPos().x + d_pplot_size,
ImGui::GetCursorScreenPos().y + (d_pplot_size / 2)},
2023-07-18 18:13:39 +02:00
ImColor(0, 255, 0, 255), 2);
2023-07-17 23:11:13 +02:00
if (upcoming_pass_points.size() > 1)
{
2023-07-20 01:02:57 +02:00
upcoming_passes_mtx.lock();
2023-07-17 23:11:13 +02:00
for (int i = 0; i < (int)upcoming_pass_points.size() - 1; i++)
{
auto &p1 = upcoming_pass_points[i];
auto &p2 = upcoming_pass_points[i + 1];
float point_x1, point_x2, point_y1, point_y2;
point_x1 = point_x2 = ImGui::GetCursorScreenPos().x + (d_pplot_size / 2);
point_y1 = point_y2 = ImGui::GetCursorScreenPos().y + (d_pplot_size / 2);
point_x1 += sin(p1.first * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - p1.second) / 90.0);
point_y1 -= cos(p1.first * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - p1.second) / 90.0);
point_x2 += sin(p2.first * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - p2.second) / 90.0);
point_y2 -= cos(p2.first * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - p2.second) / 90.0);
draw_list->AddLine({point_x1, point_y1},
{point_x2, point_y2},
2023-07-18 16:59:32 +02:00
ImColor(255, 165, 0, 255), 2.0);
2023-07-17 23:11:13 +02:00
}
2023-07-20 01:02:57 +02:00
upcoming_passes_mtx.unlock();
2023-07-17 23:11:13 +02:00
}
2023-07-20 01:02:57 +02:00
if (current_el > 0)
2023-07-17 23:11:13 +02:00
{
float point_x = ImGui::GetCursorScreenPos().x + (d_pplot_size / 2);
float point_y = ImGui::GetCursorScreenPos().y + (d_pplot_size / 2);
2023-07-20 01:02:57 +02:00
point_x += sin(current_az * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - current_el) / 90.0);
point_y -= cos(current_az * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - current_el) / 90.0);
2023-07-17 23:11:13 +02:00
draw_list->AddCircleFilled({point_x, point_y}, 5 * ui_scale, ImColor(255, 0, 0, 255));
}
2023-07-20 15:55:38 +02:00
if (rotctld_client.is_connected())
{
{
float point_x = ImGui::GetCursorScreenPos().x + (d_pplot_size / 2);
float point_y = ImGui::GetCursorScreenPos().y + (d_pplot_size / 2);
point_x += sin(current_rotator_az * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - current_rotator_el) / 90.0);
point_y -= cos(current_rotator_az * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - current_rotator_el) / 90.0);
draw_list->AddCircle({point_x, point_y}, 9 * ui_scale, ImColor(0, 237, 255, 255), 0, 2.0);
}
if (rotator_engaged)
{
float point_x = ImGui::GetCursorScreenPos().x + (d_pplot_size / 2);
float point_y = ImGui::GetCursorScreenPos().y + (d_pplot_size / 2);
point_x += sin(current_req_rotator_az * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - current_req_rotator_el) / 90.0);
point_y -= cos(current_req_rotator_az * DEG_TO_RAD) * d_pplot_size * radius * ((90.0 - current_req_rotator_el) / 90.0);
draw_list->AddLine({point_x - 5 * ui_scale, point_y}, {point_x - 12 * ui_scale, point_y}, ImColor(0, 237, 255, 255), 2.0);
draw_list->AddLine({point_x + 5 * ui_scale, point_y}, {point_x + 12 * ui_scale, point_y}, ImColor(0, 237, 255, 255), 2.0);
draw_list->AddLine({point_x, point_y - 5 * ui_scale}, {point_x, point_y - 12 * ui_scale}, ImColor(0, 237, 255, 255), 2.0);
draw_list->AddLine({point_x, point_y + 5 * ui_scale}, {point_x, point_y + 12 * ui_scale}, ImColor(0, 237, 255, 255), 2.0);
}
}
2023-07-17 23:11:13 +02:00
ImGui::Dummy(ImVec2(d_pplot_size + 3 * ui_scale, d_pplot_size + 3 * ui_scale));
}
bool update_global = false;
2023-07-20 16:36:16 +02:00
if (backend_needs_update)
style::beginDisabled();
2023-07-17 23:11:13 +02:00
ImGui::SetNextItemWidth(ImGui::GetWindowContentRegionWidth());
if (horizons_mode)
update_global = update_global || ImGui::Combo("###horizonsselectcombo", &current_horizons, horizonsoptionstr.c_str());
else
update_global = update_global || ImGui::Combo("###satelliteselectcombo", &current_satellite, satoptionstr.c_str());
if (ImGui::BeginTable("##trackingradiotable", 2, NULL))
{
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
if (ImGui::RadioButton("Satellites", !horizons_mode))
{
horizons_mode = false;
update_global = true;
}
ImGui::TableSetColumnIndex(1);
if (ImGui::RadioButton("Horizons", horizons_mode))
{
horizons_mode = true;
update_global = true;
}
ImGui::EndTable();
}
2023-07-20 16:36:16 +02:00
if (backend_needs_update)
style::endDisabled();
if (update_global)
backend_needs_update = true;
2023-07-17 23:11:13 +02:00
if (ImGui::BeginTable("##trackingwidgettable", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
{
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("Azimuth");
ImGui::TableSetColumnIndex(1);
2023-07-20 16:36:16 +02:00
ImGui::Text("%.3f", current_az);
2023-07-17 23:11:13 +02:00
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("Elevation");
ImGui::TableSetColumnIndex(1);
2023-07-20 16:36:16 +02:00
ImGui::Text("%.3f", current_el);
2023-07-17 23:11:13 +02:00
if (next_aos_time != 0 && next_los_time != 0)
{
double timeOffset = 0, ctime = getTime();
if (next_aos_time > ctime)
timeOffset = next_aos_time - ctime;
else
timeOffset = next_los_time - ctime;
2023-07-19 19:47:35 +02:00
int hours = timeOffset / 3600;
int minutes = fmod(timeOffset / 60, 60);
2023-07-17 23:11:13 +02:00
int seconds = fmod(timeOffset, 60);
2023-07-19 19:47:35 +02:00
std::string time_dis = (hours < 10 ? "0" : "") + std::to_string(hours) + ":" +
(minutes < 10 ? "0" : "") + std::to_string(minutes) + ":" +
(seconds < 10 ? "0" : "") + std::to_string(seconds);
2023-07-17 23:11:13 +02:00
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("Next Event");
ImGui::TableSetColumnIndex(1);
2023-07-19 19:47:35 +02:00
ImGui::Text("%s", time_dis.c_str());
2023-07-17 23:11:13 +02:00
}
#if 1
if (!horizons_mode && satellite_object != nullptr)
{
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("Azimuth Rate");
ImGui::TableSetColumnIndex(1);
ImGui::Text("%.2f", observation_pos.azimuth_rate * RAD_TO_DEG);
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("Elevation Rate");
ImGui::TableSetColumnIndex(1);
ImGui::Text("%.2f", observation_pos.elevation_rate * RAD_TO_DEG);
}
#endif
ImGui::EndTable();
}
ImGui::Spacing();
2023-07-18 21:31:13 +02:00
2023-07-20 15:55:38 +02:00
//////////////////
ImGui::Separator();
2023-07-20 16:36:16 +02:00
ImGui::Spacing();
if (ImGui::BeginTable("##trackingwidgettable", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
{
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("Rot Az");
ImGui::TableSetColumnIndex(1);
ImGui::Text("Rot El");
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::InputFloat("##Rot Az", &current_req_rotator_az);
ImGui::TableSetColumnIndex(1);
ImGui::InputFloat("##Rot El", &current_req_rotator_el);
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("%.3f", current_rotator_az);
ImGui::TableSetColumnIndex(1);
ImGui::Text("%.3f", current_rotator_el);
ImGui::EndTable();
}
2023-07-20 15:55:38 +02:00
ImGui::Checkbox("Engage", &rotator_engaged);
ImGui::SameLine();
ImGui::Checkbox("Track", &rotator_tracking);
ImGui::Separator();
2023-07-20 16:36:16 +02:00
2023-07-20 15:55:38 +02:00
rotctld_client.render();
2023-07-20 16:36:16 +02:00
2023-07-20 15:55:38 +02:00
ImGui::Spacing();
2023-07-20 01:02:57 +02:00
// tle_update_mutex.unlock();
2023-07-17 23:11:13 +02:00
}
double TrackingWidget::getTime()
{
auto time = std::chrono::system_clock::now();
auto since_epoch = time.time_since_epoch();
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch);
return millis.count() / 1e3;
}
}