added GPR
This commit is contained in:
@@ -81,6 +81,26 @@ struct PreprocessConfig {
|
||||
std::string reference_bundle_path{};
|
||||
};
|
||||
|
||||
struct GprTxGeometry {
|
||||
// Transmitter geometry keyed by output switch position.
|
||||
std::uint32_t output_pos = 0;
|
||||
float x_m = 0.0F;
|
||||
};
|
||||
|
||||
struct GprRxGeometry {
|
||||
// Receiver geometry keyed by input switch position.
|
||||
std::uint32_t input_pos = 0;
|
||||
float x_m = 0.0F;
|
||||
};
|
||||
|
||||
struct GprConfig {
|
||||
// Stable collection-level GPR processing settings.
|
||||
std::string mode = "point";
|
||||
float relative_permittivity = 1.0F;
|
||||
std::vector<GprTxGeometry> tx_geometry{};
|
||||
std::vector<GprRxGeometry> rx_geometry{};
|
||||
};
|
||||
|
||||
struct RunConfig {
|
||||
// Single configuration object shared by all C++ processes.
|
||||
RadarConfig radar{};
|
||||
@@ -89,6 +109,7 @@ struct RunConfig {
|
||||
RingsConfig rings{};
|
||||
RuntimeConfig runtime{};
|
||||
PreprocessConfig preprocess{};
|
||||
GprConfig gpr{};
|
||||
std::vector<radar::ipc::ComboKey> run_combos{};
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
@@ -214,6 +216,69 @@ void validate_combo_key(const ipc::ComboKey& key, const RunConfig& config) {
|
||||
}
|
||||
}
|
||||
|
||||
void validate_gpr_config(const GprConfig& config, const RunConfig& run_config) {
|
||||
if (config.mode != "point" && config.mode != "extended") {
|
||||
throw std::runtime_error("gpr.mode must be either 'point' or 'extended'");
|
||||
}
|
||||
if (!(config.relative_permittivity > 0.0F)) {
|
||||
throw std::runtime_error("gpr.relative_permittivity must be > 0");
|
||||
}
|
||||
|
||||
std::unordered_set<std::uint32_t> seen_tx_positions{};
|
||||
for (const auto& entry : config.tx_geometry) {
|
||||
if (entry.output_pos >= run_config.output_switch.positions) {
|
||||
throw std::runtime_error("gpr.tx_geometry output_pos is out of range");
|
||||
}
|
||||
if (!seen_tx_positions.insert(entry.output_pos).second) {
|
||||
throw std::runtime_error("gpr.tx_geometry contains duplicate output_pos");
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<std::uint32_t> seen_rx_positions{};
|
||||
for (const auto& entry : config.rx_geometry) {
|
||||
if (entry.input_pos >= run_config.input_switch.positions) {
|
||||
throw std::runtime_error("gpr.rx_geometry input_pos is out of range");
|
||||
}
|
||||
if (!seen_rx_positions.insert(entry.input_pos).second) {
|
||||
throw std::runtime_error("gpr.rx_geometry contains duplicate input_pos");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] auto parse_gpr_config(const Json& object, const RunConfig& run_config) -> GprConfig {
|
||||
const auto* gpr_obj = as_object(object, "gpr");
|
||||
GprConfig config{};
|
||||
config.mode = optional_string(*gpr_obj, "mode", "point");
|
||||
config.relative_permittivity = optional_f32(*gpr_obj, "relative_permittivity", 1.0F);
|
||||
|
||||
if (const auto* tx_value = optional_field(*gpr_obj, "tx_geometry"); tx_value != nullptr) {
|
||||
const auto* tx_array = as_array(*tx_value, "gpr.tx_geometry");
|
||||
config.tx_geometry.reserve(tx_array->size());
|
||||
for (const auto& entry_value : *tx_array) {
|
||||
const auto* entry_obj = as_object(entry_value, "gpr.tx_geometry[]");
|
||||
GprTxGeometry entry{};
|
||||
entry.output_pos = optional_u32(*entry_obj, "output_pos", 0U);
|
||||
entry.x_m = optional_f32(*entry_obj, "x_m", 0.0F);
|
||||
config.tx_geometry.push_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto* rx_value = optional_field(*gpr_obj, "rx_geometry"); rx_value != nullptr) {
|
||||
const auto* rx_array = as_array(*rx_value, "gpr.rx_geometry");
|
||||
config.rx_geometry.reserve(rx_array->size());
|
||||
for (const auto& entry_value : *rx_array) {
|
||||
const auto* entry_obj = as_object(entry_value, "gpr.rx_geometry[]");
|
||||
GprRxGeometry entry{};
|
||||
entry.input_pos = optional_u32(*entry_obj, "input_pos", 0U);
|
||||
entry.x_m = optional_f32(*entry_obj, "x_m", 0.0F);
|
||||
config.rx_geometry.push_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
validate_gpr_config(config, run_config);
|
||||
return config;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto parse_switch_config(
|
||||
const Json& object,
|
||||
const std::string& default_name,
|
||||
@@ -379,6 +444,12 @@ auto load_run_config(const std::string& path) -> RunConfig {
|
||||
config.preprocess.reference_bundle_path = optional_string(*preprocess_obj, "reference_bundle_path", "");
|
||||
}
|
||||
|
||||
if (const auto* gpr_value = optional_field(*root_obj, "gpr"); gpr_value != nullptr) {
|
||||
config.gpr = parse_gpr_config(*gpr_value, config);
|
||||
} else {
|
||||
validate_gpr_config(config.gpr, config);
|
||||
}
|
||||
|
||||
{
|
||||
const auto* rings_obj = as_object(required_field(*root_obj, "rings"), "rings");
|
||||
config.rings.raw = parse_ring_endpoint(*rings_obj, "raw", config.rings.raw);
|
||||
|
||||
Reference in New Issue
Block a user