satdump/src-cli/autotrack/autotrack.cpp

348 lines
12 KiB
C++
Raw Permalink Normal View History

2023-12-13 18:13:23 +01:00
#include "autotrack.h"
#include "init.h"
2023-12-11 18:02:33 +01:00
#include "logger.h"
#include "common/utils.h"
2025-05-26 19:21:10 +01:00
#include "utils/time.h"
2023-12-11 18:02:33 +01:00
AutoTrackApp::AutoTrackApp(nlohmann::json settings, nlohmann::json parameters, std::string output_folder)
: d_settings(settings), d_parameters(parameters), d_output_folder(output_folder)
2023-12-11 18:02:33 +01:00
{
///////////////////////////////////////////////////////////////////////////////////
///////////////// Initial settings parsing
///////////////////////////////////////////////////////////////////////////////////
2023-12-11 18:02:33 +01:00
uint64_t samplerate;
uint64_t initial_frequency;
std::string handler_id;
2024-05-01 16:26:07 +02:00
std::string hdl_dev_id;
2023-12-11 18:02:33 +01:00
try
{
samplerate = parameters["samplerate"].get<uint64_t>();
initial_frequency = parameters["initial_frequency"].get<uint64_t>();
handler_id = parameters["source"].get<std::string>();
if (parameters.contains("source_id"))
2024-05-01 16:26:07 +02:00
hdl_dev_id = parameters["source_id"].get<std::string>();
2023-12-11 18:02:33 +01:00
}
catch (std::exception &e)
{
logger->error("Error parsing arguments! %s", e.what());
exit(1);
2023-12-11 18:02:33 +01:00
}
///////////////////////////////////////////////////////////////////////////////////
///////////////// SDR Search
///////////////////////////////////////////////////////////////////////////////////
2023-12-11 18:02:33 +01:00
dsp::registerAllSources();
std::vector<dsp::SourceDescriptor> source_tr = dsp::getAllAvailableSources();
for (dsp::SourceDescriptor src : source_tr)
logger->debug("Device " + src.name);
// Try to find it and check it's usable
bool src_found = false;
for (dsp::SourceDescriptor src : source_tr)
{
if (handler_id == src.source_type)
{
if (parameters.contains("source_id"))
{
if (hdl_dev_id == src.unique_id)
{
selected_src = src;
src_found = true;
}
}
else
{
selected_src = src;
src_found = true;
}
}
}
if (!src_found)
{
logger->error("Could not find a handler for source type : %s!", handler_id.c_str());
exit(1);
2023-12-11 18:02:33 +01:00
}
///////////////////////////////////////////////////////////////////////////////////
///////////////// SDR Open & Init, Main DSP Setup
///////////////////////////////////////////////////////////////////////////////////
// SDR
source_ptr = getSourceFromDescriptor(selected_src);
2023-12-11 18:02:33 +01:00
source_ptr->open();
set_frequency(initial_frequency);
2023-12-11 18:02:33 +01:00
source_ptr->set_samplerate(samplerate);
source_ptr->set_settings(parameters);
// Splitter
splitter = std::make_unique<dsp::SplitterBlock>(source_ptr->output_stream);
splitter->set_main_enabled(false);
splitter->add_output("record");
splitter->add_output("live");
2023-12-11 18:02:33 +01:00
// Optional FFT
2024-02-03 22:23:14 -05:00
if (parameters.contains("fft_enable") && parameters["fft_enable"])
2023-12-11 18:02:33 +01:00
{
if (parameters.contains("fft_size"))
fft_size = parameters["fft_size"].get<int>();
if (parameters.contains("fft_rate"))
fft_rate = parameters["fft_rate"].get<int>();
if (parameters.contains("fft_min"))
fft_min = parameters["fft_min"].get<int>();
if (parameters.contains("fft_max"))
fft_max = parameters["fft_max"].get<int>();
2023-12-16 19:58:45 +01:00
splitter->add_output("fft");
fft = std::make_unique<dsp::FFTPanBlock>(splitter->get_output("fft"));
fft->set_fft_settings(fft_size, samplerate, fft_rate);
if (parameters.contains("fft_avgn"))
fft->avg_num = parameters["fft_avgn"].get<float>();
2023-12-16 19:58:45 +01:00
fft_plot = std::make_unique<widgets::FFTPlot>(fft->output_stream->writeBuf, fft_size, fft_min, fft_max, 40);
logger->critical("FFT GOOD!");
fft->start();
2024-02-03 22:23:14 -05:00
}
2023-12-11 18:02:33 +01:00
2024-01-21 21:24:35 +01:00
file_sink = std::make_shared<dsp::FileSinkBlock>(splitter->get_output("record"));
file_sink->start();
///////////////////////////////////////////////////////////////////////////////////
///////////////// Tracking modules init
///////////////////////////////////////////////////////////////////////////////////
2023-12-11 18:02:33 +01:00
double qth_lon = settings["qth"]["lon"];
double qth_lat = settings["qth"]["lat"];
double qth_alt = settings["qth"]["alt"];
logger->trace("Using QTH %f %f Alt %f", qth_lon, qth_lat, qth_alt);
// Init Obj Tracker & scheduler
2023-12-11 18:02:33 +01:00
object_tracker.setQTH(qth_lon, qth_lat, qth_alt);
auto_scheduler.setQTH(qth_lon, qth_lat, qth_alt);
// Other config for the tracker and scheduler
std::vector<satdump::TrackedObject> enabled_satellites = settings["tracked_objects"];
nlohmann::json rotator_algo_cfg;
if (settings["tracking"].contains("rotator_algo"))
rotator_algo_cfg = settings["tracking"]["rotator_algo"];
auto_scheduler.setTracked(enabled_satellites);
object_tracker.setRotatorConfig(rotator_algo_cfg);
2024-01-19 00:29:42 +01:00
auto_scheduler.setAutoTrackCfg(getValueOrDefault<satdump::AutoTrackCfg>(settings["tracking"]["autotrack_cfg"], satdump::AutoTrackCfg()));
2023-12-11 18:02:33 +01:00
setup_schedular_callbacks();
///////////////////////////////////////////////////////////////////////////////////
///////////////// Optional source start
///////////////////////////////////////////////////////////////////////////////////
if (!auto_scheduler.getAutoTrackCfg().stop_sdr_when_idle)
start_device();
///////////////////////////////////////////////////////////////////////////////////
///////////////// Rotator Setup & Start autotrack
///////////////////////////////////////////////////////////////////////////////////
2023-12-11 18:02:33 +01:00
rotator_handler = std::make_shared<rotator::RotctlHandler>();
if (settings["tracking"].contains("rotator_type"))
{
auto options = rotator::getRotatorHandlerOptions();
for (auto &opt : options)
if (opt.name == settings["tracking"]["rotator_type"].get<std::string>())
rotator_handler = opt.construct();
}
2023-12-11 18:02:33 +01:00
if (rotator_handler)
{
try
{
rotator_handler->set_settings(settings["tracking"]["rotator_cfg"]);
}
2024-01-16 15:51:56 -05:00
catch (std::exception &)
2023-12-11 18:02:33 +01:00
{
}
rotator_handler->connect();
// rotator_handler->set_pos(0, 0);
object_tracker.setRotator(rotator_handler);
// object_tracker.setRotatorReqPos(0, 0);
object_tracker.setRotatorEngaged(true);
object_tracker.setRotatorTracking(true);
}
// Finally, start
auto_scheduler.start();
2025-05-26 19:21:10 +01:00
auto_scheduler.setEngaged(true, satdump::getTime());
2023-12-11 18:02:33 +01:00
///////////////////////////////////////////////////////////////////////////////////
///////////////// WebServer
///////////////////////////////////////////////////////////////////////////////////
setup_webserver();
2024-03-07 11:36:02 +01:00
///////////////////////////////////////////////////////////////////////////////////
///////////////// Experimental - Net Forward
2024-03-07 11:36:02 +01:00
///////////////////////////////////////////////////////////////////////////////////
if (parameters.contains("net_fwd_address") && parameters.contains("net_fwd_port"))
2024-03-07 11:36:02 +01:00
{
std::string mode = "udp";
if (parameters.contains("net_fwd_mode"))
mode = parameters["net_fwd_mode"];
std::string address = parameters["net_fwd_address"];
int port = parameters["net_fwd_port"];
splitter->add_output("net_fwd");
udp_sink = std::make_shared<dsp::NetSinkBlock>(splitter->get_output("net_fwd"), mode, (char *)address.c_str(), port);
2024-03-07 11:36:02 +01:00
udp_sink->start();
splitter->set_enabled("net_fwd", true);
2024-03-07 11:36:02 +01:00
}
}
AutoTrackApp::~AutoTrackApp()
{
stop_webserver();
retry_vfo:
for (auto &vfo : vfo_list)
{
del_vfo(vfo.id);
goto retry_vfo;
}
stop_processing();
stop_device();
source_ptr->close();
splitter->input_stream = std::make_shared<dsp::stream<complex_t>>();
splitter->stop();
if (fft)
fft->stop();
2024-01-25 14:23:50 +01:00
if (file_sink)
file_sink->stop();
2024-03-07 11:36:02 +01:00
// Experimental
if (udp_sink)
udp_sink->stop();
}
void AutoTrackApp::setup_schedular_callbacks()
{
auto_scheduler.eng_callback = [this](satdump::AutoTrackCfg, satdump::SatellitePass, satdump::TrackedObject obj)
2023-12-11 18:02:33 +01:00
{
// logger->critical(obj.norad);
object_tracker.setObject(object_tracker.TRACKING_SATELLITE, obj.norad);
};
auto_scheduler.aos_callback = [this](satdump::AutoTrackCfg autotrack_cfg, satdump::SatellitePass, satdump::TrackedObject obj)
{
object_tracker.setObject(object_tracker.TRACKING_SATELLITE, obj.norad);
2024-01-22 23:03:51 +01:00
if (autotrack_cfg.multi_mode || obj.downlinks.size() > 1)
{
for (auto &dl : obj.downlinks)
2023-12-16 19:58:45 +01:00
{
if (dl.live || dl.record)
if (!is_started)
start_device();
if (dl.live)
2023-12-16 19:58:45 +01:00
{
2024-01-21 22:58:56 +01:00
std::string id = std::to_string(obj.norad) + "_" + std::to_string(dl.frequency) + "_live";
std::string name = std::to_string(obj.norad);
if (satdump::db_tle->get_from_norad(obj.norad).has_value())
name = satdump::db_tle->get_from_norad(obj.norad)->name;
name += " - " + format_notated(dl.frequency, "Hz");
2024-07-21 14:58:03 -04:00
add_vfo_live(id, name, dl.frequency, dl.pipeline_selector->selected_pipeline, dl.pipeline_selector->getParameters());
2023-12-16 19:58:45 +01:00
}
if (dl.record)
{
2024-01-21 22:58:56 +01:00
std::string id = std::to_string(obj.norad) + "_" + std::to_string(dl.frequency) + "_record";
std::string name = std::to_string(obj.norad);
if (satdump::db_tle->get_from_norad(obj.norad).has_value())
name = satdump::db_tle->get_from_norad(obj.norad)->name;
2024-01-21 22:58:56 +01:00
name += " - " + format_notated(dl.frequency, "Hz");
2024-08-18 11:43:57 -04:00
add_vfo_reco(id, name, dl.frequency, dl.baseband_format, dl.baseband_decimation);
}
}
}
else
{
if (obj.downlinks[0].live)
stop_processing();
if (obj.downlinks[0].record)
2024-01-21 21:24:35 +01:00
stop_recording();
if (obj.downlinks[0].live || obj.downlinks[0].record)
{
frequency_hz = obj.downlinks[0].frequency;
if (is_started)
set_frequency(frequency_hz);
else
start_device();
// Catch situations where source could not start
if (!is_started)
{
logger->error("Could not start recorder/processor since the source could not be started!");
return;
}
}
if (obj.downlinks[0].live)
{
pipeline_params = obj.downlinks[0].pipeline_selector->getParameters();
2024-07-21 14:58:03 -04:00
selected_pipeline = obj.downlinks[0].pipeline_selector->selected_pipeline;
start_processing();
2023-12-15 13:43:50 +01:00
}
if (obj.downlinks[0].record)
2023-12-15 13:43:50 +01:00
{
2024-08-18 11:43:57 -04:00
file_sink->set_output_sample_type(obj.downlinks[0].baseband_format);
2024-01-21 21:24:35 +01:00
start_recording();
2023-12-15 13:43:50 +01:00
}
2023-12-11 18:02:33 +01:00
}
};
2023-12-11 18:02:33 +01:00
auto_scheduler.los_callback = [this](satdump::AutoTrackCfg autotrack_cfg, satdump::SatellitePass, satdump::TrackedObject obj)
{
2024-01-22 23:03:51 +01:00
if (autotrack_cfg.multi_mode || obj.downlinks.size() > 1)
2023-12-16 19:58:45 +01:00
{
for (auto &dl : obj.downlinks)
2023-12-16 19:58:45 +01:00
{
if (dl.live)
{
2024-01-21 22:58:56 +01:00
std::string id = std::to_string(obj.norad) + "_" + std::to_string(dl.frequency) + "_live";
del_vfo(id);
}
if (dl.record)
{
std::string id = std::to_string(obj.norad) + "_" + std::to_string(dl.frequency) + "_record";
del_vfo(id);
}
if (dl.live || dl.record)
if (is_started && vfo_list.size() == 0 && autotrack_cfg.stop_sdr_when_idle)
stop_device();
2023-12-16 19:58:45 +01:00
}
}
else
{
if (obj.downlinks[0].record)
2024-01-21 21:24:35 +01:00
stop_recording();
if (obj.downlinks[0].live)
stop_processing();
if (autotrack_cfg.stop_sdr_when_idle)
stop_device();
}
};
2024-02-03 22:23:14 -05:00
}