Skip to content

Commit 8ba925c

Browse files
authored
Fix SmacPlanner memory leaks and costmap downsampler test (#2050)
* Fix shared_ptr cyclic dependencies Signed-off-by: Sarthak Mittal <[email protected]> * Refactor costmap downsampler and fix test Signed-off-by: Sarthak Mittal <[email protected]> * Revert costmap downsampler test changes Signed-off-by: Sarthak Mittal <[email protected]>
1 parent 884d144 commit 8ba925c

7 files changed

Lines changed: 143 additions & 127 deletions

File tree

smac_planner/include/smac_planner/costmap_downsampler.hpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,24 @@ class CostmapDownsampler
3434
public:
3535
/**
3636
* @brief A constructor for CostmapDownsampler
37-
* @param node Lifecycle node pointer
3837
*/
39-
explicit CostmapDownsampler(const nav2_util::LifecycleNode::SharedPtr & node);
38+
CostmapDownsampler();
4039

4140
/**
4241
* @brief A destructor for CostmapDownsampler
4342
*/
4443
~CostmapDownsampler();
4544

4645
/**
47-
* @brief Initialize the downsampled costmap object and the ROS publisher
46+
* @brief Configure the downsampled costmap object and the ROS publisher
47+
* @param node Lifecycle node pointer
4848
* @param global_frame The ID of the global frame used by the costmap
4949
* @param topic_name The name of the topic to publish the downsampled costmap
5050
* @param costmap The costmap we want to downsample
5151
* @param downsampling_factor Multiplier for the costmap resolution
5252
*/
53-
void initialize(
53+
void on_configure(
54+
const nav2_util::LifecycleNode::WeakPtr & node,
5455
const std::string & global_frame,
5556
const std::string & topic_name,
5657
nav2_costmap_2d::Costmap2D * const costmap,
@@ -59,18 +60,17 @@ class CostmapDownsampler
5960
/**
6061
* @brief Activate the publisher of the downsampled costmap
6162
*/
62-
void activatePublisher()
63-
{
64-
_downsampled_costmap_pub->on_activate();
65-
}
63+
void on_activate();
6664

6765
/**
6866
* @brief Deactivate the publisher of the downsampled costmap
6967
*/
70-
void deactivatePublisher()
71-
{
72-
_downsampled_costmap_pub->on_deactivate();
73-
}
68+
void on_deactivate();
69+
70+
/**
71+
* @brief Cleanup the publisher of the downsampled costmap
72+
*/
73+
void on_cleanup();
7474

7575
/**
7676
* @brief Downsample the given costmap by the downsampling factor, and publish the downsampled costmap
@@ -105,8 +105,6 @@ class CostmapDownsampler
105105
unsigned int _downsampled_size_y;
106106
unsigned int _downsampling_factor;
107107
float _downsampled_resolution;
108-
std::string _topic_name;
109-
nav2_util::LifecycleNode::SharedPtr _node;
110108
nav2_costmap_2d::Costmap2D * _costmap;
111109
std::unique_ptr<nav2_costmap_2d::Costmap2D> _downsampled_costmap;
112110
std::unique_ptr<nav2_costmap_2d::Costmap2DPublisher> _downsampled_costmap_pub;

smac_planner/include/smac_planner/smac_planner.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ class SmacPlanner : public nav2_core::GlobalPlanner
111111
protected:
112112
std::unique_ptr<AStarAlgorithm<NodeSE2>> _a_star;
113113
std::unique_ptr<Smoother> _smoother;
114-
nav2_util::LifecycleNode::SharedPtr _node;
114+
rclcpp::Clock::SharedPtr _clock;
115+
rclcpp::Logger _logger{rclcpp::get_logger("SmacPlanner")};
115116
nav2_costmap_2d::Costmap2D * _costmap;
116117
std::unique_ptr<CostmapDownsampler> _costmap_downsampler;
117118
std::string _global_frame, _name;

smac_planner/include/smac_planner/smac_planner_2d.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ class SmacPlanner2D : public nav2_core::GlobalPlanner
106106
std::unique_ptr<Smoother> _smoother;
107107
nav2_costmap_2d::Costmap2D * _costmap;
108108
std::unique_ptr<CostmapDownsampler> _costmap_downsampler;
109-
nav2_util::LifecycleNode::SharedPtr _node;
109+
rclcpp::Clock::SharedPtr _clock;
110+
rclcpp::Logger _logger{rclcpp::get_logger("SmacPlanner2D")};
110111
std::string _global_frame, _name;
111112
float _tolerance;
112113
int _downsampling_factor;

smac_planner/src/costmap_downsampler.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@
2222
namespace smac_planner
2323
{
2424

25-
CostmapDownsampler::CostmapDownsampler(const nav2_util::LifecycleNode::SharedPtr & node)
26-
: _node(node),
27-
_costmap(nullptr),
25+
CostmapDownsampler::CostmapDownsampler()
26+
: _costmap(nullptr),
2827
_downsampled_costmap(nullptr),
2928
_downsampled_costmap_pub(nullptr)
3029
{
@@ -34,13 +33,13 @@ CostmapDownsampler::~CostmapDownsampler()
3433
{
3534
}
3635

37-
void CostmapDownsampler::initialize(
36+
void CostmapDownsampler::on_configure(
37+
const nav2_util::LifecycleNode::WeakPtr & node,
3838
const std::string & global_frame,
3939
const std::string & topic_name,
4040
nav2_costmap_2d::Costmap2D * const costmap,
4141
const unsigned int & downsampling_factor)
4242
{
43-
_topic_name = topic_name;
4443
_costmap = costmap;
4544
_downsampling_factor = downsampling_factor;
4645
updateCostmapSize();
@@ -50,7 +49,24 @@ void CostmapDownsampler::initialize(
5049
_costmap->getOriginX(), _costmap->getOriginY(), UNKNOWN);
5150

5251
_downsampled_costmap_pub = std::make_unique<nav2_costmap_2d::Costmap2DPublisher>(
53-
_node, _downsampled_costmap.get(), global_frame, _topic_name, false);
52+
node, _downsampled_costmap.get(), global_frame, topic_name, false);
53+
}
54+
55+
void CostmapDownsampler::on_activate()
56+
{
57+
_downsampled_costmap_pub->on_activate();
58+
}
59+
60+
void CostmapDownsampler::on_deactivate()
61+
{
62+
_downsampled_costmap_pub->on_deactivate();
63+
}
64+
65+
void CostmapDownsampler::on_cleanup()
66+
{
67+
_costmap = nullptr;
68+
_downsampled_costmap.reset();
69+
_downsampled_costmap_pub.reset();
5470
}
5571

5672
nav2_costmap_2d::Costmap2D * CostmapDownsampler::downsample(
@@ -74,10 +90,7 @@ nav2_costmap_2d::Costmap2D * CostmapDownsampler::downsample(
7490
}
7591
}
7692

77-
if (_node->count_subscribers(_topic_name) > 0) {
78-
_downsampled_costmap_pub->publishCostmap();
79-
}
80-
93+
_downsampled_costmap_pub->publishCostmap();
8194
return _downsampled_costmap.get();
8295
}
8396

smac_planner/src/smac_planner.cpp

Lines changed: 54 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ using namespace std::chrono; // NOLINT
3131
SmacPlanner::SmacPlanner()
3232
: _a_star(nullptr),
3333
_smoother(nullptr),
34-
_node(nullptr),
3534
_costmap(nullptr),
3635
_costmap_downsampler(nullptr)
3736
{
@@ -40,7 +39,7 @@ SmacPlanner::SmacPlanner()
4039
SmacPlanner::~SmacPlanner()
4140
{
4241
RCLCPP_INFO(
43-
_node->get_logger(), "Destroying plugin %s of type SmacPlanner",
42+
_logger, "Destroying plugin %s of type SmacPlanner",
4443
_name.c_str());
4544
}
4645

@@ -49,7 +48,9 @@ void SmacPlanner::configure(
4948
std::string name, std::shared_ptr<tf2_ros::Buffer>/*tf*/,
5049
std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros)
5150
{
52-
_node = parent.lock();
51+
auto node = parent.lock();
52+
_logger = node->get_logger();
53+
_clock = node->get_clock();
5354
_costmap = costmap_ros->getCostmap();
5455
_name = name;
5556
_global_frame = costmap_ros->getGlobalFrameID();
@@ -64,77 +65,77 @@ void SmacPlanner::configure(
6465

6566
// General planner params
6667
nav2_util::declare_parameter_if_not_declared(
67-
_node, name + ".tolerance", rclcpp::ParameterValue(0.125));
68-
_tolerance = static_cast<float>(_node->get_parameter(name + ".tolerance").as_double());
68+
node, name + ".tolerance", rclcpp::ParameterValue(0.125));
69+
_tolerance = static_cast<float>(node->get_parameter(name + ".tolerance").as_double());
6970
nav2_util::declare_parameter_if_not_declared(
70-
_node, name + ".downsample_costmap", rclcpp::ParameterValue(true));
71-
_node->get_parameter(name + ".downsample_costmap", _downsample_costmap);
71+
node, name + ".downsample_costmap", rclcpp::ParameterValue(true));
72+
node->get_parameter(name + ".downsample_costmap", _downsample_costmap);
7273
nav2_util::declare_parameter_if_not_declared(
73-
_node, name + ".downsampling_factor", rclcpp::ParameterValue(1));
74-
_node->get_parameter(name + ".downsampling_factor", _downsampling_factor);
74+
node, name + ".downsampling_factor", rclcpp::ParameterValue(1));
75+
node->get_parameter(name + ".downsampling_factor", _downsampling_factor);
7576

7677
nav2_util::declare_parameter_if_not_declared(
77-
_node, name + ".angle_quantization_bins", rclcpp::ParameterValue(1));
78-
_node->get_parameter(name + ".angle_quantization_bins", angle_quantizations);
78+
node, name + ".angle_quantization_bins", rclcpp::ParameterValue(1));
79+
node->get_parameter(name + ".angle_quantization_bins", angle_quantizations);
7980
_angle_bin_size = 2.0 * M_PI / angle_quantizations;
8081
_angle_quantizations = static_cast<unsigned int>(angle_quantizations);
8182

8283
nav2_util::declare_parameter_if_not_declared(
83-
_node, name + ".allow_unknown", rclcpp::ParameterValue(true));
84-
_node->get_parameter(name + ".allow_unknown", allow_unknown);
84+
node, name + ".allow_unknown", rclcpp::ParameterValue(true));
85+
node->get_parameter(name + ".allow_unknown", allow_unknown);
8586
nav2_util::declare_parameter_if_not_declared(
86-
_node, name + ".max_iterations", rclcpp::ParameterValue(-1));
87-
_node->get_parameter(name + ".max_iterations", max_iterations);
87+
node, name + ".max_iterations", rclcpp::ParameterValue(-1));
88+
node->get_parameter(name + ".max_iterations", max_iterations);
8889
nav2_util::declare_parameter_if_not_declared(
89-
_node, name + ".smooth_path", rclcpp::ParameterValue(false));
90-
_node->get_parameter(name + ".smooth_path", smooth_path);
90+
node, name + ".smooth_path", rclcpp::ParameterValue(false));
91+
node->get_parameter(name + ".smooth_path", smooth_path);
9192

9293
nav2_util::declare_parameter_if_not_declared(
93-
_node, name + ".minimum_turning_radius", rclcpp::ParameterValue(0.2));
94-
_node->get_parameter(name + ".minimum_turning_radius", search_info.minimum_turning_radius);
94+
node, name + ".minimum_turning_radius", rclcpp::ParameterValue(0.2));
95+
node->get_parameter(name + ".minimum_turning_radius", search_info.minimum_turning_radius);
9596

9697
nav2_util::declare_parameter_if_not_declared(
97-
_node, name + ".reverse_penalty", rclcpp::ParameterValue(2.0));
98-
_node->get_parameter(name + ".reverse_penalty", search_info.reverse_penalty);
98+
node, name + ".reverse_penalty", rclcpp::ParameterValue(2.0));
99+
node->get_parameter(name + ".reverse_penalty", search_info.reverse_penalty);
99100
nav2_util::declare_parameter_if_not_declared(
100-
_node, name + ".change_penalty", rclcpp::ParameterValue(0.5));
101-
_node->get_parameter(name + ".change_penalty", search_info.change_penalty);
101+
node, name + ".change_penalty", rclcpp::ParameterValue(0.5));
102+
node->get_parameter(name + ".change_penalty", search_info.change_penalty);
102103
nav2_util::declare_parameter_if_not_declared(
103-
_node, name + ".non_straight_penalty", rclcpp::ParameterValue(1.05));
104-
_node->get_parameter(name + ".non_straight_penalty", search_info.non_straight_penalty);
104+
node, name + ".non_straight_penalty", rclcpp::ParameterValue(1.05));
105+
node->get_parameter(name + ".non_straight_penalty", search_info.non_straight_penalty);
105106
nav2_util::declare_parameter_if_not_declared(
106-
_node, name + ".cost_penalty", rclcpp::ParameterValue(1.2));
107-
_node->get_parameter(name + ".cost_penalty", search_info.cost_penalty);
107+
node, name + ".cost_penalty", rclcpp::ParameterValue(1.2));
108+
node->get_parameter(name + ".cost_penalty", search_info.cost_penalty);
108109
nav2_util::declare_parameter_if_not_declared(
109-
_node, name + ".analytic_expansion_ratio", rclcpp::ParameterValue(2.0));
110-
_node->get_parameter(name + ".analytic_expansion_ratio", search_info.analytic_expansion_ratio);
110+
node, name + ".analytic_expansion_ratio", rclcpp::ParameterValue(2.0));
111+
node->get_parameter(name + ".analytic_expansion_ratio", search_info.analytic_expansion_ratio);
111112

112113
nav2_util::declare_parameter_if_not_declared(
113-
_node, name + ".max_planning_time_ms", rclcpp::ParameterValue(5000.0));
114-
_node->get_parameter(name + ".max_planning_time_ms", _max_planning_time);
114+
node, name + ".max_planning_time_ms", rclcpp::ParameterValue(5000.0));
115+
node->get_parameter(name + ".max_planning_time_ms", _max_planning_time);
115116

116117
nav2_util::declare_parameter_if_not_declared(
117-
_node, name + ".motion_model_for_search", rclcpp::ParameterValue(std::string("DUBIN")));
118-
_node->get_parameter(name + ".motion_model_for_search", motion_model_for_search);
118+
node, name + ".motion_model_for_search", rclcpp::ParameterValue(std::string("DUBIN")));
119+
node->get_parameter(name + ".motion_model_for_search", motion_model_for_search);
119120
MotionModel motion_model = fromString(motion_model_for_search);
120121
if (motion_model == MotionModel::UNKNOWN) {
121122
RCLCPP_WARN(
122-
_node->get_logger(),
123+
_logger,
123124
"Unable to get MotionModel search type. Given '%s', "
124125
"valid options are MOORE, VON_NEUMANN, DUBIN, REEDS_SHEPP.",
125126
motion_model_for_search.c_str());
126127
}
127128

128129
if (max_on_approach_iterations <= 0) {
129130
RCLCPP_INFO(
130-
_node->get_logger(), "On approach iteration selected as <= 0, "
131+
_logger, "On approach iteration selected as <= 0, "
131132
"disabling tolerance and on approach iterations.");
132133
max_on_approach_iterations = std::numeric_limits<int>::max();
133134
}
134135

135136
if (max_iterations <= 0) {
136137
RCLCPP_INFO(
137-
_node->get_logger(), "maximum iteration selected as <= 0, "
138+
_logger, "maximum iteration selected as <= 0, "
138139
"disabling maximum iterations.");
139140
max_iterations = std::numeric_limits<int>::max();
140141
}
@@ -153,22 +154,23 @@ void SmacPlanner::configure(
153154

154155
if (smooth_path) {
155156
_smoother = std::make_unique<Smoother>();
156-
_optimizer_params.get(_node.get(), name);
157-
_smoother_params.get(_node.get(), name);
157+
_optimizer_params.get(node.get(), name);
158+
_smoother_params.get(node.get(), name);
158159
_smoother_params.max_curvature = 1.0f / minimum_turning_radius_global_coords;
159160
_smoother->initialize(_optimizer_params);
160161
}
161162

162163
if (_downsample_costmap && _downsampling_factor > 1) {
163164
std::string topic_name = "downsampled_costmap";
164-
_costmap_downsampler = std::make_unique<CostmapDownsampler>(_node);
165-
_costmap_downsampler->initialize(_global_frame, topic_name, _costmap, _downsampling_factor);
165+
_costmap_downsampler = std::make_unique<CostmapDownsampler>();
166+
_costmap_downsampler->on_configure(
167+
node, _global_frame, topic_name, _costmap, _downsampling_factor);
166168
}
167169

168-
_raw_plan_publisher = _node->create_publisher<nav_msgs::msg::Path>("unsmoothed_plan", 1);
170+
_raw_plan_publisher = node->create_publisher<nav_msgs::msg::Path>("unsmoothed_plan", 1);
169171

170172
RCLCPP_INFO(
171-
_node->get_logger(), "Configured plugin %s of type SmacPlanner with "
173+
_logger, "Configured plugin %s of type SmacPlanner with "
172174
"tolerance %.2f, maximum iterations %i, "
173175
"max on approach iterations %i, and %s. Using motion model: %s.",
174176
_name.c_str(), _tolerance, max_iterations, max_on_approach_iterations,
@@ -179,32 +181,33 @@ void SmacPlanner::configure(
179181
void SmacPlanner::activate()
180182
{
181183
RCLCPP_INFO(
182-
_node->get_logger(), "Activating plugin %s of type SmacPlanner",
184+
_logger, "Activating plugin %s of type SmacPlanner",
183185
_name.c_str());
184186
_raw_plan_publisher->on_activate();
185187
if (_costmap_downsampler) {
186-
_costmap_downsampler->activatePublisher();
188+
_costmap_downsampler->on_activate();
187189
}
188190
}
189191

190192
void SmacPlanner::deactivate()
191193
{
192194
RCLCPP_INFO(
193-
_node->get_logger(), "Deactivating plugin %s of type SmacPlanner",
195+
_logger, "Deactivating plugin %s of type SmacPlanner",
194196
_name.c_str());
195197
_raw_plan_publisher->on_deactivate();
196198
if (_costmap_downsampler) {
197-
_costmap_downsampler->deactivatePublisher();
199+
_costmap_downsampler->on_deactivate();
198200
}
199201
}
200202

201203
void SmacPlanner::cleanup()
202204
{
203205
RCLCPP_INFO(
204-
_node->get_logger(), "Cleaning up plugin %s of type SmacPlanner",
206+
_logger, "Cleaning up plugin %s of type SmacPlanner",
205207
_name.c_str());
206208
_a_star.reset();
207209
_smoother.reset();
210+
_costmap_downsampler->on_cleanup();
208211
_costmap_downsampler.reset();
209212
_raw_plan_publisher.reset();
210213
}
@@ -251,7 +254,7 @@ nav_msgs::msg::Path SmacPlanner::createPlan(
251254

252255
// Setup message
253256
nav_msgs::msg::Path plan;
254-
plan.header.stamp = _node->now();
257+
plan.header.stamp = _clock->now();
255258
plan.header.frame_id = _global_frame;
256259
geometry_msgs::msg::PoseStamped pose;
257260
pose.header = plan.header;
@@ -282,7 +285,7 @@ nav_msgs::msg::Path SmacPlanner::createPlan(
282285

283286
if (!error.empty()) {
284287
RCLCPP_WARN(
285-
_node->get_logger(),
288+
_logger,
286289
"%s: failed to create plan, %s.",
287290
_name.c_str(), error.c_str());
288291
return plan;
@@ -304,7 +307,7 @@ nav_msgs::msg::Path SmacPlanner::createPlan(
304307
}
305308

306309
// Publish raw path for debug
307-
if (_node->count_subscribers(_raw_plan_publisher->get_topic_name()) > 0) {
310+
if (_raw_plan_publisher->get_subscription_count() > 0) {
308311
_raw_plan_publisher->publish(plan);
309312
}
310313

@@ -328,7 +331,7 @@ nav_msgs::msg::Path SmacPlanner::createPlan(
328331
// Smooth plan
329332
if (!_smoother->smooth(path_world, costmap, _smoother_params)) {
330333
RCLCPP_WARN(
331-
_node->get_logger(),
334+
_logger,
332335
"%s: failed to smooth plan, Ceres could not find a usable solution to optimize.",
333336
_name.c_str());
334337
return plan;

0 commit comments

Comments
 (0)