Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
host_vehicle_filter_component.cpp
Go to the documentation of this file.
1// Copyright 2023 Leidos
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
16
17#include <carma_cooperative_perception_interfaces/msg/detection.hpp>
18#include <carma_ros2_utils/carma_lifecycle_node.hpp>
19#include <rclcpp_components/register_node_macro.hpp>
20
21#include <vector>
22
24{
26 const rclcpp_lifecycle::State & /* previous_state */) -> carma_ros2_utils::CallbackReturn
27{
28 RCLCPP_INFO(get_logger(), "Lifecycle transition: configuring");
29
30 detection_list_sub_ = create_subscription<
31 carma_cooperative_perception_interfaces::msg::DetectionList>(
32 "input/detection_list", 1,
33 [this](const carma_cooperative_perception_interfaces::msg::DetectionList::SharedPtr msg_ptr) {
34 if (const auto current_state{this->get_current_state().label()}; current_state == "active") {
35 attempt_filter_and_republish(*msg_ptr);
36 } else {
37 RCLCPP_WARN(
38 this->get_logger(),
39 "Trying to receive message on the topic '%s', but the containing node is not activated. "
40 "Current node state: '%s'",
41 this->detection_list_sub_->get_topic_name(), current_state.c_str());
42 }
43 });
44
45 host_vehicle_pose_sub_ = create_subscription<geometry_msgs::msg::PoseStamped>(
46 "input/host_vehicle_pose", 1, [this](const geometry_msgs::msg::PoseStamped::SharedPtr msg_ptr) {
47 if (const auto current_state{this->get_current_state().label()}; current_state == "active") {
48 update_host_vehicle_pose(*msg_ptr);
49 } else {
50 RCLCPP_WARN(
51 this->get_logger(),
52 "Trying to receive message on the topic '%s', but the containing node is not activated. "
53 "Current node state: '%s'",
54 this->detection_list_sub_->get_topic_name(), current_state.c_str());
55 }
56 });
57
58 detection_list_pub_ =
59 create_publisher<carma_cooperative_perception_interfaces::msg::DetectionList>(
60 "output/detection_list", 1);
61
62 RCLCPP_INFO(get_logger(), "Lifecycle transition: successfully configured");
63
64 on_set_parameters_callback_ =
65 add_on_set_parameters_callback([this](const std::vector<rclcpp::Parameter> & parameters) {
66 rcl_interfaces::msg::SetParametersResult result;
67 result.successful = true;
68 result.reason = "success";
69
70 for (const auto & parameter : parameters) {
71 if (parameter.get_name() == "distance_threshold_meters") {
72 if (this->get_current_state().label() == "active") {
73 result.successful = false;
74 result.reason = "parameter is read-only while node is in 'Active' state";
75
76 RCLCPP_ERROR(
77 get_logger(),
78 "Cannot change parameter 'distance_threshold_meters': " + result.reason);
79
80 break;
81 }
82
83 if (const auto value{parameter.as_double()}; value < 0) {
84 result.successful = false;
85 result.reason = "parameter must be nonnegative";
86
87 RCLCPP_ERROR(
88 get_logger(),
89 "Cannot change parameter 'distance_threshold_meters': " + result.reason);
90
91 break;
92 } else {
93 this->squared_distance_threshold_meters_ = std::pow(value, 2);
94 }
95 } else {
96 result.successful = false;
97 result.reason = "Unexpected parameter name '" + parameter.get_name() + '\'';
98 break;
99 }
100 }
101
102 return result;
103 });
104
105 declare_parameter("distance_threshold_meters", 0.0);
106
107 return carma_ros2_utils::CallbackReturn::SUCCESS;
108}
109
110auto HostVehicleFilterNode::handle_on_activate(const rclcpp_lifecycle::State & /* previous_state */)
111 -> carma_ros2_utils::CallbackReturn
112{
113 RCLCPP_INFO(get_logger(), "Lifecycle transition: activating");
114 RCLCPP_INFO(get_logger(), "Lifecycle transition: successfully activated");
115
116 return carma_ros2_utils::CallbackReturn::SUCCESS;
117}
118
119auto HostVehicleFilterNode::handle_on_deactivate(
120 const rclcpp_lifecycle::State & /* previous_state */) -> carma_ros2_utils::CallbackReturn
121{
122 RCLCPP_INFO(get_logger(), "Lifecycle transition: deactivating");
123 RCLCPP_INFO(get_logger(), "Lifecycle transition: successfully deactivated");
124
125 return carma_ros2_utils::CallbackReturn::SUCCESS;
126}
127
128auto HostVehicleFilterNode::handle_on_cleanup(const rclcpp_lifecycle::State & /* previous_state */)
129 -> carma_ros2_utils::CallbackReturn
130{
131 RCLCPP_INFO(get_logger(), "Lifecycle transition: cleaning up");
132
133 // CarmaLifecycleNode does not handle subscriber pointer reseting for us
134 detection_list_sub_.reset();
135 host_vehicle_pose_sub_.reset();
136
137 RCLCPP_INFO(get_logger(), "Lifecycle transition: successfully cleaned up");
138
139 return carma_ros2_utils::CallbackReturn::SUCCESS;
140}
141
142auto HostVehicleFilterNode::handle_on_shutdown(const rclcpp_lifecycle::State & /* previous_state */)
143 -> carma_ros2_utils::CallbackReturn
144{
145 RCLCPP_INFO(get_logger(), "Lifecycle transition: shutting down");
146
147 // CarmaLifecycleNode does not handle subscriber pointer reseting for us
148 detection_list_sub_.reset();
149 host_vehicle_pose_sub_.reset();
150
151 RCLCPP_INFO(get_logger(), "Lifecycle transition: successfully shut down");
152
153 return carma_ros2_utils::CallbackReturn::SUCCESS;
154}
155
156auto HostVehicleFilterNode::update_host_vehicle_pose(const geometry_msgs::msg::PoseStamped & msg)
157 -> void
158{
159 host_vehicle_pose_ = msg;
160}
161
162auto HostVehicleFilterNode::attempt_filter_and_republish(
163 carma_cooperative_perception_interfaces::msg::DetectionList msg) -> void
164{
165 if (!host_vehicle_pose_.has_value()) {
166 RCLCPP_WARN(get_logger(), "Could not filter detection list: host vehicle pose unknown");
167 return;
168 }
169
170 const auto is_within_distance = [this](const auto & detection) {
171 if (
172 detection.semantic_class != detection.SEMANTIC_CLASS_UNKNOWN &&
173 detection.semantic_class != detection.SEMANTIC_CLASS_SMALL_VEHICLE) {
174 return false;
175 }
176
177 return euclidean_distance_squared(host_vehicle_pose_.value().pose, detection.pose.pose) <=
178 this->squared_distance_threshold_meters_;
179 };
180
181 const auto new_end{
182 std::remove_if(std::begin(msg.detections), std::end(msg.detections), is_within_distance)};
183
184 msg.detections.erase(new_end, std::end(msg.detections));
185
186 this->detection_list_pub_->publish(msg);
187}
188
190 const geometry_msgs::msg::Pose & a, const geometry_msgs::msg::Pose & b) -> double
191{
192 return std::pow(a.position.x - b.position.x, 2) + std::pow(a.position.y - b.position.y, 2) +
193 std::pow(a.position.z - b.position.z, 2);
194}
195
196} // namespace carma_cooperative_perception
197
198// This is not our macro, so we should not worry about linting it.
199// clang-tidy added support for ignoring system macros in release 14.0.0 (see the release notes
200// here: https://releases.llvm.org/14.0.0/tools/clang/tools/extra/docs/ReleaseNotes.html), but
201// ament_clang_tidy for ROS 2 Foxy specifically looks for clang-tidy-6.0.
202RCLCPP_COMPONENTS_REGISTER_NODE( // NOLINT
auto handle_on_configure(const rclcpp_lifecycle::State &) -> carma_ros2_utils::CallbackReturn override
auto euclidean_distance_squared(const geometry_msgs::msg::Pose &a, const geometry_msgs::msg::Pose &b) -> double