some fixes and improvements
This commit is contained in:
@@ -34,6 +34,19 @@ class RadarDriver {
|
||||
virtual void close() = 0;
|
||||
/** @brief Acquire one sweep containing the forward traces exposed by the driver. */
|
||||
[[nodiscard]] virtual auto acquire_sweep() -> SweepTrace = 0;
|
||||
|
||||
/**
|
||||
* @brief Announce which switch combo the next `acquire_sweep` belongs to.
|
||||
*
|
||||
* Real radars are agnostic to this because the switch state itself decides
|
||||
* what they see. Mock drivers use it to synthesise per-combo variation so
|
||||
* downstream plots show eight distinct traces for an eight-combo run
|
||||
* instead of eight identical curves stacked on top of each other.
|
||||
*
|
||||
* Default implementation is a no-op so production drivers do not need to
|
||||
* override.
|
||||
*/
|
||||
virtual void set_active_combo(const ipc::ComboKey& /*combo*/) {}
|
||||
};
|
||||
|
||||
} // namespace radar::drivers
|
||||
|
||||
+18
-3
@@ -126,6 +126,10 @@ void LibreVnaMinimalDriver::close() {
|
||||
is_open_ = false;
|
||||
}
|
||||
|
||||
void LibreVnaMinimalDriver::set_active_combo(const ipc::ComboKey& combo) {
|
||||
active_combo_ = combo;
|
||||
}
|
||||
|
||||
auto LibreVnaMinimalDriver::acquire_sweep() -> SweepTrace {
|
||||
if (!is_open_) {
|
||||
throw std::runtime_error("Radar driver is not open");
|
||||
@@ -189,6 +193,17 @@ auto LibreVnaMinimalDriver::acquire_mock() -> SweepTrace {
|
||||
const float range_drift_m =
|
||||
0.01F * std::sin(0.07F * static_cast<float>(sweep_index_));
|
||||
|
||||
// Combo-dependent variation. Without this the mock returns near-identical
|
||||
// S21 for every (input, output) combo and an eight-combo pass-through plot
|
||||
// collapses into a single visible trace. The factors below are arbitrary
|
||||
// but chosen small enough that the overall response stays in a reasonable
|
||||
// band and large enough that each pair is visually distinct.
|
||||
const auto input_pos = static_cast<float>(active_combo_.input_pos);
|
||||
const auto output_pos = static_cast<float>(active_combo_.output_pos);
|
||||
const float combo_amplitude_gain = 0.55F + 0.08F * input_pos + 0.05F * output_pos;
|
||||
const float combo_phase_offset = 0.4F * input_pos + 0.9F * output_pos;
|
||||
const float combo_range_offset_m = 0.05F * input_pos + 0.12F * output_pos;
|
||||
|
||||
// Deterministic-per-sweep noise so two consecutive frames look distinct
|
||||
// but the test stays reproducible for any given sweep index.
|
||||
std::mt19937 noise_engine(
|
||||
@@ -205,7 +220,7 @@ auto LibreVnaMinimalDriver::acquire_mock() -> SweepTrace {
|
||||
std::complex<float> s11_total{0.0F, 0.0F};
|
||||
|
||||
for (const auto& target : kMockTargets) {
|
||||
const float range_m = target.range_m + range_drift_m;
|
||||
const float range_m = target.range_m + range_drift_m + combo_range_offset_m;
|
||||
// Round-trip phase: 2π·f·(2R/v).
|
||||
const float round_trip_phase =
|
||||
2.0F * detail::kPi * frequency_hz * (2.0F * range_m / kGroundVelocityMps);
|
||||
@@ -216,8 +231,8 @@ auto LibreVnaMinimalDriver::acquire_mock() -> SweepTrace {
|
||||
std::exp(-kAttenuationCoeffPerMeterAtRefHz * range_m * frequency_scale);
|
||||
|
||||
const std::complex<float> contribution = std::polar<float>(
|
||||
target.reflection_magnitude * spreading * attenuation,
|
||||
-round_trip_phase
|
||||
target.reflection_magnitude * spreading * attenuation * combo_amplitude_gain,
|
||||
-round_trip_phase + combo_phase_offset
|
||||
);
|
||||
s21_total += contribution;
|
||||
s11_total += kS11CrossCouplingFactor * contribution;
|
||||
|
||||
+5
@@ -43,6 +43,7 @@ class LibreVnaMinimalDriver final : public RadarDriver {
|
||||
void open() override;
|
||||
void close() override;
|
||||
[[nodiscard]] auto acquire_sweep() -> SweepTrace override;
|
||||
void set_active_combo(const ipc::ComboKey& combo) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -92,6 +93,10 @@ class LibreVnaMinimalDriver final : public RadarDriver {
|
||||
LibreVnaMinimalDriverSettings settings_{};
|
||||
bool is_open_ = false;
|
||||
std::uint64_t sweep_index_ = 0;
|
||||
// Latest combo announced by the orchestrator. Used by the mock backend to
|
||||
// give each (input, output) pair a slightly different reflectivity profile
|
||||
// so a multi-combo run does not render as eight identical traces.
|
||||
ipc::ComboKey active_combo_{};
|
||||
|
||||
libusb_context* usb_context_ = nullptr;
|
||||
libusb_device_handle* usb_handle_ = nullptr;
|
||||
|
||||
@@ -157,6 +157,9 @@ auto SweepOrchestrator::acquire_one_collection(
|
||||
input_switch_driver_.switch_to(combo.input_pos);
|
||||
sleep_if_needed_ms(config_.runtime.settling_ms);
|
||||
|
||||
// Production drivers ignore this; mock drivers use it to give every
|
||||
// (input, output) pair its own synthetic response.
|
||||
radar_driver_.set_active_combo(combo);
|
||||
auto sweep = radar_driver_.acquire_sweep();
|
||||
validate_sweep(sweep);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user