Skip to content

Commit 07bec40

Browse files
feat(tier4_autoware_utils, obstacle_cruise): change to read topic by polling (autowarefoundation#6702)
change to read topic by polling Signed-off-by: Yuki Takagi <yuki.takagi@tier4.jp>
1 parent eceefd7 commit 07bec40

File tree

3 files changed

+93
-32
lines changed

3 files changed

+93
-32
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2024 TIER IV, Inc.
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+
15+
#ifndef TIER4_AUTOWARE_UTILS__ROS__POLLING_SUBSCRIBER_HPP_
16+
#define TIER4_AUTOWARE_UTILS__ROS__POLLING_SUBSCRIBER_HPP_
17+
18+
#include <rclcpp/rclcpp.hpp>
19+
20+
#include <string>
21+
22+
namespace tier4_autoware_utils
23+
{
24+
25+
template <typename T>
26+
class InterProcessPollingSubscriber
27+
{
28+
private:
29+
typename rclcpp::Subscription<T>::SharedPtr subscriber_;
30+
std::optional<T> data_;
31+
32+
public:
33+
explicit InterProcessPollingSubscriber(rclcpp::Node * node, const std::string & topic_name)
34+
{
35+
auto noexec_callback_group =
36+
node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive, false);
37+
auto noexec_subscription_options = rclcpp::SubscriptionOptions();
38+
noexec_subscription_options.callback_group = noexec_callback_group;
39+
40+
subscriber_ = node->create_subscription<T>(
41+
topic_name, rclcpp::QoS{1}, [node](const typename T::ConstSharedPtr msg) { assert(false); },
42+
noexec_subscription_options);
43+
};
44+
bool updateLatestData()
45+
{
46+
rclcpp::MessageInfo message_info;
47+
T tmp;
48+
// The queue size (QoS) must be 1 to get the last message data.
49+
if (subscriber_->take(tmp, message_info)) {
50+
data_ = tmp;
51+
}
52+
return data_.has_value();
53+
};
54+
const T & getData() const
55+
{
56+
if (!data_.has_value()) {
57+
throw std::runtime_error("Bad_optional_access in class InterProcessPollingSubscriber");
58+
}
59+
return data_.value();
60+
};
61+
};
62+
63+
} // namespace tier4_autoware_utils
64+
65+
#endif // TIER4_AUTOWARE_UTILS__ROS__POLLING_SUBSCRIBER_HPP_

planning/obstacle_cruise_planner/include/obstacle_cruise_planner/node.hpp

+7-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "obstacle_cruise_planner/type_alias.hpp"
2222
#include "signal_processing/lowpass_filter_1d.hpp"
2323
#include "tier4_autoware_utils/ros/logger_level_configure.hpp"
24+
#include "tier4_autoware_utils/ros/polling_subscriber.hpp"
2425
#include "tier4_autoware_utils/system/stop_watch.hpp"
2526

2627
#include <rclcpp/rclcpp.hpp>
@@ -137,14 +138,12 @@ class ObstacleCruisePlannerNode : public rclcpp::Node
137138

138139
// subscriber
139140
rclcpp::Subscription<Trajectory>::SharedPtr traj_sub_;
140-
rclcpp::Subscription<PredictedObjects>::SharedPtr objects_sub_;
141-
rclcpp::Subscription<Odometry>::SharedPtr odom_sub_;
142-
rclcpp::Subscription<AccelWithCovarianceStamped>::SharedPtr acc_sub_;
143-
144-
// data for callback functions
145-
PredictedObjects::ConstSharedPtr objects_ptr_{nullptr};
146-
Odometry::ConstSharedPtr ego_odom_ptr_{nullptr};
147-
AccelWithCovarianceStamped::ConstSharedPtr ego_accel_ptr_{nullptr};
141+
tier4_autoware_utils::InterProcessPollingSubscriber<Odometry> ego_odom_sub_{
142+
this, "~/input/odometry"};
143+
tier4_autoware_utils::InterProcessPollingSubscriber<PredictedObjects> objects_sub_{
144+
this, "~/input/objects"};
145+
tier4_autoware_utils::InterProcessPollingSubscriber<AccelWithCovarianceStamped> acc_sub_{
146+
this, "~/input/acceleration"};
148147

149148
// Vehicle Parameters
150149
VehicleInfo vehicle_info_;

planning/obstacle_cruise_planner/src/node.cpp

+21-24
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,6 @@ ObstacleCruisePlannerNode::ObstacleCruisePlannerNode(const rclcpp::NodeOptions &
357357
traj_sub_ = create_subscription<Trajectory>(
358358
"~/input/trajectory", rclcpp::QoS{1},
359359
std::bind(&ObstacleCruisePlannerNode::onTrajectory, this, _1));
360-
objects_sub_ = create_subscription<PredictedObjects>(
361-
"~/input/objects", rclcpp::QoS{1},
362-
[this](const PredictedObjects::ConstSharedPtr msg) { objects_ptr_ = msg; });
363-
odom_sub_ = create_subscription<Odometry>(
364-
"~/input/odometry", rclcpp::QoS{1},
365-
[this](const Odometry::ConstSharedPtr msg) { ego_odom_ptr_ = msg; });
366-
acc_sub_ = create_subscription<AccelWithCovarianceStamped>(
367-
"~/input/acceleration", rclcpp::QoS{1},
368-
[this](const AccelWithCovarianceStamped::ConstSharedPtr msg) { ego_accel_ptr_ = msg; });
369360

370361
// publisher
371362
trajectory_pub_ = create_publisher<Trajectory>("~/output/trajectory", 1);
@@ -492,10 +483,15 @@ rcl_interfaces::msg::SetParametersResult ObstacleCruisePlannerNode::onParam(
492483

493484
void ObstacleCruisePlannerNode::onTrajectory(const Trajectory::ConstSharedPtr msg)
494485
{
495-
const auto traj_points = motion_utils::convertToTrajectoryPointArray(*msg);
486+
if (
487+
!ego_odom_sub_.updateLatestData() || !objects_sub_.updateLatestData() ||
488+
!acc_sub_.updateLatestData()) {
489+
return;
490+
}
496491

492+
const auto traj_points = motion_utils::convertToTrajectoryPointArray(*msg);
497493
// check if subscribed variables are ready
498-
if (traj_points.empty() || !ego_odom_ptr_ || !ego_accel_ptr_ || !objects_ptr_) {
494+
if (traj_points.empty()) {
499495
return;
500496
}
501497

@@ -607,11 +603,11 @@ std::vector<Obstacle> ObstacleCruisePlannerNode::convertToObstacles(
607603
{
608604
stop_watch_.tic(__func__);
609605

610-
const auto obj_stamp = rclcpp::Time(objects_ptr_->header.stamp);
606+
const auto obj_stamp = rclcpp::Time(objects_sub_.getData().header.stamp);
611607
const auto & p = behavior_determination_param_;
612608

613609
std::vector<Obstacle> target_obstacles;
614-
for (const auto & predicted_object : objects_ptr_->objects) {
610+
for (const auto & predicted_object : objects_sub_.getData().objects) {
615611
const auto & object_id =
616612
tier4_autoware_utils::toHexString(predicted_object.object_id).substr(0, 4);
617613
const auto & current_obstacle_pose =
@@ -629,7 +625,8 @@ std::vector<Obstacle> ObstacleCruisePlannerNode::convertToObstacles(
629625
}
630626

631627
// 2. Check if the obstacle is in front of the ego.
632-
const size_t ego_idx = ego_nearest_param_.findIndex(traj_points, ego_odom_ptr_->pose.pose);
628+
const size_t ego_idx =
629+
ego_nearest_param_.findIndex(traj_points, ego_odom_sub_.getData().pose.pose);
633630
const auto ego_to_obstacle_distance =
634631
calcDistanceToFrontVehicle(traj_points, ego_idx, current_obstacle_pose.pose.position);
635632
if (!ego_to_obstacle_distance) {
@@ -725,7 +722,7 @@ ObstacleCruisePlannerNode::determineEgoBehaviorAgainstObstacles(
725722
// calculated decimated trajectory points and trajectory polygon
726723
const auto decimated_traj_points = decimateTrajectoryPoints(traj_points);
727724
const auto decimated_traj_polys =
728-
createOneStepPolygons(decimated_traj_points, vehicle_info_, ego_odom_ptr_->pose.pose);
725+
createOneStepPolygons(decimated_traj_points, vehicle_info_, ego_odom_sub_.getData().pose.pose);
729726
debug_data_ptr_->detection_polygons = decimated_traj_polys;
730727

731728
// determine ego's behavior from stop, cruise and slow down
@@ -783,7 +780,7 @@ ObstacleCruisePlannerNode::determineEgoBehaviorAgainstObstacles(
783780
slow_down_condition_counter_.removeCounterUnlessUpdated();
784781

785782
// Check target obstacles' consistency
786-
checkConsistency(objects_ptr_->header.stamp, *objects_ptr_, stop_obstacles);
783+
checkConsistency(objects_sub_.getData().header.stamp, objects_sub_.getData(), stop_obstacles);
787784

788785
// update previous obstacles
789786
prev_stop_obstacles_ = stop_obstacles;
@@ -805,7 +802,7 @@ std::vector<TrajectoryPoint> ObstacleCruisePlannerNode::decimateTrajectoryPoints
805802

806803
// trim trajectory
807804
const size_t ego_seg_idx =
808-
ego_nearest_param_.findSegmentIndex(traj_points, ego_odom_ptr_->pose.pose);
805+
ego_nearest_param_.findSegmentIndex(traj_points, ego_odom_sub_.getData().pose.pose);
809806
const size_t traj_start_point_idx = ego_seg_idx;
810807
const auto trimmed_traj_points =
811808
std::vector<TrajectoryPoint>(traj_points.begin() + traj_start_point_idx, traj_points.end());
@@ -1189,7 +1186,7 @@ std::optional<StopObstacle> ObstacleCruisePlannerNode::createStopObstacle(
11891186

11901187
// calculate collision points with trajectory with lateral stop margin
11911188
const auto traj_polys_with_lat_margin = createOneStepPolygons(
1192-
traj_points, vehicle_info_, ego_odom_ptr_->pose.pose, p.max_lat_margin_for_stop);
1189+
traj_points, vehicle_info_, ego_odom_sub_.getData().pose.pose, p.max_lat_margin_for_stop);
11931190

11941191
const auto collision_point = polygon_utils::getCollisionPoint(
11951192
traj_points, traj_polys_with_lat_margin, obstacle, is_driving_forward_, vehicle_info_);
@@ -1259,7 +1256,7 @@ std::optional<SlowDownObstacle> ObstacleCruisePlannerNode::createSlowDownObstacl
12591256
// calculate collision points with trajectory with lateral stop margin
12601257
// NOTE: For additional margin, hysteresis is not divided by two.
12611258
const auto traj_polys_with_lat_margin = createOneStepPolygons(
1262-
traj_points, vehicle_info_, ego_odom_ptr_->pose.pose,
1259+
traj_points, vehicle_info_, ego_odom_sub_.getData().pose.pose,
12631260
p.max_lat_margin_for_slow_down + p.lat_hysteresis_margin_for_slow_down);
12641261

12651262
std::vector<Polygon2d> front_collision_polygons;
@@ -1422,8 +1419,8 @@ double ObstacleCruisePlannerNode::calcCollisionTimeMargin(
14221419
const std::vector<PointWithStamp> & collision_points,
14231420
const std::vector<TrajectoryPoint> & traj_points, const bool is_driving_forward) const
14241421
{
1425-
const auto & ego_pose = ego_odom_ptr_->pose.pose;
1426-
const double ego_vel = ego_odom_ptr_->twist.twist.linear.x;
1422+
const auto & ego_pose = ego_odom_sub_.getData().pose.pose;
1423+
const double ego_vel = ego_odom_sub_.getData().twist.twist.linear.x;
14271424

14281425
const double time_to_reach_collision_point = [&]() {
14291426
const double abs_ego_offset = is_driving_forward
@@ -1455,9 +1452,9 @@ PlannerData ObstacleCruisePlannerNode::createPlannerData(
14551452
PlannerData planner_data;
14561453
planner_data.current_time = now();
14571454
planner_data.traj_points = traj_points;
1458-
planner_data.ego_pose = ego_odom_ptr_->pose.pose;
1459-
planner_data.ego_vel = ego_odom_ptr_->twist.twist.linear.x;
1460-
planner_data.ego_acc = ego_accel_ptr_->accel.accel.linear.x;
1455+
planner_data.ego_pose = ego_odom_sub_.getData().pose.pose;
1456+
planner_data.ego_vel = ego_odom_sub_.getData().twist.twist.linear.x;
1457+
planner_data.ego_acc = acc_sub_.getData().accel.accel.linear.x;
14611458
planner_data.is_driving_forward = is_driving_forward_;
14621459
return planner_data;
14631460
}

0 commit comments

Comments
 (0)