dc_util owns parameter declaration; nav2_util stays a dependency
Before this decision, parameter declaration in dc_measurements/dc_group was three
patterns at once: most Measurement/Condition plugins called
nav2_util::declare_parameter_if_not_declared directly, duplicating the same
declare-then-get_parameter-then-fatal-on-failure boilerplate in each onConfigure();
measurement_server.cpp mixed that with a handful of raw declare_parameter calls for
its own node-level parameters (which throw on redeclaration instead of being idempotent);
and a dc_util::get_*_type_param() helper family existed but was only used in ~20 of the
roughly 90 plugin-parameter call sites, wrapping nav2_util::declare_parameter_if_not_declared
for the rest without most callers going through it.
Decision
nav2_utilstays a dependency.MeasurementServeralready inheritsnav2_util::LifecycleNodefor the bond/lifecycle machinerydc_lifecycle_managerorchestrates — droppingnav2_utilisn't on the table regardless of how parameter declaration is handled, so re-implementingdeclare_parameter_if_not_declared's idempotent-declare logic insidedc_utilwould only add a second implementation of the same thing for no dependency-removal benefit.dc_util::get_*_type_param()/get_*_param()become the single sanctioned way to declare a parameter indc_measurements/dc_groupC++ code. Plugin authors call these, neverdeclare_parameterornav2_util::declare_parameter_if_not_declareddirectly (documented indoc/src/dc/contributing.md). Internally these helpers still callnav2_util::declare_parameter_if_not_declared—dc_util/include/dc_util/node_utils.hppis now the only file indc_measurements/dc_groupallowed to referencenav2_utilfor parameter declaration — so the dependency is kept, but callers no longer see it or hand-roll its error handling.- The helper family was extended to cover every parameter type actually declared across
the plugins (
double, and mandatoryvector<bool>/vector<int64_t>/vector<double>were missing) plus a node-level (unprefixed) variant forMeasurementServer's own parameters, so the rawdeclare_parametercalls in its constructor could move to the same idempotent pattern as everything else. dc_group(Python/rclpy) keeps its existing plainself.declare_parameter(...)calls. There is no Python equivalent ofnav2_util::declare_parameter_if_not_declaredin this codebase, and none is needed: everyGroupServerparameter is declared exactly once, ininit_parameters(), never re-entered — the idempotent-declare problem the C++ helpers solve (multiple plugins/onConfigure() calls potentially racing to declare a shared namespace) doesn't exist on the group-server side. Introducing a declare-if-not-declared wrapper there would be solving a problem this file doesn't have.
Consequences
- A new plugin parameter is one
dc_util::get_*_type_param()call, not a declare-if-not-declared pair plus a manual fatal-on-missing check. - Two pre-existing bugs surfaced while converting call sites —
bool_equal.cpp'svalue_field isdoubledespite the parameter being declaredPARAMETER_BOOL, anddistance_traveled.cppdeclarestransform_tolerancebut reads back the different, undeclared nametransform_timeout— were deliberately left as directnav2_util::declare_parameter_if_not_declared/get_parametercalls rather than folded into the new helpers, so as not to silently change behavior while unifying the declaration pattern. Both are noted inline and are follow-up work, not part of this change.