Skip to content

Commit e5d55fb

Browse files
author
Evgeni Raikhel
committed
Add generic composite-option API, proven via HKR Temporal Filter DPP
Introduces a new API surface for multi-parameter XU controls that are exchanged as one atomic struct in a single UVC transaction, distinct from the existing single-value rs2_option mechanism: - C API: rs2_set/get_composite_option, rs2_get_composite_option_range, keyed by their own rs2_composite_option_id enum (kept separate from rs2_option so composite controls don't collide with the scalar option-numbering space), plus metadata queries (description, read-only, supported-options enumeration). - C++ wrapper: rs2::options gains get_composite_option_as<T>()/ set_composite_option_from<T>()/get_composite_option_range_as<T>(), casting the raw payload to/from an application-defined struct that matches the documented wire layout - no SDK-side per-feature struct header, so adding a new control doesn't require an SDK release. - composite_xu_option implements the mechanism against a real XU transport; options_container gets a second, separate composite-option registry alongside its existing scalar one. HKR Temporal Filter DPP is the first control built on this mechanism, registered as its own embedded filter (not directly on the sensor), with a realsense-viewer panel and a fake-transport example proving the round-trip is atomic. This commit represents the API's final shape; the design went through several rounds of rework (ownership model, identity/enum split, casting approach) before landing here.
1 parent 42e5f69 commit e5d55fb

31 files changed

Lines changed: 1307 additions & 0 deletions

common/device-model.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#include <librealsense2/rs.hpp>
66
#include <rs-config.h>
77

8+
#include <algorithm>
9+
#include <cstring>
10+
811
#include <third-party/filesystem/glob.h>
912

1013
#include <imgui.h>
@@ -2871,6 +2874,84 @@ namespace rs2
28712874
}
28722875
}
28732876

2877+
// PROTOTYPE / DEMO: HKR Temporal Filter DPP "structured API" panel. Only
2878+
// rendered for a sensor that actually exposes
2879+
// RS2_COMPOSITE_OPTION_HKR_TEMPORAL_FILTER_DPP - composite options are a
2880+
// completely separate identity space from ordinary rs2_option scalar options, so
2881+
// support is checked via get_supported_composite_options(), not via
2882+
// supports()/is<T>()/as<T>() casting. Uses the DIRECT
2883+
// get_composite_option()/set_composite_option() C++ methods, which call
2884+
// rs2_get_composite_option/rs2_set_composite_option under the hood - no wrapper
2885+
// handle type. The SDK ships a public struct for this one prototype control
2886+
// (rs2_temporal_filter_dpp_config, see rs_hkr_temporal_filter_dpp.h) that this
2887+
// viewer casts the raw bytes to/from. All fields are sent together in ONE atomic
2888+
// UVC transaction when "Apply" is clicked - never as separate per-field option
2889+
// writes.
2890+
auto supported_composite_options = sub->s->get_supported_composite_options();
2891+
bool has_temporal_filter_dpp = std::find(supported_composite_options.begin(),
2892+
supported_composite_options.end(),
2893+
RS2_COMPOSITE_OPTION_HKR_TEMPORAL_FILTER_DPP)
2894+
!= supported_composite_options.end();
2895+
if (has_temporal_filter_dpp)
2896+
{
2897+
label = rsutils::string::from() << "HKR Temporal Filter DPP (prototype)##" << id;
2898+
if (ImGui::TreeNode(label.c_str()))
2899+
{
2900+
try
2901+
{
2902+
if (!sub->temporal_filter_dpp_populated)
2903+
{
2904+
auto bytes = sub->s->get_composite_option(RS2_COMPOSITE_OPTION_HKR_TEMPORAL_FILTER_DPP);
2905+
if (bytes.size() != sizeof(rs2_temporal_filter_dpp_config))
2906+
throw std::runtime_error("HKR Temporal Filter DPP: unexpected payload size from get_composite_option");
2907+
2908+
rs2_temporal_filter_dpp_config cfg{};
2909+
memcpy(&cfg, bytes.data(), sizeof(cfg));
2910+
sub->temporal_filter_dpp_enabled = cfg.enabled;
2911+
sub->temporal_filter_dpp_smooth_alpha = cfg.smooth_alpha;
2912+
sub->temporal_filter_dpp_smooth_delta = cfg.smooth_delta;
2913+
sub->temporal_filter_dpp_persistency_index = cfg.persistency_index;
2914+
sub->temporal_filter_dpp_populated = true;
2915+
}
2916+
2917+
bool enabled_bool = (sub->temporal_filter_dpp_enabled != 0);
2918+
label = rsutils::string::from() << "Enabled##temporal_filter_dpp_enabled" << id;
2919+
if (ImGui::Checkbox(label.c_str(), &enabled_bool))
2920+
sub->temporal_filter_dpp_enabled = enabled_bool ? 1 : 0;
2921+
2922+
label = rsutils::string::from() << "Smooth Alpha##temporal_filter_dpp_alpha" << id;
2923+
ImGui::DragFloat(label.c_str(), &sub->temporal_filter_dpp_smooth_alpha, 0.01f, 0.f, 1.f);
2924+
2925+
label = rsutils::string::from() << "Smooth Delta##temporal_filter_dpp_delta" << id;
2926+
ImGui::DragInt(label.c_str(), &sub->temporal_filter_dpp_smooth_delta, 1, 1, 100);
2927+
2928+
label = rsutils::string::from() << "Persistency Index##temporal_filter_dpp_persistency" << id;
2929+
ImGui::DragInt(label.c_str(), &sub->temporal_filter_dpp_persistency_index, 1, 0, 8);
2930+
2931+
label = rsutils::string::from() << "Send##temporal_filter_dpp_send" << id;
2932+
if (ImGui::Button(label.c_str()))
2933+
{
2934+
rs2_temporal_filter_dpp_config cfg{};
2935+
cfg.enabled = sub->temporal_filter_dpp_enabled;
2936+
cfg.smooth_alpha = sub->temporal_filter_dpp_smooth_alpha;
2937+
cfg.smooth_delta = sub->temporal_filter_dpp_smooth_delta;
2938+
cfg.persistency_index = sub->temporal_filter_dpp_persistency_index;
2939+
sub->s->set_composite_option(RS2_COMPOSITE_OPTION_HKR_TEMPORAL_FILTER_DPP, &cfg, sizeof(cfg));
2940+
}
2941+
}
2942+
catch (const error& e)
2943+
{
2944+
error_message = error_to_string(e);
2945+
}
2946+
catch (const std::exception& e)
2947+
{
2948+
error_message = e.what();
2949+
}
2950+
2951+
ImGui::TreePop();
2952+
}
2953+
}
2954+
28742955
draw_embedded_filters(sub, windows_width, window, viewer,
28752956
error_message, label, draw_later, update_read_only_options);
28762957

common/subdevice-model.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,17 @@ namespace rs2
230230
std::vector<std::shared_ptr<embedded_filter_model>> embedded_filters;
231231
bool embedded_filters_enabled = true;
232232

233+
// PROTOTYPE / DEMO: UI state for the HKR Temporal Filter DPP "structured API" panel
234+
// (gated on RS2_COMPOSITE_OPTION_HKR_TEMPORAL_FILTER_DPP appearing in
235+
// sub->s->get_supported_composite_options() - see device-model.cpp). Widget values only
236+
// change locally until "Apply" is pressed; that single click issues one
237+
// set_composite_option() call, i.e. one atomic UVC transaction.
238+
bool temporal_filter_dpp_populated = false;
239+
int temporal_filter_dpp_enabled = 0;
240+
float temporal_filter_dpp_smooth_alpha = 0.4f;
241+
int temporal_filter_dpp_smooth_delta = 20;
242+
int temporal_filter_dpp_persistency_index = 3;
243+
233244
bool uvmapping_calib_full = false;
234245
device_model* dev_model;
235246
std::string _opt_base_label;

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,6 @@ add_subdirectory(on-chip-calib)
5858
add_subdirectory(eth-config)
5959
add_subdirectory(embedded-filters)
6060
add_subdirectory(object-detection)
61+
add_subdirectory(hkr-temporal-filter-dpp-mock)
6162

6263
unset_security_flags_for_executable()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# License: Apache 2.0. See LICENSE file in root directory.
2+
# Copyright(c) 2026 RealSense, Inc. All Rights Reserved.
3+
cmake_minimum_required(VERSION 3.10)
4+
5+
project(RealsenseExamplesHkrTemporalFilterDppMock)
6+
7+
# PROTOTYPE / DEMO test scaffolding: proves the atomicity + round-trip behavior of the generic
8+
# "composite option" mechanism (include/librealsense2/h/rs_composite_option.h,
9+
# src/composite-option-interface.h) as applied to RS2_COMPOSITE_OPTION_HKR_TEMPORAL_FILTER_DPP,
10+
# against a fake in-memory librealsense::composite_option_interface implementation standing in for
11+
# real HKR/D555 hardware (librealsense::composite_xu_option, src/ds/composite-xu-option.h), which
12+
# is not present on this dev machine. Drives the mechanism through the REAL PUBLIC ENTRY POINTS
13+
# (rs2_set_composite_option/rs2_get_composite_option and the direct
14+
# rs2::options::get_composite_option()/set_composite_option() C++ methods - no casting/handle
15+
# type involved) rather than bypassing into an internal transport class directly, so it links
16+
# against realsense2 like any other example.
17+
add_executable(rs-hkr-temporal-filter-dpp-mock
18+
rs-hkr-temporal-filter-dpp-mock.cpp
19+
)
20+
set_property(TARGET rs-hkr-temporal-filter-dpp-mock PROPERTY CXX_STANDARD 14)
21+
target_link_libraries(rs-hkr-temporal-filter-dpp-mock PRIVATE ${LRS_TARGET})
22+
set_target_properties (rs-hkr-temporal-filter-dpp-mock PROPERTIES FOLDER Examples)
23+
install(TARGETS rs-hkr-temporal-filter-dpp-mock RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

0 commit comments

Comments
 (0)