Repository navigation
refactor(autoware_radar_objects_adapter): separate the conversion from the node - #13470
Conversation
…ts role RadarObjectsAdapter becomes RadarObjectsAdapterNode in the namespace autoware::radar_objects_adapter, so that the conversion logic can take the plain name when it is separated from the node. The component plugin name changes accordingly; the executable name and the node name stay, and the launch files only reference the executable. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Kentaro NAGATOMO <kentaro.nagatomo@tier4.jp>
…he node class
radar_objects_adapter.{hpp,cpp} become radar_objects_adapter_node.{hpp,cpp},
so that the conversion logic can take the plain file name when it is
moved out of the node in the next step. Rename only; the include guard
follows the file name.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Kentaro NAGATOMO <kentaro.nagatomo@tier4.jp>
|
Thank you for contributing to the Autoware project! 🚧 If your pull request is in progress, switch it to draft mode. Please ensure:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #13470 +/- ##
==========================================
+ Coverage 37.56% 37.58% +0.02%
==========================================
Files 2025 2027 +2
Lines 141920 141968 +48
==========================================
+ Hits 53316 53364 +48
Misses 88604 88604
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
bdf88d5 to
87e269a
Compare
sasakisasaki
left a comment
There was a problem hiding this comment.
Reviewed. I approve this PR while put quick win comments 👍
| auto default_size_x = params_.default_size_x; | ||
| auto default_size_y = params_.default_size_y; | ||
| auto default_size_z = params_.default_size_z; | ||
| auto default_position_z = params_.default_position_z; | ||
| auto default_velocity_z = params_.default_velocity_z; | ||
| auto default_acceleration_z = params_.default_acceleration_z; |
There was a problem hiding this comment.
Perhaps we do not need to define these variables for simplicity. Because we can directly use this value as my proposal below.
There was a problem hiding this comment.
You are right that they are not needed. They are there so that the moved lines read as they did in the node (default_size_xz_ becomes default_size_x) and this commit stays a move. The function is replaced as a whole in the next refactoring step, which builds the tracked object first (kentdotn#15), and the locals disappear with it. I would like to leave them as they are in this PR.
| output_shape.dimensions.x = size_x_available_ ? input_object.size.x : default_size_x; | ||
| output_shape.dimensions.y = size_y_available_ ? input_object.size.y : default_size_y; | ||
| output_shape.dimensions.z = size_z_available_ ? input_object.size.z : default_size_z; |
There was a problem hiding this comment.
If my proposal is applied (same for other places):
| output_shape.dimensions.x = size_x_available_ ? input_object.size.x : default_size_x; | |
| output_shape.dimensions.y = size_y_available_ ? input_object.size.y : default_size_y; | |
| output_shape.dimensions.z = size_z_available_ ? input_object.size.z : default_size_z; | |
| output_shape.dimensions.x = size_x_available_ ? input_object.size.x : params_.default_size_x; | |
| output_shape.dimensions.y = size_y_available_ ? input_object.size.y : params_.default_size_y; | |
| output_shape.dimensions.z = size_z_available_ ? input_object.size.z : params_.default_size_z; |
87e269a to
60ecbcb
Compare
technolojin
left a comment
There was a problem hiding this comment.
I checked runtime and worked. LGTM
interimadd
left a comment
There was a problem hiding this comment.
Thank you for the PR!
I have left comments on the design of core logic functions. Could you take a look?
…m the node
The conversion of radar objects into detected and tracked objects moves
out of the node into RadarObjectsAdapter, a class without rclcpp, in
radar_objects_adapter.{hpp,cpp}. The node keeps the topics, the
parameters and the logging; it hands the adapter the parameter values,
the classification remap and the input topic name, feeds it the radar
info messages, and publishes what convert() returns.
The conversion code is the former node code with its members: the field
map, the validity and the *_available_ flags, the remap table and the
hash of the topic name keep their names and are read by the same
functions as before, now private members of the adapter. What is new is
the interface. update_radar_info() returns what the adapter decided from
a radar info: the optional fields it will fill from a parameter and the
value it will use, or, as the error of a tl::expected, the required
fields the message does not declare, so that the node logs the decision
without knowing which parameter stands in for which field. convert()
returns the messages to publish, or why the objects were dropped. The
errors derive from std::runtime_error and carry their text; the node
keeps the severity and the throttling. The remap built from the
parameter names comes back together with the entries that could not be
read, instead of through an output argument. No value is computed
differently. The acceleration covariance helper, which reads no member,
is declared static: cppcheck asks for it now that the class is not
derived from Node.
One log line changes: the missing required fields are listed in the
error itself, where the node printed them in a loop of
RCLCPP_ERROR_ONCE that only ever showed the first one.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Kentaro NAGATOMO <kentaro.nagatomo@tier4.jp>
60ecbcb to
9200205
Compare
interimadd
left a comment
There was a problem hiding this comment.
Thank you for addressing comments! LGTM
Description
Purpose
This PR separates the conversion logic of
radar_objects_adapterfrom its ROS node, so that the conversion can be unit-tested without ROS and later reused without the node. It is phase 3 of the plan used forTrafficLightMapVisualizerNode(#12487 → #12511 → #12553 → #12591 / #12596 → #12612): the characterization tests (#13405, #13445) and the preparation (#13465) come before it; the unit tests of the logic come after.Nothing the node publishes changes. The 25 characterization cases pass unchanged through every commit, and the moved code computes every value as it did.
What goes where
The node keeps everything that talks to ROS: the topics and their QoS, the parameters, the logging, the publishing.
RadarObjectsAdapter, inradar_objects_adapter.{hpp,cpp}and free of rclcpp, takes the rest:RadarObjectsAdapterParams), the classification remap as label ids (ClassificationRemap, a map keyed by the message's own label types) and the input topic name, whose hash goes into the tracked objects' UUIDs as before. The remap is built from the parameter names bymake_classification_remap_from_string_pair(), which returns it together with the entries it could not read as a name (ClassificationRemapParseResult); the node warns about those.update_radar_info()is fed every radar info message and returns what the adapter decided from it, as atl::expected: the configuration it will convert with (ConversionConfiguration, so far the optional fields it will fill from a parameter together with the value it will use), or the errorInvalidRadarInfo, astd::runtime_errorthat names the required fields the message does not declare. The node logs that decision; it no longer knows which parameter stands in for which field.convert()answers aRadarObjectsmessage with atl::expected: theDetectedObjectsandTrackedObjectsto publish (ConversionOutcome), or the errorMissingRadarInfo, astd::runtime_errorsaying that no valid radar info has arrived. Whether the gate is open is decided insideconvert(), because the conversion cannot run without a valid radar info; the node only decides how to log it (severity and throttling stay in the node).tl::expectedis what the perception packages use for their logic classes; here each function has its own error type, derived fromstd::runtime_errorso thatwhat()is the log text, and a second kind of error would turn that function's error type into astd::variantof the two.Inside the adapter, the former node members keep their names and their readers: the field map,
valid_radar_info_, the*_available_flags,topic_hash_code_,required_attributes_andclassification_remap_are read by the same covariance andpopulate_*functions as before, now private members of the adapter. The only change in the moved bodies is that the sixdefault_*_members become locals at the top ofpopulate_common_fields(), copied fromparams_(default_size_xfordefault_size_x_), and that the acceleration covariance helper, which reads no member, is declaredstatic: cppcheck asks for it (functionStatic) now that the class is not derived fromNode, which is what kept it quiet about the same function in the node.parse_as_detections/parse_as_tracksbecometo_detected_objects/to_tracked_objectsand return the message instead of publishing it.The commits
RadarObjectsAdapter→RadarObjectsAdapterNode, namespaceautoware→autoware::radar_objects_adapter, so that the logic can take the plain name. The consequence to decide on: the component plugin name becomesautoware::radar_objects_adapter::RadarObjectsAdapterNode. The launch files reference the executable, whose name does not change, and no launch file inautoware_launchor in TIER IV's launchers names the plugin.git mvof the two source files toradar_objects_adapter_node.{hpp,cpp}, include guard andCMakeLists.txtfollowing. Rename only.git show --color-moved=zebraon this commit tells the moved bodies from the new interface: the interface inradar_objects_adapter.hpp, the error type, the two result builders and the node's two callbacks are new; the rest ofradar_objects_adapter.cppis moved. One warning changes shape without changing what it prints: the sixRCLCPP_WARN_ONCEcall sites for a defaulted field become one loop over the adapter's list, with the node remembering which fields it has warned about, becauseRCLCPP_WARN_ONCEfires once per call site, not once per message. One error line changes what it prints: the missing required fields are listed in it (see "Effects on system behavior").Left alone on purpose
What the moved code shows and this PR does not touch, because none of it belongs to the separation. Each is a later PR under the unit tests:
populate_common_fields<T>template and the two loops over the objects.0.0assignments to theY_Zcovariance entry, which go when the covariances are built by value (the maintainers' answer: the z-related entries are to be set explicitly, all of them), and thefloatparameters.INVALIDandUNKNOWNmovement status read as stationary. Kept as it is until there is data to decide otherwise.Related links
Parent Issue:
None
Preparation this builds on: refactor(autoware_radar_objects_adapter): prepare the node for the logic separation #13465
The pattern for the return types:
tl::expectedas inautoware_traffic_light_pipeline,autoware_tensorrt_yoloxandautoware_euclidean_clusterHow was this PR tested?
From the CI-equivalent dev container (
ghcr.io/autowarefoundation/autoware:universe-dependencies-jazzy):colcon build --packages-select autoware_radar_objects_adapter \ --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo colcon test --packages-select autoware_radar_objects_adapter \ --event-handlers console_direct+grep -E 'rclcpp|agnocast|RCLCPP' src/radar_objects_adapter.{hpp,cpp}finds nothing.clang-format,cpplintand the rest of the repository'spre-commithooks pass, andcppcheckwith the CI's own settings reports nothing at every commit.Notes for reviewers
_ONCEbehavior is kept: once per field for the defaulted fields (now by a set in the node), once in total for the missing required fields, which are now all named in that one line: the loop ofRCLCPP_ERROR_ONCEit replaces only ever printed the first one, because_ONCEis per call site.Interface changes
The component plugin name changes from
autoware::RadarObjectsAdaptertoautoware::radar_objects_adapter::RadarObjectsAdapterNode. The executable name, the node name, the topics and the parameters do not change.Effects on system behavior
None on what is published. One log line changes: the error for an invalid radar info lists every missing required field in parentheses, where it used to print the first one on a separate line.
🤖 Generated with Claude Code