Skip to content

Commit e188bf9

Browse files
Fix DiffDrive claiming state when open_loop is set (#1730)
1 parent fa4f95b commit e188bf9

File tree

4 files changed

+103
-20
lines changed

4 files changed

+103
-20
lines changed

diff_drive_controller/doc/userdoc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Feedback
4141
,,,,,,,,,,,,,,
4242

4343
As feedback interface type the joints' position (``hardware_interface::HW_IF_POSITION``) or velocity (``hardware_interface::HW_IF_VELOCITY``,if parameter ``position_feedback=false``) are used.
44+
Unless the parameter ``open_loop=true`` is set, then no external state interfaces are used (the commanded velocity is used for odometry instead).
4445

4546
Output
4647
,,,,,,,,,

diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class DiffDriveController : public controller_interface::ChainableControllerInte
8383

8484
struct WheelHandle
8585
{
86-
std::reference_wrapper<const hardware_interface::LoanedStateInterface> feedback;
86+
std::optional<std::reference_wrapper<const hardware_interface::LoanedStateInterface>> feedback;
8787
std::reference_wrapper<hardware_interface::LoanedCommandInterface> velocity;
8888
};
8989

diff_drive_controller/src/diff_drive_controller.cpp

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ InterfaceConfiguration DiffDriveController::command_interface_configuration() co
8585

8686
InterfaceConfiguration DiffDriveController::state_interface_configuration() const
8787
{
88+
if (params_.open_loop)
89+
{
90+
return {interface_configuration_type::NONE, {}};
91+
}
92+
8893
std::vector<std::string> conf_names;
8994
for (const auto & joint_name : params_.left_wheel_names)
9095
{
@@ -168,9 +173,9 @@ controller_interface::return_type DiffDriveController::update_and_write_commands
168173
for (size_t index = 0; index < static_cast<size_t>(wheels_per_side_); ++index)
169174
{
170175
const auto left_feedback_op =
171-
registered_left_wheel_handles_[index].feedback.get().get_optional();
176+
registered_left_wheel_handles_[index].feedback.value().get().get_optional();
172177
const auto right_feedback_op =
173-
registered_right_wheel_handles_[index].feedback.get().get_optional();
178+
registered_right_wheel_handles_[index].feedback.value().get().get_optional();
174179

175180
if (!left_feedback_op.has_value() || !right_feedback_op.has_value())
176181
{
@@ -667,21 +672,6 @@ controller_interface::CallbackReturn DiffDriveController::configure_side(
667672
registered_handles.reserve(wheel_names.size());
668673
for (const auto & wheel_name : wheel_names)
669674
{
670-
const auto interface_name = feedback_type();
671-
const auto state_handle = std::find_if(
672-
state_interfaces_.cbegin(), state_interfaces_.cend(),
673-
[&wheel_name, &interface_name](const auto & interface)
674-
{
675-
return interface.get_prefix_name() == wheel_name &&
676-
interface.get_interface_name() == interface_name;
677-
});
678-
679-
if (state_handle == state_interfaces_.cend())
680-
{
681-
RCLCPP_ERROR(logger, "Unable to obtain joint state handle for %s", wheel_name.c_str());
682-
return controller_interface::CallbackReturn::ERROR;
683-
}
684-
685675
const auto command_handle = std::find_if(
686676
command_interfaces_.begin(), command_interfaces_.end(),
687677
[&wheel_name](const auto & interface)
@@ -696,8 +686,30 @@ controller_interface::CallbackReturn DiffDriveController::configure_side(
696686
return controller_interface::CallbackReturn::ERROR;
697687
}
698688

699-
registered_handles.emplace_back(
700-
WheelHandle{std::ref(*state_handle), std::ref(*command_handle)});
689+
if (params_.open_loop)
690+
{
691+
registered_handles.emplace_back(WheelHandle{std::nullopt, std::ref(*command_handle)});
692+
}
693+
else
694+
{
695+
const auto interface_name = feedback_type();
696+
const auto state_handle = std::find_if(
697+
state_interfaces_.cbegin(), state_interfaces_.cend(),
698+
[&wheel_name, &interface_name](const auto & interface)
699+
{
700+
return interface.get_prefix_name() == wheel_name &&
701+
interface.get_interface_name() == interface_name;
702+
});
703+
704+
if (state_handle == state_interfaces_.cend())
705+
{
706+
RCLCPP_ERROR(logger, "Unable to obtain joint state handle for %s", wheel_name.c_str());
707+
return controller_interface::CallbackReturn::ERROR;
708+
}
709+
710+
registered_handles.emplace_back(
711+
WheelHandle{{std::ref(*state_handle)}, std::ref(*command_handle)});
712+
}
701713
}
702714

703715
return controller_interface::CallbackReturn::SUCCESS;

diff_drive_controller/test/test_diff_drive_controller.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,15 @@ class TestDiffDriveController : public ::testing::Test
175175
controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs));
176176
}
177177

178+
void assignResourcesNoFeedback()
179+
{
180+
std::vector<LoanedCommandInterface> command_ifs;
181+
command_ifs.emplace_back(left_wheel_vel_cmd_);
182+
command_ifs.emplace_back(right_wheel_vel_cmd_);
183+
184+
controller_->assign_interfaces(std::move(command_ifs), {});
185+
}
186+
178187
controller_interface::return_type InitController(
179188
const std::vector<std::string> left_wheel_joints_init = left_wheel_names,
180189
const std::vector<std::string> right_wheel_joints_init = right_wheel_names,
@@ -262,6 +271,26 @@ TEST_F(
262271
EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL);
263272
}
264273

274+
TEST_F(
275+
TestDiffDriveController,
276+
command_and_state_interface_configuration_succeeds_when_wheels_and_open_loop_are_specified)
277+
{
278+
ASSERT_EQ(
279+
InitController(
280+
left_wheel_names, right_wheel_names,
281+
{rclcpp::Parameter("open_loop", rclcpp::ParameterValue(true))}),
282+
controller_interface::return_type::OK);
283+
284+
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS);
285+
286+
auto state_if_conf = controller_->state_interface_configuration();
287+
ASSERT_THAT(state_if_conf.names, SizeIs(0));
288+
EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE);
289+
auto cmd_if_conf = controller_->command_interface_configuration();
290+
ASSERT_THAT(cmd_if_conf.names, SizeIs(left_wheel_names.size() + right_wheel_names.size()));
291+
EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL);
292+
}
293+
265294
TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_namespace)
266295
{
267296
std::string odom_id = "odom";
@@ -458,6 +487,19 @@ TEST_F(TestDiffDriveController, activate_succeeds_with_vel_resources_assigned)
458487
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS);
459488
}
460489

490+
TEST_F(TestDiffDriveController, activate_succeeds_with_open_loop_assigned)
491+
{
492+
ASSERT_EQ(
493+
InitController(
494+
left_wheel_names, right_wheel_names,
495+
{rclcpp::Parameter("open_loop", rclcpp::ParameterValue(true))}),
496+
controller_interface::return_type::OK);
497+
498+
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS);
499+
assignResourcesNoFeedback();
500+
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS);
501+
}
502+
461503
TEST_F(TestDiffDriveController, test_speed_limiter)
462504
{
463505
// If you send a linear velocity command without acceleration limits,
@@ -690,6 +732,34 @@ TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_2)
690732
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::ERROR);
691733
}
692734

735+
TEST_F(TestDiffDriveController, activate_silently_ignores_with_unnecessary_resources_assigned_1)
736+
{
737+
ASSERT_EQ(
738+
InitController(
739+
left_wheel_names, right_wheel_names,
740+
{rclcpp::Parameter("open_loop", rclcpp::ParameterValue(true)),
741+
rclcpp::Parameter("position_feedback", rclcpp::ParameterValue(false))}),
742+
controller_interface::return_type::OK);
743+
744+
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS);
745+
assignResourcesPosFeedback();
746+
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS);
747+
}
748+
749+
TEST_F(TestDiffDriveController, activate_silently_ignores_with_unnecessary_resources_assigned_2)
750+
{
751+
ASSERT_EQ(
752+
InitController(
753+
left_wheel_names, right_wheel_names,
754+
{rclcpp::Parameter("open_loop", rclcpp::ParameterValue(true)),
755+
rclcpp::Parameter("position_feedback", rclcpp::ParameterValue(true))}),
756+
controller_interface::return_type::OK);
757+
758+
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS);
759+
assignResourcesVelFeedback();
760+
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS);
761+
}
762+
693763
TEST_F(TestDiffDriveController, cleanup)
694764
{
695765
ASSERT_EQ(

0 commit comments

Comments
 (0)