Skip to content

Commit 976fbeb

Browse files
authored
Redesign DWB dynamic parameters pattern (#5641)
* Redesign dwb dynamic parameters patterns Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Fix typo Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Activate dynamic parameters callback in Avtivate stage Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Precommit Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Fix as suggested Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> --------- Signed-off-by: mini-1235 <mauricepurnawan@gmail.com>
1 parent bad1142 commit 976fbeb

File tree

7 files changed

+184
-65
lines changed

7 files changed

+184
-65
lines changed

nav2_dwb_controller/dwb_core/include/dwb_core/trajectory_generator.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ class TrajectoryGenerator
7575
virtual void initialize(
7676
const nav2::LifecycleNode::SharedPtr & nh,
7777
const std::string & plugin_name) = 0;
78+
/**
79+
* @brief Activate callbacks as needed
80+
*/
81+
virtual void activate() = 0;
82+
/**
83+
* @brief Deactivate callbacks as needed
84+
*/
85+
virtual void deactivate() = 0;
7886
virtual void reset() {}
7987
/**
8088
* @brief Start a new iteration based on the current velocity

nav2_dwb_controller/dwb_core/src/dwb_local_planner.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,14 @@ void
151151
DWBLocalPlanner::activate()
152152
{
153153
pub_->on_activate();
154+
traj_generator_->activate();
154155
}
155156

156157
void
157158
DWBLocalPlanner::deactivate()
158159
{
159160
pub_->on_deactivate();
161+
traj_generator_->deactivate();
160162
}
161163

162164
void

nav2_dwb_controller/dwb_plugins/include/dwb_plugins/kinematic_parameters.hpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ class KinematicsHandler
142142
KinematicsHandler();
143143
~KinematicsHandler();
144144
void initialize(const nav2::LifecycleNode::SharedPtr & nh, const std::string & plugin_name);
145+
void activate();
146+
void deactivate();
145147

146148
inline KinematicParameters getKinematics() {return *kinematics_.load();}
147149

@@ -151,16 +153,30 @@ class KinematicsHandler
151153

152154
protected:
153155
nav2::LifecycleNode::WeakPtr node_;
156+
rclcpp::Logger logger_{rclcpp::get_logger("DWBController")};
154157
std::atomic<KinematicParameters *> kinematics_;
155158

156159
// Dynamic parameters handler
157-
rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr dyn_params_handler_;
160+
rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtr post_set_params_handler_;
161+
rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr on_set_params_handler_;
158162
/**
159-
* @brief Callback executed when a parameter change is detected
160-
* @param parameters list of changed parameters
163+
* @brief Validate incoming parameter updates before applying them.
164+
* This callback is triggered when one or more parameters are about to be updated.
165+
* It checks the validity of parameter values and rejects updates that would lead
166+
* to invalid or inconsistent configurations
167+
* @param parameters List of parameters that are being updated.
168+
* @return rcl_interfaces::msg::SetParametersResult Result indicating whether the update is accepted.
161169
*/
162-
rcl_interfaces::msg::SetParametersResult dynamicParametersCallback(
170+
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(
163171
std::vector<rclcpp::Parameter> parameters);
172+
173+
/**
174+
* @brief Apply parameter updates after validation
175+
* This callback is executed when parameters have been successfully updated.
176+
* It updates the internal configuration of the node with the new parameter values.
177+
* @param parameters List of parameters that have been updated.
178+
*/
179+
void updateParametersCallback(std::vector<rclcpp::Parameter> parameters);
164180
void update_kinematics(KinematicParameters kinematics);
165181
std::string plugin_name_;
166182
};

nav2_dwb_controller/dwb_plugins/include/dwb_plugins/standard_traj_generator.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ class StandardTrajectoryGenerator : public dwb_core::TrajectoryGenerator
8282
}
8383
}
8484

85+
/**
86+
* @brief Registers callbacks for dynamic parameter handling.
87+
*/
88+
void activate();
89+
90+
/**
91+
* @brief Resets callbacks for dynamic parameter handling.
92+
*/
93+
void deactivate();
94+
8595
protected:
8696
/**
8797
* @brief Initialize the VelocityIterator pointer. Put in its own function for easy overriding

nav2_dwb_controller/dwb_plugins/src/kinematic_parameters.cpp

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ KinematicsHandler::KinematicsHandler()
5555

5656
KinematicsHandler::~KinematicsHandler()
5757
{
58-
auto node = node_.lock();
59-
if (dyn_params_handler_ && node) {
60-
node->remove_on_set_parameters_callback(dyn_params_handler_.get());
61-
}
62-
dyn_params_handler_.reset();
6358
delete kinematics_.load();
6459
}
6560

@@ -69,6 +64,7 @@ void KinematicsHandler::initialize(
6964
{
7065
node_ = nh;
7166
plugin_name_ = plugin_name;
67+
logger_ = nh->get_logger();
7268

7369
declare_parameter_if_not_declared(nh, plugin_name + ".min_vel_x", rclcpp::ParameterValue(0.0));
7470
declare_parameter_if_not_declared(nh, plugin_name + ".min_vel_y", rclcpp::ParameterValue(0.0));
@@ -119,16 +115,39 @@ void KinematicsHandler::initialize(
119115
kinematics.base_max_speed_xy_ = kinematics.max_speed_xy_;
120116
kinematics.base_max_vel_theta_ = kinematics.max_vel_theta_;
121117

122-
// Add callback for dynamic parameters
123-
dyn_params_handler_ = nh->add_on_set_parameters_callback(
124-
std::bind(&KinematicsHandler::dynamicParametersCallback, this, _1));
125-
126118
kinematics.min_speed_xy_sq_ = kinematics.min_speed_xy_ * kinematics.min_speed_xy_;
127119
kinematics.max_speed_xy_sq_ = kinematics.max_speed_xy_ * kinematics.max_speed_xy_;
128120

129121
update_kinematics(kinematics);
130122
}
131123

124+
void KinematicsHandler::activate()
125+
{
126+
auto node = node_.lock();
127+
// Add callback for dynamic parameters
128+
post_set_params_handler_ = node->add_post_set_parameters_callback(
129+
std::bind(
130+
&KinematicsHandler::updateParametersCallback,
131+
this, std::placeholders::_1));
132+
on_set_params_handler_ = node->add_on_set_parameters_callback(
133+
std::bind(
134+
&KinematicsHandler::validateParameterUpdatesCallback,
135+
this, std::placeholders::_1));
136+
}
137+
138+
void KinematicsHandler::deactivate()
139+
{
140+
auto node = node_.lock();
141+
if (post_set_params_handler_ && node) {
142+
node->remove_post_set_parameters_callback(post_set_params_handler_.get());
143+
}
144+
post_set_params_handler_.reset();
145+
if (on_set_params_handler_ && node) {
146+
node->remove_on_set_parameters_callback(on_set_params_handler_.get());
147+
}
148+
on_set_params_handler_.reset();
149+
}
150+
132151
void KinematicsHandler::setSpeedLimit(
133152
const double & speed_limit, const bool & percentage)
134153
{
@@ -169,8 +188,48 @@ void KinematicsHandler::setSpeedLimit(
169188
update_kinematics(kinematics);
170189
}
171190

172-
rcl_interfaces::msg::SetParametersResult
173-
KinematicsHandler::dynamicParametersCallback(std::vector<rclcpp::Parameter> parameters)
191+
rcl_interfaces::msg::SetParametersResult KinematicsHandler::validateParameterUpdatesCallback(
192+
std::vector<rclcpp::Parameter> parameters)
193+
{
194+
rcl_interfaces::msg::SetParametersResult result;
195+
result.successful = true;
196+
for (auto parameter : parameters) {
197+
const auto & param_type = parameter.get_type();
198+
const auto & param_name = parameter.get_name();
199+
if (param_name.find(plugin_name_ + ".") != 0) {
200+
continue;
201+
}
202+
if (param_type == ParameterType::PARAMETER_DOUBLE) {
203+
if (parameter.as_double() < 0.0 &&
204+
(param_name == plugin_name_ + ".max_vel_x" || param_name == plugin_name_ + ".max_vel_y" ||
205+
param_name == plugin_name_ + ".max_vel_theta" ||
206+
param_name == plugin_name_ + ".max_speed_xy" ||
207+
param_name == plugin_name_ + ".acc_lim_x" || param_name == plugin_name_ + ".acc_lim_y" ||
208+
param_name == plugin_name_ + ".acc_lim_theta"))
209+
{
210+
RCLCPP_WARN(
211+
logger_, "The value of parameter '%s' is incorrectly set to %f, "
212+
"it should be >= 0. Ignoring parameter update.",
213+
param_name.c_str(), parameter.as_double());
214+
result.successful = false;
215+
} else if (parameter.as_double() > 0.0 && // NOLINT
216+
(param_name == plugin_name_ + ".decel_lim_x" ||
217+
param_name == plugin_name_ + ".decel_lim_y" ||
218+
param_name == plugin_name_ + ".decel_lim_theta"))
219+
{
220+
RCLCPP_WARN(
221+
logger_, "The value of parameter '%s' is incorrectly set to %f, "
222+
"it should be <= 0. Ignoring parameter update.",
223+
param_name.c_str(), parameter.as_double());
224+
result.successful = false;
225+
}
226+
}
227+
}
228+
return result;
229+
}
230+
231+
void
232+
KinematicsHandler::updateParametersCallback(std::vector<rclcpp::Parameter> parameters)
174233
{
175234
rcl_interfaces::msg::SetParametersResult result;
176235
KinematicParameters kinematics(*kinematics_.load());
@@ -221,8 +280,6 @@ KinematicsHandler::dynamicParametersCallback(std::vector<rclcpp::Parameter> para
221280
}
222281
}
223282
update_kinematics(kinematics);
224-
result.successful = true;
225-
return result;
226283
}
227284

228285
void KinematicsHandler::update_kinematics(KinematicParameters kinematics)

nav2_dwb_controller/dwb_plugins/src/standard_traj_generator.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ void StandardTrajectoryGenerator::initialize(
9797
nh->get_parameter(plugin_name + ".limit_vel_cmd_in_traj", limit_vel_cmd_in_traj_);
9898
}
9999

100+
void StandardTrajectoryGenerator::activate()
101+
{
102+
kinematics_handler_->activate();
103+
}
104+
105+
void StandardTrajectoryGenerator::deactivate()
106+
{
107+
kinematics_handler_->deactivate();
108+
}
109+
100110
void StandardTrajectoryGenerator::initializeIterator(
101111
const nav2::LifecycleNode::SharedPtr & nh)
102112
{

nav2_dwb_controller/dwb_plugins/test/kinematic_parameters_test.cpp

Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -43,56 +43,39 @@ using rcl_interfaces::msg::Parameter;
4343
using rcl_interfaces::msg::ParameterType;
4444
using rcl_interfaces::msg::ParameterEvent;
4545

46-
class KinematicsHandlerTest : public dwb_plugins::KinematicsHandler
47-
{
48-
public:
49-
void simulate_event(
50-
std::vector<rclcpp::Parameter> parameters)
51-
{
52-
dynamicParametersCallback(parameters);
53-
}
54-
};
55-
5646
TEST(KinematicParameters, SetAllParameters) {
5747
std::string nodeName = "test_node";
5848
auto node = std::make_shared<nav2::LifecycleNode>(nodeName);
59-
KinematicsHandlerTest kh;
49+
dwb_plugins::KinematicsHandler kh;
6050
kh.initialize(node, nodeName);
51+
kh.activate();
6152

62-
std::vector<rclcpp::Parameter> parameters;
63-
rclcpp::Parameter
64-
p_minX(nodeName + ".min_vel_x", 12.34),
65-
p_maxX(nodeName + ".max_vel_x", 23.45),
66-
p_minY(nodeName + ".min_vel_y", 34.56),
67-
p_maxY(nodeName + ".max_vel_y", 45.67),
68-
p_accX(nodeName + ".acc_lim_x", 56.78),
69-
p_decelX(nodeName + ".acc_lim_y", 67.89),
70-
p_accY(nodeName + ".decel_lim_x", 78.90),
71-
p_decelY(nodeName + ".decel_lim_y", 89.01),
72-
p_minSpeedXY(nodeName + ".min_speed_xy", 90.12),
73-
p_maxSpeedXY(nodeName + ".max_speed_xy", 123.456),
74-
p_maxTheta(nodeName + ".max_vel_theta", 345.678),
75-
p_accTheta(nodeName + ".acc_lim_theta", 234.567),
76-
p_decelTheta(nodeName + ".decel_lim_theta", 456.789),
77-
p_minSpeedTheta(nodeName + ".min_speed_theta", 567.890);
78-
79-
parameters.push_back(p_minX);
80-
parameters.push_back(p_minX);
81-
parameters.push_back(p_maxX);
82-
parameters.push_back(p_minY);
83-
parameters.push_back(p_maxY);
84-
parameters.push_back(p_accX);
85-
parameters.push_back(p_accY);
86-
parameters.push_back(p_decelX);
87-
parameters.push_back(p_decelY);
88-
parameters.push_back(p_minSpeedXY);
89-
parameters.push_back(p_maxSpeedXY);
90-
parameters.push_back(p_maxTheta);
91-
parameters.push_back(p_accTheta);
92-
parameters.push_back(p_decelTheta);
93-
parameters.push_back(p_minSpeedTheta);
94-
95-
kh.simulate_event(parameters);
53+
auto rec_param = std::make_shared<rclcpp::AsyncParametersClient>(
54+
node->get_node_base_interface(), node->get_node_topics_interface(),
55+
node->get_node_graph_interface(),
56+
node->get_node_services_interface());
57+
58+
auto results = rec_param->set_parameters_atomically(
59+
{
60+
rclcpp::Parameter(nodeName + ".min_vel_x", 12.34),
61+
rclcpp::Parameter(nodeName + ".max_vel_x", 23.45),
62+
rclcpp::Parameter(nodeName + ".min_vel_y", 34.56),
63+
rclcpp::Parameter(nodeName + ".max_vel_y", 45.67),
64+
rclcpp::Parameter(nodeName + ".acc_lim_x", 56.78),
65+
rclcpp::Parameter(nodeName + ".acc_lim_y", 67.89),
66+
rclcpp::Parameter(nodeName + ".decel_lim_x", -78.90),
67+
rclcpp::Parameter(nodeName + ".decel_lim_y", -89.01),
68+
rclcpp::Parameter(nodeName + ".min_speed_xy", 90.12),
69+
rclcpp::Parameter(nodeName + ".max_speed_xy", 123.456),
70+
rclcpp::Parameter(nodeName + ".max_vel_theta", 345.678),
71+
rclcpp::Parameter(nodeName + ".acc_lim_theta", 234.567),
72+
rclcpp::Parameter(nodeName + ".decel_lim_theta", -456.789),
73+
rclcpp::Parameter(nodeName + ".min_speed_theta", 567.890),
74+
});
75+
76+
rclcpp::spin_until_future_complete(
77+
node->get_node_base_interface(),
78+
results);
9679

9780
dwb_plugins::KinematicParameters kp = kh.getKinematics();
9881

@@ -102,14 +85,47 @@ TEST(KinematicParameters, SetAllParameters) {
10285
EXPECT_EQ(kp.getMaxY(), 45.67);
10386
EXPECT_EQ(kp.getAccX(), 56.78);
10487
EXPECT_EQ(kp.getAccY(), 67.89);
105-
EXPECT_EQ(kp.getDecelX(), 78.90);
106-
EXPECT_EQ(kp.getDecelY(), 89.01);
88+
EXPECT_EQ(kp.getDecelX(), -78.90);
89+
EXPECT_EQ(kp.getDecelY(), -89.01);
10790
EXPECT_EQ(kp.getMinSpeedXY(), 90.12);
10891
EXPECT_EQ(kp.getMaxSpeedXY(), 123.456);
10992
EXPECT_EQ(kp.getAccTheta(), 234.567);
11093
EXPECT_EQ(kp.getMaxTheta(), 345.678);
111-
EXPECT_EQ(kp.getDecelTheta(), 456.789);
94+
EXPECT_EQ(kp.getDecelTheta(), -456.789);
11295
EXPECT_EQ(kp.getMinSpeedTheta(), 567.890);
96+
97+
results = rec_param->set_parameters_atomically(
98+
{
99+
rclcpp::Parameter(nodeName + ".decel_lim_x", 1.0)
100+
});
101+
102+
rclcpp::spin_until_future_complete(
103+
node->get_node_base_interface(),
104+
results);
105+
106+
EXPECT_EQ(kp.getDecelX(), -78.90);
107+
108+
results = rec_param->set_parameters_atomically(
109+
{
110+
rclcpp::Parameter(nodeName + ".max_vel_x", -1.0)
111+
});
112+
113+
rclcpp::spin_until_future_complete(
114+
node->get_node_base_interface(),
115+
results);
116+
117+
EXPECT_EQ(kp.getMaxX(), 23.45);
118+
119+
results = rec_param->set_parameters_atomically(
120+
{
121+
rclcpp::Parameter(nodeName + ".acc_lim_x", -0.1)
122+
});
123+
124+
rclcpp::spin_until_future_complete(
125+
node->get_node_base_interface(),
126+
results);
127+
128+
EXPECT_EQ(kp.getAccX(), 56.78);
113129
}
114130

115131

0 commit comments

Comments
 (0)