Skip to content

Commit a3e718d

Browse files
kentdotnclaude
andauthored
refactor(autoware_radar_objects_adapter): align the README and the default_* parameters with what the node does (#13538)
* docs(autoware_radar_objects_adapter): document what the node expects of its input The README now says what the conversion assumes rather than leaving it to the code: positions and their covariances are taken in the header frame and published as they are, velocities and accelerations are absolute and rotated into the object's frame, the absolute_dynamics flag is not checked, and which object fields are required and which fall back to the default_* parameters. The classification_remap section states that the probabilities are treated as independent confidences and are not merged when two labels map to the same one, in place of the note that only observed the duplicates. None of this changes with the refactoring under way; it is what the node has done since the characterization tests pinned it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Kentaro NAGATOMO <kentaro.nagatomo@tier4.jp> * refactor(autoware_radar_objects_adapter): read the default_* parameters as double The six default_* parameters were declared as float and stored as float in RadarObjectsAdapterParams, although rclcpp parameters are double and every field they end up in (a position, a twist, a shape dimension) is double. They are now double end to end, and so is the value update_radar_info() reports for a defaulted field. The test parameters lose their casts. Values that a float represents exactly, such as the shipped configuration (0.0, 5.0, 2.0), come out the same; any other value changes the output at the 1e-8 level. The existing cases use only exactly representable values and so could not tell the two apart; two new cases use values a float cannot represent (0.1, 4.1, ...) and check that they reach the output as written, one through the adapter (every defaulted field) and one through the node and its parameter declaration. Both fail on the float code. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Kentaro NAGATOMO <kentaro.nagatomo@tier4.jp> --------- Signed-off-by: Kentaro NAGATOMO <kentaro.nagatomo@tier4.jp> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
1 parent ed710a0 commit a3e718d

6 files changed

Lines changed: 90 additions & 29 deletions

File tree

‎sensing/autoware_radar_objects_adapter/README.md‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,22 @@ This package converts `autoware_sensing_msgs::msg::RadarObjects` into `autoware_
88

99
A node that converts radar objects from the sensing definition into a perception friendly format with no filtering involved.
1010

11+
### What the input is expected to be
12+
13+
The node converts the message format; it does not transform coordinates, compensate the ego motion, or synchronize anything. It therefore expects the radar driver to publish `RadarObjects` in the form the perception pipeline uses:
14+
15+
- Positions, orientations, sizes and their covariances are expressed in the frame named in `header.frame_id`, which is the frame the output objects are published in (typically `base_link`).
16+
- Velocities and accelerations are absolute (ground-relative) and expressed in that same frame, as the driver reports them; the node rotates them by the object's orientation so that the output twist and acceleration are expressed in the object's own frame, as Autoware's object messages require. The `absolute_dynamics` flag of `RadarInfo` is not checked.
17+
- The `RadarInfo` message declares the object fields the radar provides. The following fields are required, and objects are dropped until a `RadarInfo` that declares all of them has arrived: `existence_probability`, `position_x`, `position_y`, `velocity_x`, `velocity_y`, `acceleration_x`, `acceleration_y`, `orientation`.
18+
- Fields the `RadarInfo` does not declare are filled from the `default_*` parameters: `position_z`, `velocity_z`, `acceleration_z`, `size_x`, `size_y`, `size_z`. The yaw variances of the pose and the twist are set only when `orientation_std` and `orientation_rate_std` are declared.
19+
1120
### Parameter: classification_remap
1221

1322
This parameter allows remapping of classification labels from `autoware_sensing_msgs::msg::RadarClassification` to `autoware_perception_msgs::msg::ObjectClassification`. It should be provided as a flat list of strings, where each pair of strings represents an input label and the corresponding output label.
1423

1524
For example, the current default configuration remaps `MOTORCYCLE` and `BICYCLE` from radar classification to `CAR` in the perception classification, while keeping other labels unchanged.
1625

17-
**Note**: If multiple radar labels are remapped to the same perception label, multiple probabilities may appear for that label.
18-
This does not violate any logic in Autoware but may be worth monitoring.
26+
The `probability` of each radar classification is treated as an independent confidence for that label, not as a share of a distribution, and is copied as it is. Consequently, if multiple radar labels are remapped to the same perception label, multiple entries with that label and their own probabilities appear in the output; the probabilities are not merged. This does not violate any logic in Autoware but may be worth monitoring.
1927

2028
### Inputs / Outputs
2129

‎sensing/autoware_radar_objects_adapter/src/radar_objects_adapter.cpp‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,13 @@ std::string join(const std::vector<std::string> & words)
8585

8686
} // namespace
8787

88-
void ConversionConfiguration::add_field(std::string name, float default_value)
88+
void ConversionConfiguration::add_field(std::string name, double default_value)
8989
{
9090
default_fields_.push_back({std::move(name), default_value});
9191
}
9292

93-
const std::vector<std::pair<std::string, float>> & ConversionConfiguration::defaulted_fields() const
93+
const std::vector<std::pair<std::string, double>> & ConversionConfiguration::defaulted_fields()
94+
const
9495
{
9596
return default_fields_;
9697
}

‎sensing/autoware_radar_objects_adapter/src/radar_objects_adapter.hpp‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ class InvalidRadarInfo : public std::runtime_error
7979
class ConversionConfiguration
8080
{
8181
public:
82-
void add_field(std::string name, float default_value);
82+
void add_field(std::string name, double default_value);
8383

8484
// The defaulted fields, in the order they were added.
85-
const std::vector<std::pair<std::string, float>> & defaulted_fields() const;
85+
const std::vector<std::pair<std::string, double>> & defaulted_fields() const;
8686

8787
private:
88-
std::vector<std::pair<std::string, float>> default_fields_;
88+
std::vector<std::pair<std::string, double>> default_fields_;
8989
};
9090

9191
// What a radar objects message converts into: the messages to publish.
@@ -106,12 +106,12 @@ class MissingRadarInfo : public std::runtime_error
106106
// The values used for the object fields a radar does not provide.
107107
struct RadarObjectsAdapterParams
108108
{
109-
float default_position_z{0.0f};
110-
float default_velocity_z{0.0f};
111-
float default_acceleration_z{0.0f};
112-
float default_size_x{0.0f};
113-
float default_size_y{0.0f};
114-
float default_size_z{0.0f};
109+
double default_position_z{0.0};
110+
double default_velocity_z{0.0};
111+
double default_acceleration_z{0.0};
112+
double default_size_x{0.0};
113+
double default_size_y{0.0};
114+
double default_size_z{0.0};
115115
};
116116

117117
// Converts radar objects into detected objects and into tracked objects. Learns which fields the

‎sensing/autoware_radar_objects_adapter/src/radar_objects_adapter_node.cpp‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ RadarObjectsAdapterNode::RadarObjectsAdapterNode(const rclcpp::NodeOptions & opt
4141

4242
RadarObjectsAdapterParams params;
4343

44-
params.default_position_z = this->declare_parameter<float>("default_position_z");
45-
params.default_velocity_z = this->declare_parameter<float>("default_velocity_z");
46-
params.default_acceleration_z = this->declare_parameter<float>("default_acceleration_z");
44+
params.default_position_z = this->declare_parameter<double>("default_position_z");
45+
params.default_velocity_z = this->declare_parameter<double>("default_velocity_z");
46+
params.default_acceleration_z = this->declare_parameter<double>("default_acceleration_z");
4747

48-
params.default_size_x = this->declare_parameter<float>("default_size_x");
49-
params.default_size_y = this->declare_parameter<float>("default_size_y");
50-
params.default_size_z = this->declare_parameter<float>("default_size_z");
48+
params.default_size_x = this->declare_parameter<double>("default_size_x");
49+
params.default_size_y = this->declare_parameter<double>("default_size_y");
50+
params.default_size_z = this->declare_parameter<double>("default_size_z");
5151

5252
// The tracks of this radar are told from those of another by the hash of the input topic name.
5353
const std::string topic_name = radar_objects_sub_->get_topic_name();

‎sensing/autoware_radar_objects_adapter/test/test_radar_objects_adapter.cpp‎

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,23 +89,23 @@ struct DefaultParameters
8989
[[nodiscard]] RadarObjectsAdapterParams to_params() const
9090
{
9191
RadarObjectsAdapterParams params;
92-
params.default_position_z = static_cast<float>(position_z);
93-
params.default_velocity_z = static_cast<float>(velocity_z);
94-
params.default_acceleration_z = static_cast<float>(acceleration_z);
95-
params.default_size_x = static_cast<float>(size_x);
96-
params.default_size_y = static_cast<float>(size_y);
97-
params.default_size_z = static_cast<float>(size_z);
92+
params.default_position_z = position_z;
93+
params.default_velocity_z = velocity_z;
94+
params.default_acceleration_z = acceleration_z;
95+
params.default_size_x = size_x;
96+
params.default_size_y = size_y;
97+
params.default_size_z = size_z;
9898
return params;
9999
}
100100
};
101101

102102
// The six optional fields that have a parameter, with the value DefaultParameters gives each, in
103103
// the order update_radar_info() reports them. orientation_std and orientation_rate_std have no
104104
// parameter and are never reported.
105-
using DefaultedField = std::pair<std::string, float>;
106-
const std::vector<DefaultedField> all_defaulted = {{"position_z", 0.25f}, {"velocity_z", 0.5f},
107-
{"acceleration_z", 0.75f}, {"size_x", 5.0f},
108-
{"size_y", 2.0f}, {"size_z", 1.5f}};
105+
using DefaultedField = std::pair<std::string, double>;
106+
const std::vector<DefaultedField> all_defaulted = {{"position_z", 0.25}, {"velocity_z", 0.5},
107+
{"acceleration_z", 0.75}, {"size_x", 5.0},
108+
{"size_y", 2.0}, {"size_z", 1.5}};
109109

110110
std::vector<DefaultedField> all_defaulted_except(const std::string & declared)
111111
{
@@ -731,6 +731,37 @@ TEST(RadarObjectsAdapter, Detections_OptionalFields_ChoiceMadePerField)
731731
}
732732
}
733733

734+
// The parameters above are values a float represents exactly, so they cannot tell a parameter
735+
// that was rounded to float on the way from one that was not. These cannot be represented as
736+
// float: each must reach the output as written, on whichever output carries it.
737+
TEST(RadarObjectsAdapter, Detections_UndeclaredFields_ParameterNotRoundedToFloat)
738+
{
739+
// Arrange
740+
DefaultParameters defaults;
741+
defaults.position_z = 0.1;
742+
defaults.velocity_z = 0.2;
743+
defaults.acceleration_z = 0.3;
744+
defaults.size_x = 4.1;
745+
defaults.size_y = 1.9;
746+
defaults.size_z = 1.7;
747+
const RadarInfo info = make_radar_info(required_fields);
748+
const RadarObject radar = make_radar_object();
749+
750+
// Act
751+
const auto outputs = run_adapter_and_collect_outputs(info, {radar}, defaults.to_params());
752+
ASSERT_TRUE(outputs.has_value());
753+
754+
// Assert: the parameter's value as written, not its nearest float
755+
const DetectedObject & detected = outputs->detections.objects.at(0);
756+
const TrackedObject & tracked = outputs->tracks.objects.at(0);
757+
EXPECT_DOUBLE_EQ(detected.kinematics.pose_with_covariance.pose.position.z, 0.1);
758+
EXPECT_DOUBLE_EQ(detected.kinematics.twist_with_covariance.twist.linear.z, 0.2);
759+
EXPECT_DOUBLE_EQ(tracked.kinematics.acceleration_with_covariance.accel.linear.z, 0.3);
760+
EXPECT_DOUBLE_EQ(detected.shape.dimensions.x, 4.1);
761+
EXPECT_DOUBLE_EQ(detected.shape.dimensions.y, 1.9);
762+
EXPECT_DOUBLE_EQ(detected.shape.dimensions.z, 1.7);
763+
}
764+
734765
// The radar's yaw angle becomes the orientation quaternion: a rotation about z alone.
735766
TEST(RadarObjectsAdapter, Detections_Orientation_QuaternionFromYaw)
736767
{

‎sensing/autoware_radar_objects_adapter/test/test_radar_objects_adapter_node.cpp‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,27 @@ TEST_F(RadarObjectsAdapterNodeTest, Construct_RemapParametersOmitted_Constructs)
384384
EXPECT_NO_THROW(std::make_shared<RadarObjectsAdapterNode>(options));
385385
}
386386

387+
// A default_* value that a float cannot represent exactly reaches the output as written: the
388+
// parameter is read as the double it is declared as, not through a float.
389+
TEST_F(RadarObjectsAdapterNodeTest, Construct_DefaultParameterNotRepresentableAsFloat_ReachesOutput)
390+
{
391+
// Arrange: no optional field declared, so every default_* parameter is used
392+
DefaultParameters defaults;
393+
defaults.position_z = 0.1;
394+
defaults.size_x = 4.1;
395+
const RadarInfo info = make_radar_info(required_fields);
396+
397+
// Act
398+
const auto outputs =
399+
run_node_and_collect_outputs(info, {make_radar_object()}, defaults.to_options());
400+
ASSERT_TRUE(outputs.has_value());
401+
402+
// Assert
403+
const auto & detected = outputs->detections.objects.at(0);
404+
EXPECT_DOUBLE_EQ(detected.kinematics.pose_with_covariance.pose.position.z, 0.1);
405+
EXPECT_DOUBLE_EQ(detected.shape.dimensions.x, 4.1);
406+
}
407+
387408
// ---------------------------------------------------------------------------------------------
388409
// The radar info gate. Radar objects are converted only after a radar info message has declared
389410
// all of the fields the node requires; until then every radar objects message is dropped with a

0 commit comments

Comments
 (0)