added timing
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "locator/tcp_server.hpp"
|
||||
#include "processor_interface.hpp"
|
||||
#include "processing_live_config.hpp"
|
||||
#include "run_config.hpp"
|
||||
@@ -22,7 +23,8 @@ class DataProcessor {
|
||||
const config::RunConfig& config,
|
||||
ipc::ShmRing& preprocessed_ring,
|
||||
ipc::ShmRing& results_ring,
|
||||
ProcessorRegistry processors
|
||||
ProcessorRegistry processors,
|
||||
radar::locator::TcpServer* locator_server = nullptr
|
||||
);
|
||||
|
||||
void run(const std::atomic<bool>& stop_requested);
|
||||
@@ -38,12 +40,26 @@ class DataProcessor {
|
||||
[[nodiscard]] auto resolve_processor(const ProcessingLiveConfig& live_config) -> ProcessorInterface&;
|
||||
[[nodiscard]] auto should_replay_entire_history(const ProcessingLiveConfig& live_config) const -> bool;
|
||||
|
||||
// Merge live config with the latest socket-supplied speed (if any and if
|
||||
// not suppressed by `ignore_socket_speed`). The returned config is what
|
||||
// actually drives processing for this tick.
|
||||
[[nodiscard]] auto resolve_effective_live_config(const ProcessingLiveConfig& live_config) const
|
||||
-> ProcessingLiveConfig;
|
||||
|
||||
// Convert one processed collection into a locator filter spec, derived
|
||||
// from the live config and current processor mode.
|
||||
[[nodiscard]] auto build_locator_filter(const ProcessingLiveConfig& live_config) const
|
||||
-> radar::locator::FilterParams;
|
||||
|
||||
void publish_locator(const ipc::ResultCollection& collection, const ProcessingLiveConfig& live_config);
|
||||
|
||||
const config::RunConfig& config_;
|
||||
ipc::ShmRing& preprocessed_ring_;
|
||||
ipc::ShmRing& results_ring_;
|
||||
ProcessorRegistry processors_{};
|
||||
std::string default_processor_mode_{};
|
||||
ProcessingLiveConfigLoader live_config_loader_;
|
||||
radar::locator::TcpServer* locator_server_ = nullptr;
|
||||
};
|
||||
|
||||
[[nodiscard]] auto create_default_processors() -> ProcessorRegistry;
|
||||
|
||||
@@ -52,6 +52,17 @@ struct ProcessingLiveConfig {
|
||||
// BP image is computed in the y=imaging_plane_y_m slice of the 3D grid.
|
||||
// Default 0 keeps legacy 1D antenna layouts imaging in the antenna plane.
|
||||
float gpr_imaging_plane_y_m = 0.0F;
|
||||
// Locator filter parameters. Mode-dependent threshold (legacy_gpr uses
|
||||
// `legacy_gpr_min_visible_pair_count`, everything else uses
|
||||
// `gpr_min_visible_score`). Draw limits apply only to non-legacy modes.
|
||||
float gpr_min_visible_score = 0.0F;
|
||||
float legacy_gpr_min_visible_pair_count = 0.0F;
|
||||
std::uint32_t gpr_max_detected_objects_to_draw = 0;
|
||||
std::uint32_t gpr_draw_top_m_objects = 0;
|
||||
// When true, the data_processor ignores socket-supplied `vlc` updates and
|
||||
// keeps using `gpr_speed_m_s` from this file. Mirrored from the GUI's
|
||||
// "ignore socket speed" checkbox.
|
||||
bool ignore_socket_speed = false;
|
||||
bool reprocess_current_result = true;
|
||||
std::uint64_t history_command_seq = 0;
|
||||
HistoryCommand history_command = HistoryCommand::None;
|
||||
|
||||
@@ -37,14 +37,16 @@ DataProcessor::DataProcessor(
|
||||
const config::RunConfig& config,
|
||||
ipc::ShmRing& preprocessed_ring,
|
||||
ipc::ShmRing& results_ring,
|
||||
ProcessorRegistry processors
|
||||
ProcessorRegistry processors,
|
||||
radar::locator::TcpServer* locator_server
|
||||
)
|
||||
: config_(config),
|
||||
preprocessed_ring_(preprocessed_ring),
|
||||
results_ring_(results_ring),
|
||||
processors_(std::move(processors)),
|
||||
default_processor_mode_(kDefaultProcessorMode),
|
||||
live_config_loader_(config.runtime.processing_live_config_path) {
|
||||
live_config_loader_(config.runtime.processing_live_config_path),
|
||||
locator_server_(locator_server) {
|
||||
if (processors_.empty()) {
|
||||
throw std::runtime_error("DataProcessor requires at least one processor");
|
||||
}
|
||||
@@ -61,7 +63,8 @@ void DataProcessor::run(const std::atomic<bool>& stop_requested) {
|
||||
std::uint64_t last_applied_history_command_seq = 0;
|
||||
|
||||
while (!stop_requested.load(std::memory_order_relaxed)) {
|
||||
const auto live_config = live_config_loader_.refresh_if_needed();
|
||||
const auto live_config_raw = live_config_loader_.refresh_if_needed();
|
||||
const auto live_config = resolve_effective_live_config(live_config_raw);
|
||||
const auto live_revision = live_config_loader_.revision();
|
||||
auto& processor = resolve_processor(live_config);
|
||||
|
||||
@@ -89,6 +92,7 @@ void DataProcessor::run(const std::atomic<bool>& stop_requested) {
|
||||
live_config
|
||||
);
|
||||
publish_result_collection(replay_result, results_ring_);
|
||||
publish_locator(replay_result, live_config);
|
||||
}
|
||||
} else if (!preprocessed_history.empty()) {
|
||||
const auto replay_result = process_collection(
|
||||
@@ -98,6 +102,7 @@ void DataProcessor::run(const std::atomic<bool>& stop_requested) {
|
||||
live_config
|
||||
);
|
||||
publish_result_collection(replay_result, results_ring_);
|
||||
publish_locator(replay_result, live_config);
|
||||
}
|
||||
last_replayed_revision = live_revision;
|
||||
}
|
||||
@@ -116,6 +121,7 @@ void DataProcessor::run(const std::atomic<bool>& stop_requested) {
|
||||
live_config
|
||||
);
|
||||
publish_result_collection(result_collection, results_ring_);
|
||||
publish_locator(result_collection, live_config);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -129,7 +135,13 @@ auto DataProcessor::process_collection(
|
||||
ProcessorInterface& processor,
|
||||
const ProcessingLiveConfig& live_config
|
||||
) -> ipc::ResultCollection {
|
||||
return processor.process_collection(config_, preprocessed, previous_collections, live_config);
|
||||
const auto started_at = std::chrono::steady_clock::now();
|
||||
auto result = processor.process_collection(config_, preprocessed, previous_collections, live_config);
|
||||
const auto finished_at = std::chrono::steady_clock::now();
|
||||
result.processing_duration_ns = static_cast<std::uint64_t>(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(finished_at - started_at).count()
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto DataProcessor::resolve_processor(const ProcessingLiveConfig& live_config) -> ProcessorInterface& {
|
||||
@@ -151,6 +163,54 @@ auto DataProcessor::should_replay_entire_history(const ProcessingLiveConfig& liv
|
||||
return requested_mode == "bscan";
|
||||
}
|
||||
|
||||
auto DataProcessor::resolve_effective_live_config(const ProcessingLiveConfig& live_config) const
|
||||
-> ProcessingLiveConfig {
|
||||
if (live_config.ignore_socket_speed || locator_server_ == nullptr) {
|
||||
return live_config;
|
||||
}
|
||||
const auto socket_speed = locator_server_->latest_socket_speed();
|
||||
if (!socket_speed.has_value()) {
|
||||
return live_config;
|
||||
}
|
||||
ProcessingLiveConfig effective = live_config;
|
||||
effective.gpr_speed_m_s = static_cast<float>(*socket_speed);
|
||||
return effective;
|
||||
}
|
||||
|
||||
auto DataProcessor::build_locator_filter(const ProcessingLiveConfig& live_config) const
|
||||
-> radar::locator::FilterParams {
|
||||
const std::string requested_mode =
|
||||
live_config.processor_mode.empty() ? default_processor_mode_ : live_config.processor_mode;
|
||||
|
||||
radar::locator::FilterParams filter{};
|
||||
if (requested_mode == "legacy_gpr") {
|
||||
filter.min_score = live_config.legacy_gpr_min_visible_pair_count;
|
||||
// The GUI deliberately disables the "draw top N" capping for legacy
|
||||
// GPR, so we also skip it on the wire to match observation semantics.
|
||||
filter.draw_limits.reset();
|
||||
} else {
|
||||
filter.min_score = live_config.gpr_min_visible_score;
|
||||
if (live_config.gpr_max_detected_objects_to_draw > 0U
|
||||
&& live_config.gpr_draw_top_m_objects > 0U) {
|
||||
filter.draw_limits = radar::locator::DrawLimits{
|
||||
.max_detected_objects = live_config.gpr_max_detected_objects_to_draw,
|
||||
.draw_top_objects = live_config.gpr_draw_top_m_objects,
|
||||
};
|
||||
}
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
void DataProcessor::publish_locator(
|
||||
const ipc::ResultCollection& collection,
|
||||
const ProcessingLiveConfig& live_config
|
||||
) {
|
||||
if (locator_server_ == nullptr || !locator_server_->is_running()) {
|
||||
return;
|
||||
}
|
||||
locator_server_->publish(collection, build_locator_filter(live_config));
|
||||
}
|
||||
|
||||
auto create_default_processors() -> ProcessorRegistry {
|
||||
ProcessorRegistry processors{};
|
||||
{
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
#include <csignal>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "data_processor.hpp"
|
||||
#include "locator/tcp_server.hpp"
|
||||
#include "run_config.hpp"
|
||||
#include "shm_ring.hpp"
|
||||
|
||||
@@ -21,6 +23,8 @@ void signal_handler(int /*signal*/) {
|
||||
void install_signal_handlers() {
|
||||
std::signal(SIGINT, signal_handler);
|
||||
std::signal(SIGTERM, signal_handler);
|
||||
// Writing to a peer-closed socket would otherwise terminate the process.
|
||||
std::signal(SIGPIPE, SIG_IGN);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto read_config_path(int argc, char** argv) -> std::string {
|
||||
@@ -34,6 +38,21 @@ void install_signal_handlers() {
|
||||
return config_path;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto start_locator_server(const radar::config::RunConfig& config)
|
||||
-> std::unique_ptr<radar::locator::TcpServer> {
|
||||
if (!config.locator_server.enabled) {
|
||||
return nullptr;
|
||||
}
|
||||
auto server = std::make_unique<radar::locator::TcpServer>(config.locator_server);
|
||||
try {
|
||||
server->start();
|
||||
} catch (const std::exception& exception) {
|
||||
std::cerr << "data_processor: locator server disabled (" << exception.what() << ")\n";
|
||||
return nullptr;
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
@@ -54,11 +73,14 @@ int main(int argc, char** argv) {
|
||||
config.rings.results.slot_size_bytes
|
||||
);
|
||||
|
||||
auto locator_server = start_locator_server(config);
|
||||
|
||||
radar::processing::DataProcessor processor(
|
||||
config,
|
||||
preprocessed_ring,
|
||||
results_ring,
|
||||
radar::processing::create_default_processors()
|
||||
radar::processing::create_default_processors(),
|
||||
locator_server.get()
|
||||
);
|
||||
processor.run(g_stop_requested);
|
||||
return 0;
|
||||
|
||||
@@ -311,6 +311,32 @@ void apply_legacy_gpr_algorithm_alias(ProcessingLiveConfig& config, const std::s
|
||||
}
|
||||
config.gpr_imaging_plane_y_m = static_cast<float>(found->get<double>());
|
||||
}
|
||||
if (const auto found = root.find("gpr_min_visible_score"); found != root.end()) {
|
||||
if (!found->is_number()) {
|
||||
throw std::runtime_error("processing.gpr_min_visible_score must be number");
|
||||
}
|
||||
config.gpr_min_visible_score = static_cast<float>(found->get<double>());
|
||||
}
|
||||
if (const auto found = root.find("legacy_gpr_min_visible_pair_count"); found != root.end()) {
|
||||
if (!found->is_number()) {
|
||||
throw std::runtime_error("processing.legacy_gpr_min_visible_pair_count must be number");
|
||||
}
|
||||
config.legacy_gpr_min_visible_pair_count = static_cast<float>(found->get<double>());
|
||||
}
|
||||
if (const auto found = root.find("gpr_max_detected_objects_to_draw"); found != root.end()) {
|
||||
config.gpr_max_detected_objects_to_draw =
|
||||
parse_u32_number(*found, "processing.gpr_max_detected_objects_to_draw");
|
||||
}
|
||||
if (const auto found = root.find("gpr_draw_top_m_objects"); found != root.end()) {
|
||||
config.gpr_draw_top_m_objects =
|
||||
parse_u32_number(*found, "processing.gpr_draw_top_m_objects");
|
||||
}
|
||||
if (const auto found = root.find("ignore_socket_speed"); found != root.end()) {
|
||||
if (!found->is_boolean()) {
|
||||
throw std::runtime_error("processing.ignore_socket_speed must be bool");
|
||||
}
|
||||
config.ignore_socket_speed = found->get<bool>();
|
||||
}
|
||||
if (const auto found = root.find("reprocess_current_result"); found != root.end()) {
|
||||
if (!found->is_boolean()) {
|
||||
throw std::runtime_error("processing.reprocess_current_result must be bool");
|
||||
|
||||
Reference in New Issue
Block a user