keep sweeps in acquisition order through history replays

The processor appended sweeps the GUI fed back to its own history, so its next replay
published them twice and out of order, and the B-scan came out with rotated columns.
Fed-back sweeps now stay out of that history, results are kept in timestamp order,
picking the displayed combo only redraws and only new sweeps are recorded to disk.
This commit is contained in:
Ayzen
2026-10-02 16:05:32 +03:00
parent 45861f4047
commit d283ecfdf1
11 changed files with 421 additions and 91 deletions
@@ -514,9 +514,16 @@ struct Oblique {
} // namespace
struct Sar3dProcessor::State {
// A-scans by collection id for `frames_key`; null marks a collection that
// could not be processed, so its error is reported once and not retried.
std::map<std::uint64_t, std::shared_ptr<const Frame>> frames{};
// A sweep is its id with its timestamp: ids start again from 1 on every run,
// while the processor and this cache outlive runs.
using SweepKey = std::pair<std::uint64_t, std::uint64_t>;
[[nodiscard]] static auto sweep_key(const ipc::PreprocessedCollection& collection) -> SweepKey {
return {collection.collection_id, collection.monotonic_ns};
}
// A-scans by sweep for `frames_key`; null marks a sweep that could not be
// processed, so its error is reported once and not retried.
std::map<SweepKey, std::shared_ptr<const Frame>> frames{};
AscanKey frames_key{};
std::unique_ptr<sar3d::Gpu> gpu{};
std::string gpu_error{};
@@ -525,7 +532,7 @@ struct Sar3dProcessor::State {
auto frame(const ipc::PreprocessedCollection& collection, const Settings& settings, sar3d::Gpu& gpu)
-> std::shared_ptr<const Frame> {
if (const auto found = frames.find(collection.collection_id); found != frames.end()) {
if (const auto found = frames.find(sweep_key(collection)); found != frames.end()) {
return found->second;
}
std::shared_ptr<const Frame> frame{};
@@ -534,7 +541,7 @@ struct Sar3dProcessor::State {
} catch (const std::exception& error) {
report_error(error.what());
}
frames.emplace(collection.collection_id, frame);
frames.emplace(sweep_key(collection), frame);
return frame;
}
@@ -572,10 +579,10 @@ struct Sar3dProcessor::State {
// the newest one, so the image trails the input by r frames. Collections
// that left the aperture are dropped from the cache.
std::vector<std::shared_ptr<const Frame>> aperture{};
std::map<std::uint64_t, std::shared_ptr<const Frame>> kept{{collection.collection_id, newest}};
std::map<SweepKey, std::shared_ptr<const Frame>> kept{{sweep_key(collection), newest}};
for (const auto& member : previous.last(std::min(previous.size(), 2U * settings.frame_radius))) {
auto member_frame = frame(member, settings, gpu);
kept.emplace(member.collection_id, member_frame);
kept.emplace(sweep_key(member), member_frame);
const bool same_axis = member_frame != nullptr && member_frame->samples == newest->samples &&
member_frame->dt_s == newest->dt_s;
if (same_axis) {