satdump/src-core/common/tracking/scheduler/passes.cpp
2023-12-10 19:53:50 +01:00

175 lines
No EOL
7.2 KiB
C++

#include "passes.h"
#include "common/geodetic/geodetic_coordinates.h"
#include "libs/predict/predict.h"
namespace satdump
{
std::vector<SatellitePass> getPassesForSatellite(int norad, double initial_time, double timespan, double qth_lon, double qth_lat, double qth_alt, std::vector<SatellitePass> premade_passes)
{
std::vector<SatellitePass> passes;
predict_observer_t *observer_station = predict_create_observer("Main", qth_lat * DEG_TO_RAD, qth_lon * DEG_TO_RAD, qth_alt * DEG_TO_RAD);
auto tle = general_tle_registry.get_from_norad(norad).value();
predict_orbital_elements_t *satellite_object_ = predict_parse_tle(tle.line1.c_str(), tle.line2.c_str());
double current_time = initial_time;
if (premade_passes.size() == 0) // Normal algo, for normal LEOs
{
while (current_time < initial_time + timespan)
{
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)
passes.push_back({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;
}
}
else // For pre-processed "AOS"/"LOS" times, we just fill in meta
{
for (auto pass : premade_passes)
{
float max_el = 0;
predict_position satellite_orbit2;
predict_observation observation_pos2;
double time_step = abs(pass.los_time - pass.aos_time) / 50.0;
for (double ctime = pass.aos_time; ctime <= pass.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;
}
pass.norad = norad;
pass.max_elevation = max_el;
passes.push_back(pass);
}
}
predict_destroy_orbital_elements(satellite_object_);
predict_destroy_observer(observer_station);
return passes;
}
std::vector<SatellitePass> filterPassesByElevation(std::vector<SatellitePass> passes, float min_elevation, float max_elevation)
{
std::vector<SatellitePass> passes2;
for (auto &pass : passes)
if (pass.max_elevation >= min_elevation && pass.max_elevation <= max_elevation)
passes2.push_back(pass);
return passes2;
}
std::vector<SatellitePass> selectPassesForAutotrack(std::vector<SatellitePass> passes)
{
std::vector<SatellitePass> passes2;
#if 0
for (int i = 0; i < (int)passes.size() - 1; i++)
{
auto &pass1 = passes[i];
auto &pass2 = passes[i + 1];
if (pass1.los_time > pass2.aos_time)
{
// logger->critical("Overlap : ");
// logPass(pass1);
// logPass(pass2);
if (pass1.max_elevation > pass2.max_elevation)
passes2.push_back(pass1);
else
passes2.push_back(pass2);
}
else
{
passes2.push_back(pass1);
}
}
#else
SatellitePass selectedPass = {-1, -1, -1 - 1};
// double busyUntil = 0;
if (passes.size() > 0)
{
double start_time = passes[0].aos_time;
double stop_time = passes[passes.size() - 1].los_time;
for (double current_time = start_time; current_time < stop_time; current_time++)
{
std::vector<SatellitePass> ongoing_passes;
for (auto &cpass : passes)
if (cpass.aos_time <= current_time && current_time <= cpass.los_time)
ongoing_passes.push_back(cpass);
if (ongoing_passes.size() == 0)
continue;
// if (current_time < busyUntil)
// continue;
SatellitePass picked_pass = {-1, -1, -1 - 1};
for (auto &cpass : ongoing_passes)
if (picked_pass.max_elevation < cpass.max_elevation)
picked_pass = cpass;
std::vector<SatellitePass> picked_pass_overlaping_passes;
picked_pass_overlaping_passes.push_back(picked_pass);
for (auto &cpass : passes)
if (picked_pass.aos_time < cpass.los_time && !(picked_pass.los_time <= cpass.aos_time))
picked_pass_overlaping_passes.push_back(cpass);
for (auto &cpass : picked_pass_overlaping_passes)
if (picked_pass.max_elevation < cpass.max_elevation)
picked_pass = cpass;
// if (picked_pass.aos_time < selectedPass.los_time)
// continue;
if (picked_pass.norad != selectedPass.norad ||
picked_pass.aos_time != selectedPass.aos_time ||
picked_pass.los_time != selectedPass.los_time)
{
selectedPass = picked_pass;
passes2.push_back(picked_pass);
// busyUntil = picked_pass.los_time;
}
}
}
#endif
return passes2;
}
}