Skip to content

Commit b9817db

Browse files
authored
Add 6dof support for velocity smoother (#5243)
* Add 6dof support for velocity smoother Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Fix formatting and logic error Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Check size first Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Add tests for param size Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Revert param changes Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Add more tests Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> * Fix as suggested Signed-off-by: Maurice <mauricepurnawan@gmail.com> --------- Signed-off-by: mini-1235 <mauricepurnawan@gmail.com> Signed-off-by: Maurice <mauricepurnawan@gmail.com>
1 parent f10aa77 commit b9817db

File tree

3 files changed

+270
-67
lines changed

3 files changed

+270
-67
lines changed

nav2_velocity_smoother/include/nav2_velocity_smoother/velocity_smoother.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class VelocitySmoother : public nav2::LifecycleNode
149149
bool open_loop_;
150150
bool stopped_{true};
151151
bool scale_velocities_;
152+
bool is_6dof_;
152153
std::vector<double> max_velocities_;
153154
std::vector<double> min_velocities_;
154155
std::vector<double> max_accels_;

nav2_velocity_smoother/src/velocity_smoother.cpp

Lines changed: 167 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,37 @@ VelocitySmoother::on_configure(const rclcpp_lifecycle::State & state)
7474
node->get_parameter("max_accel", max_accels_);
7575
node->get_parameter("max_decel", max_decels_);
7676

77-
for (unsigned int i = 0; i != 3; i++) {
77+
// Get feature parameters
78+
declare_parameter_if_not_declared(node, "odom_topic", rclcpp::ParameterValue("odom"));
79+
declare_parameter_if_not_declared(node, "odom_duration", rclcpp::ParameterValue(0.1));
80+
declare_parameter_if_not_declared(
81+
node, "deadband_velocity", rclcpp::ParameterValue(std::vector<double>{0.0, 0.0, 0.0}));
82+
declare_parameter_if_not_declared(node, "velocity_timeout", rclcpp::ParameterValue(1.0));
83+
node->get_parameter("odom_topic", odom_topic_);
84+
node->get_parameter("odom_duration", odom_duration_);
85+
node->get_parameter("deadband_velocity", deadband_velocities_);
86+
node->get_parameter("velocity_timeout", velocity_timeout_dbl);
87+
velocity_timeout_ = rclcpp::Duration::from_seconds(velocity_timeout_dbl);
88+
89+
// Check if parameters are properly set
90+
size_t size = max_velocities_.size();
91+
is_6dof_ = (size == 6);
92+
93+
if ((size != 3 && size != 6) ||
94+
min_velocities_.size() != size ||
95+
max_accels_.size() != size ||
96+
max_decels_.size() != size ||
97+
deadband_velocities_.size() != size)
98+
{
99+
RCLCPP_ERROR(
100+
get_logger(),
101+
"Invalid setting of kinematic and/or deadband limits!"
102+
" All limits must be size of 3 (x, y, theta) or 6 (x, y, z, r, p, y)");
103+
on_cleanup(state);
104+
return nav2::CallbackReturn::FAILURE;
105+
}
106+
107+
for (unsigned int i = 0; i != size; i++) {
78108
if (max_decels_[i] > 0.0) {
79109
RCLCPP_ERROR(
80110
get_logger(),
@@ -108,29 +138,6 @@ VelocitySmoother::on_configure(const rclcpp_lifecycle::State & state)
108138
}
109139
}
110140

111-
// Get feature parameters
112-
declare_parameter_if_not_declared(node, "odom_topic", rclcpp::ParameterValue("odom"));
113-
declare_parameter_if_not_declared(node, "odom_duration", rclcpp::ParameterValue(0.1));
114-
declare_parameter_if_not_declared(
115-
node, "deadband_velocity", rclcpp::ParameterValue(std::vector<double>{0.0, 0.0, 0.0}));
116-
declare_parameter_if_not_declared(node, "velocity_timeout", rclcpp::ParameterValue(1.0));
117-
node->get_parameter("odom_topic", odom_topic_);
118-
node->get_parameter("odom_duration", odom_duration_);
119-
node->get_parameter("deadband_velocity", deadband_velocities_);
120-
node->get_parameter("velocity_timeout", velocity_timeout_dbl);
121-
velocity_timeout_ = rclcpp::Duration::from_seconds(velocity_timeout_dbl);
122-
123-
if (max_velocities_.size() != 3 || min_velocities_.size() != 3 ||
124-
max_accels_.size() != 3 || max_decels_.size() != 3 || deadband_velocities_.size() != 3)
125-
{
126-
RCLCPP_ERROR(
127-
get_logger(),
128-
"Invalid setting of kinematic and/or deadband limits!"
129-
" All limits must be size of 3 representing (x, y, theta).");
130-
on_cleanup(state);
131-
return nav2::CallbackReturn::FAILURE;
132-
}
133-
134141
// Get control type
135142
if (feedback_type == "OPEN_LOOP") {
136143
open_loop_ = true;
@@ -332,15 +339,36 @@ void VelocitySmoother::smootherTimer()
332339
}
333340

334341
// Apply absolute velocity restrictions to the command
335-
command_->twist.linear.x = std::clamp(
336-
command_->twist.linear.x, min_velocities_[0],
337-
max_velocities_[0]);
338-
command_->twist.linear.y = std::clamp(
339-
command_->twist.linear.y, min_velocities_[1],
340-
max_velocities_[1]);
341-
command_->twist.angular.z = std::clamp(
342-
command_->twist.angular.z, min_velocities_[2],
343-
max_velocities_[2]);
342+
if(!is_6dof_) {
343+
command_->twist.linear.x = std::clamp(
344+
command_->twist.linear.x, min_velocities_[0],
345+
max_velocities_[0]);
346+
command_->twist.linear.y = std::clamp(
347+
command_->twist.linear.y, min_velocities_[1],
348+
max_velocities_[1]);
349+
command_->twist.angular.z = std::clamp(
350+
command_->twist.angular.z, min_velocities_[2],
351+
max_velocities_[2]);
352+
} else {
353+
command_->twist.linear.x = std::clamp(
354+
command_->twist.linear.x, min_velocities_[0],
355+
max_velocities_[0]);
356+
command_->twist.linear.y = std::clamp(
357+
command_->twist.linear.y, min_velocities_[1],
358+
max_velocities_[1]);
359+
command_->twist.linear.z = std::clamp(
360+
command_->twist.linear.z, min_velocities_[2],
361+
max_velocities_[2]);
362+
command_->twist.angular.x = std::clamp(
363+
command_->twist.angular.x, min_velocities_[3],
364+
max_velocities_[3]);
365+
command_->twist.angular.y = std::clamp(
366+
command_->twist.angular.y, min_velocities_[4],
367+
max_velocities_[4]);
368+
command_->twist.angular.z = std::clamp(
369+
command_->twist.angular.z, min_velocities_[5],
370+
max_velocities_[5]);
371+
}
344372

345373
// Find if any component is not within the acceleration constraints. If so, store the most
346374
// significant scale factor to apply to the vector <dvx, dvy, dvw>, eta, to reduce all axes
@@ -350,42 +378,113 @@ void VelocitySmoother::smootherTimer()
350378
double eta = 1.0;
351379
if (scale_velocities_) {
352380
double curr_eta = -1.0;
381+
if(!is_6dof_) {
382+
curr_eta = findEtaConstraint(
383+
current_.twist.linear.x, command_->twist.linear.x, max_accels_[0], max_decels_[0]);
384+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
385+
eta = curr_eta;
386+
}
353387

354-
curr_eta = findEtaConstraint(
355-
current_.twist.linear.x, command_->twist.linear.x, max_accels_[0], max_decels_[0]);
356-
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
357-
eta = curr_eta;
358-
}
388+
curr_eta = findEtaConstraint(
389+
current_.twist.linear.y, command_->twist.linear.y, max_accels_[1], max_decels_[1]);
390+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
391+
eta = curr_eta;
392+
}
359393

360-
curr_eta = findEtaConstraint(
361-
current_.twist.linear.y, command_->twist.linear.y, max_accels_[1], max_decels_[1]);
362-
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
363-
eta = curr_eta;
364-
}
394+
curr_eta = findEtaConstraint(
395+
current_.twist.angular.z, command_->twist.angular.z, max_accels_[2], max_decels_[2]);
396+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
397+
eta = curr_eta;
398+
}
399+
} else {
400+
curr_eta = findEtaConstraint(
401+
current_.twist.linear.x, command_->twist.linear.x, max_accels_[0], max_decels_[0]);
402+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
403+
eta = curr_eta;
404+
}
365405

366-
curr_eta = findEtaConstraint(
367-
current_.twist.angular.z, command_->twist.angular.z, max_accels_[2], max_decels_[2]);
368-
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
369-
eta = curr_eta;
406+
curr_eta = findEtaConstraint(
407+
current_.twist.linear.y, command_->twist.linear.y, max_accels_[1], max_decels_[1]);
408+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
409+
eta = curr_eta;
410+
}
411+
412+
curr_eta = findEtaConstraint(
413+
current_.twist.linear.z, command_->twist.linear.z, max_accels_[2], max_decels_[2]);
414+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
415+
eta = curr_eta;
416+
}
417+
418+
curr_eta = findEtaConstraint(
419+
current_.twist.angular.x, command_->twist.angular.x, max_accels_[3], max_decels_[3]);
420+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
421+
eta = curr_eta;
422+
}
423+
424+
curr_eta = findEtaConstraint(
425+
current_.twist.angular.y, command_->twist.angular.y, max_accels_[4], max_decels_[4]);
426+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
427+
eta = curr_eta;
428+
}
429+
430+
curr_eta = findEtaConstraint(
431+
current_.twist.angular.z, command_->twist.angular.z, max_accels_[5], max_decels_[5]);
432+
if (curr_eta > 0.0 && std::fabs(1.0 - curr_eta) > std::fabs(1.0 - eta)) {
433+
eta = curr_eta;
434+
}
370435
}
371436
}
372437

373-
cmd_vel->twist.linear.x = applyConstraints(
374-
current_.twist.linear.x, command_->twist.linear.x, max_accels_[0], max_decels_[0], eta);
375-
cmd_vel->twist.linear.y = applyConstraints(
376-
current_.twist.linear.y, command_->twist.linear.y, max_accels_[1], max_decels_[1], eta);
377-
cmd_vel->twist.angular.z = applyConstraints(
378-
current_.twist.angular.z, command_->twist.angular.z, max_accels_[2], max_decels_[2], eta);
438+
if(!is_6dof_) {
439+
cmd_vel->twist.linear.x = applyConstraints(
440+
current_.twist.linear.x, command_->twist.linear.x, max_accels_[0], max_decels_[0], eta);
441+
cmd_vel->twist.linear.y = applyConstraints(
442+
current_.twist.linear.y, command_->twist.linear.y, max_accels_[1], max_decels_[1], eta);
443+
cmd_vel->twist.angular.z = applyConstraints(
444+
current_.twist.angular.z, command_->twist.angular.z, max_accels_[2], max_decels_[2], eta);
445+
} else {
446+
cmd_vel->twist.linear.x = applyConstraints(
447+
current_.twist.linear.x, command_->twist.linear.x, max_accels_[0], max_decels_[0], eta);
448+
cmd_vel->twist.linear.y = applyConstraints(
449+
current_.twist.linear.y, command_->twist.linear.y, max_accels_[1], max_decels_[1], eta);
450+
cmd_vel->twist.linear.z = applyConstraints(
451+
current_.twist.linear.z, command_->twist.linear.z, max_accels_[2], max_decels_[2], eta);
452+
cmd_vel->twist.angular.x = applyConstraints(
453+
current_.twist.angular.x, command_->twist.angular.x, max_accels_[3], max_decels_[3], eta);
454+
cmd_vel->twist.angular.y = applyConstraints(
455+
current_.twist.angular.y, command_->twist.angular.y, max_accels_[4], max_decels_[4], eta);
456+
cmd_vel->twist.angular.z = applyConstraints(
457+
current_.twist.angular.z, command_->twist.angular.z, max_accels_[5], max_decels_[5], eta);
458+
}
459+
379460
last_cmd_ = *cmd_vel;
380461

381-
// Apply deadband restrictions & publish
382-
cmd_vel->twist.linear.x =
383-
fabs(cmd_vel->twist.linear.x) < deadband_velocities_[0] ? 0.0 : cmd_vel->twist.linear.x;
384-
cmd_vel->twist.linear.y =
385-
fabs(cmd_vel->twist.linear.y) < deadband_velocities_[1] ? 0.0 : cmd_vel->twist.linear.y;
386-
cmd_vel->twist.angular.z =
387-
fabs(cmd_vel->twist.angular.z) < deadband_velocities_[2] ? 0.0 : cmd_vel->twist.angular.z;
388462

463+
// Apply deadband restrictions & publish
464+
if(!is_6dof_) {
465+
cmd_vel->twist.linear.x =
466+
fabs(cmd_vel->twist.linear.x) < deadband_velocities_[0] ? 0.0 : cmd_vel->twist.linear.x;
467+
cmd_vel->twist.linear.y =
468+
fabs(cmd_vel->twist.linear.y) < deadband_velocities_[1] ? 0.0 : cmd_vel->twist.linear.y;
469+
cmd_vel->twist.linear.z = command_->twist.linear.z;
470+
cmd_vel->twist.angular.x = command_->twist.angular.x;
471+
cmd_vel->twist.angular.y = command_->twist.angular.y;
472+
cmd_vel->twist.angular.z =
473+
fabs(cmd_vel->twist.angular.z) < deadband_velocities_[2] ? 0.0 : cmd_vel->twist.angular.z;
474+
} else {
475+
cmd_vel->twist.linear.x =
476+
fabs(cmd_vel->twist.linear.x) < deadband_velocities_[0] ? 0.0 : cmd_vel->twist.linear.x;
477+
cmd_vel->twist.linear.y =
478+
fabs(cmd_vel->twist.linear.y) < deadband_velocities_[1] ? 0.0 : cmd_vel->twist.linear.y;
479+
cmd_vel->twist.linear.z =
480+
fabs(cmd_vel->twist.linear.z) < deadband_velocities_[2] ? 0.0 : cmd_vel->twist.linear.z;
481+
cmd_vel->twist.angular.x =
482+
fabs(cmd_vel->twist.angular.x) < deadband_velocities_[3] ? 0.0 : cmd_vel->twist.angular.x;
483+
cmd_vel->twist.angular.y =
484+
fabs(cmd_vel->twist.angular.y) < deadband_velocities_[4] ? 0.0 : cmd_vel->twist.angular.y;
485+
cmd_vel->twist.angular.z =
486+
fabs(cmd_vel->twist.angular.z) < deadband_velocities_[5] ? 0.0 : cmd_vel->twist.angular.z;
487+
}
389488
smoothed_cmd_pub_->publish(std::move(cmd_vel));
390489
}
391490

@@ -423,15 +522,16 @@ VelocitySmoother::dynamicParametersCallback(std::vector<rclcpp::Parameter> param
423522
shared_from_this(), odom_duration_, odom_topic_);
424523
}
425524
} else if (param_type == ParameterType::PARAMETER_DOUBLE_ARRAY) {
426-
if (parameter.as_double_array().size() != 3) {
427-
RCLCPP_WARN(get_logger(), "Invalid size of parameter %s. Must be size 3",
428-
param_name.c_str());
525+
size_t size = is_6dof_ ? 6 : 3;
526+
if (parameter.as_double_array().size() != size) {
527+
RCLCPP_WARN(get_logger(), "Invalid size of parameter %s. Must be size %ld",
528+
param_name.c_str(), size);
429529
result.successful = false;
430530
break;
431531
}
432532

433533
if (param_name == "max_velocity") {
434-
for (unsigned int i = 0; i != 3; i++) {
534+
for (unsigned int i = 0; i != size; i++) {
435535
if (parameter.as_double_array()[i] < 0.0) {
436536
RCLCPP_WARN(
437537
get_logger(),
@@ -443,7 +543,7 @@ VelocitySmoother::dynamicParametersCallback(std::vector<rclcpp::Parameter> param
443543
max_velocities_ = parameter.as_double_array();
444544
}
445545
} else if (param_name == "min_velocity") {
446-
for (unsigned int i = 0; i != 3; i++) {
546+
for (unsigned int i = 0; i != size; i++) {
447547
if (parameter.as_double_array()[i] > 0.0) {
448548
RCLCPP_WARN(
449549
get_logger(),
@@ -455,7 +555,7 @@ VelocitySmoother::dynamicParametersCallback(std::vector<rclcpp::Parameter> param
455555
min_velocities_ = parameter.as_double_array();
456556
}
457557
} else if (param_name == "max_accel") {
458-
for (unsigned int i = 0; i != 3; i++) {
558+
for (unsigned int i = 0; i != size; i++) {
459559
if (parameter.as_double_array()[i] < 0.0) {
460560
RCLCPP_WARN(
461561
get_logger(),
@@ -467,7 +567,7 @@ VelocitySmoother::dynamicParametersCallback(std::vector<rclcpp::Parameter> param
467567
max_accels_ = parameter.as_double_array();
468568
}
469569
} else if (param_name == "max_decel") {
470-
for (unsigned int i = 0; i != 3; i++) {
570+
for (unsigned int i = 0; i != size; i++) {
471571
if (parameter.as_double_array()[i] > 0.0) {
472572
RCLCPP_WARN(
473573
get_logger(),

0 commit comments

Comments
 (0)