Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Admittance] multiple state/command interfaces #1196

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
10ad1c3
fix: read/writes all configured state/command interfaces. Adjust stat…
MarcoMagriDev Jul 6, 2024
f427c4d
fix: uses correct `has` flags in read/write methods
MarcoMagriDev Jul 6, 2024
7ac93f6
fix: makes position state interface mandatory, adds compatibility wit…
MarcoMagriDev Jul 6, 2024
ba1a3a1
Merge branch 'ros-controls:master' into fix-state-and-command-interfaces
MarcoMagriDev Feb 4, 2025
d53d437
Merge branch 'master' into fix-state-and-command-interfaces
saikishor Feb 4, 2025
b400407
fix: adds missing `pos_ind +`
MarcoMagriDev Feb 4, 2025
0d091d2
Merge branch 'master' into fix-state-and-command-interfaces
christophfroehlich Feb 4, 2025
7cf2a24
Merge branch 'ros-controls:master' into fix-state-and-command-interfaces
MarcoMagriDev Feb 11, 2025
b1fd7a9
AdmittanceController: adds tests to check
MarcoMagriDev Feb 11, 2025
e13863c
AdmittanceController: allow to export position and velocity reference…
MarcoMagriDev Feb 11, 2025
d651d88
AdmittanceController: fixes default value of `chainable_command_inter…
MarcoMagriDev Feb 12, 2025
9ec6c16
Merge branch 'master' into fix-state-and-command-interfaces
christophfroehlich Feb 12, 2025
1fc99c4
AdmittanceController: removes `chainable_command_interfaces` from tes…
MarcoMagriDev Feb 13, 2025
7857648
Merge branch 'master' into fix-state-and-command-interfaces
MarcoMagriDev Feb 13, 2025
ab13dc3
Merge branch 'master' into fix-state-and-command-interfaces
christophfroehlich Feb 13, 2025
2cd71e1
Merge branch 'master' into fix-state-and-command-interfaces
christophfroehlich Feb 14, 2025
0bd3fdf
Merge branch 'master' into fix-state-and-command-interfaces
christophfroehlich Feb 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,6 @@ class AdmittanceController : public controller_interface::ChainableControllerInt
hardware_interface::HW_IF_ACCELERATION};

// internal reference values
const std::vector<std::string> allowed_reference_interfaces_types_ = {
hardware_interface::HW_IF_POSITION, hardware_interface::HW_IF_VELOCITY};
std::vector<std::reference_wrapper<double>> position_reference_;
std::vector<std::reference_wrapper<double>> velocity_reference_;

Expand Down
74 changes: 52 additions & 22 deletions admittance_controller/src/admittance_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ AdmittanceController::on_export_reference_interfaces()

// assign reference interfaces
auto index = 0ul;
for (const auto & interface : allowed_reference_interfaces_types_)
for (const auto & interface : admittance_->parameters_.chainable_command_interfaces)
{
for (const auto & joint : admittance_->parameters_.joints)
{
Expand Down Expand Up @@ -258,6 +258,12 @@ controller_interface::CallbackReturn AdmittanceController::on_configure(
has_acceleration_state_interface_ = contains_interface_type(
admittance_->parameters_.state_interfaces, hardware_interface::HW_IF_ACCELERATION);

if (!has_position_state_interface_)
{
RCLCPP_ERROR(get_node()->get_logger(), "Position state interface is required.");
return CallbackReturn::FAILURE;
}

auto get_interface_list = [](const std::vector<std::string> & interface_types)
{
std::stringstream ss_command_interfaces;
Expand Down Expand Up @@ -406,13 +412,22 @@ controller_interface::return_type AdmittanceController::update_reference_from_su
// if message exists, load values into references
if (joint_command_msg_.get())
{
for (size_t i = 0; i < joint_command_msg_->positions.size(); ++i)
for (const auto & interface : admittance_->parameters_.chainable_command_interfaces)
{
position_reference_[i].get() = joint_command_msg_->positions[i];
}
for (size_t i = 0; i < joint_command_msg_->velocities.size(); ++i)
{
velocity_reference_[i].get() = joint_command_msg_->velocities[i];
if (interface == hardware_interface::HW_IF_POSITION)
{
for (size_t i = 0; i < joint_command_msg_->positions.size(); ++i)
{
position_reference_[i].get() = joint_command_msg_->positions[i];
}
}
else if (interface == hardware_interface::HW_IF_VELOCITY)
{
for (size_t i = 0; i < joint_command_msg_->velocities.size(); ++i)
{
velocity_reference_[i].get() = joint_command_msg_->velocities[i];
}
}
}
}

Expand Down Expand Up @@ -464,8 +479,13 @@ controller_interface::CallbackReturn AdmittanceController::on_deactivate(
// reset to prevent stale references
for (size_t i = 0; i < num_joints_; i++)
{
position_reference_[i].get() = std::numeric_limits<double>::quiet_NaN();
velocity_reference_[i].get() = std::numeric_limits<double>::quiet_NaN();
for (const auto & interface : admittance_->parameters_.chainable_command_interfaces)
{
if (interface == hardware_interface::HW_IF_POSITION)
position_reference_[i].get() = std::numeric_limits<double>::quiet_NaN();
else if (interface == hardware_interface::HW_IF_VELOCITY)
velocity_reference_[i].get() = std::numeric_limits<double>::quiet_NaN();
}
}

for (size_t index = 0; index < allowed_interface_types_.size(); ++index)
Expand Down Expand Up @@ -500,7 +520,7 @@ void AdmittanceController::read_state_from_hardware(
bool nan_acceleration = false;

size_t pos_ind = 0;
size_t vel_ind = pos_ind + has_velocity_command_interface_;
size_t vel_ind = pos_ind + has_velocity_state_interface_;
size_t acc_ind = vel_ind + has_acceleration_state_interface_;
for (size_t joint_ind = 0; joint_ind < num_joints_; ++joint_ind)
{
Expand Down Expand Up @@ -553,8 +573,9 @@ void AdmittanceController::write_state_to_hardware(
{
// if any interface has nan values, assume state_commanded is the last command state
size_t pos_ind = 0;
size_t vel_ind = pos_ind + has_velocity_command_interface_;
size_t acc_ind = vel_ind + has_acceleration_state_interface_;
size_t vel_ind =
(has_position_command_interface_) ? pos_ind + has_velocity_command_interface_ : pos_ind;
size_t acc_ind = vel_ind + has_acceleration_command_interface_;
for (size_t joint_ind = 0; joint_ind < num_joints_; ++joint_ind)
{
if (has_position_command_interface_)
Expand Down Expand Up @@ -584,19 +605,28 @@ void AdmittanceController::read_state_reference_interfaces(
// if any interface has nan values, assume state_reference is the last set reference
for (size_t i = 0; i < num_joints_; ++i)
{
// update position
if (std::isnan(position_reference_[i]))
for (const auto & interface : admittance_->parameters_.chainable_command_interfaces)
{
position_reference_[i].get() = last_reference_.positions[i];
}
state_reference.positions[i] = position_reference_[i];
// update position
if (interface == hardware_interface::HW_IF_POSITION)
{
if (std::isnan(position_reference_[i]))
{
position_reference_[i].get() = last_reference_.positions[i];
}
state_reference.positions[i] = position_reference_[i];
}

// update velocity
if (std::isnan(velocity_reference_[i]))
{
velocity_reference_[i].get() = last_reference_.velocities[i];
// update velocity
if (interface == hardware_interface::HW_IF_VELOCITY)
{
if (std::isnan(velocity_reference_[i]))
{
velocity_reference_[i].get() = last_reference_.velocities[i];
}
state_reference.velocities[i] = velocity_reference_[i];
}
}
state_reference.velocities[i] = velocity_reference_[i];
}

last_reference_.positions = state_reference.positions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ admittance_controller:
chainable_command_interfaces:
{
type: string_array,
default_value: ["position", "velocity"],
description: "Specifies which reference interfaces the controller will export. Normally, the position and velocity are used.",
read_only: true
}
Expand Down
48 changes: 45 additions & 3 deletions admittance_controller/test/test_admittance_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ TEST_P(AdmittanceControllerTestParameterizedMissingParameters, one_init_paramete
INSTANTIATE_TEST_SUITE_P(
MissingMandatoryParameterDuringInit, AdmittanceControllerTestParameterizedMissingParameters,
::testing::Values(
"admittance.mass", "admittance.selected_axes", "admittance.stiffness",
"chainable_command_interfaces", "command_interfaces", "control.frame.id",
"fixed_world_frame.frame.id", "ft_sensor.frame.id", "ft_sensor.name",
"admittance.mass", "admittance.selected_axes", "admittance.stiffness", "command_interfaces",
"control.frame.id", "fixed_world_frame.frame.id", "ft_sensor.frame.id", "ft_sensor.name",
"gravity_compensation.CoG.pos", "gravity_compensation.frame.id", "joints", "kinematics.base",
"kinematics.plugin_name", "kinematics.plugin_package", "kinematics.tip", "state_interfaces"));

Expand Down Expand Up @@ -201,6 +200,49 @@ TEST_F(AdmittanceControllerTest, activate_success)
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS);
}

TEST_F(AdmittanceControllerTest, missing_pos_state_interface)
{
auto overrides = {rclcpp::Parameter("state_interfaces", std::vector<std::string>{"velocity"})};
SetUpController("test_admittance_controller", overrides);
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_FAILURE);
}

TEST_F(AdmittanceControllerTest, only_vel_command_interface)
{
command_interface_types_ = {"velocity"};
auto overrides = {rclcpp::Parameter("command_interfaces", std::vector<std::string>{"velocity"})};
SetUpController("test_admittance_controller", overrides);
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS);
ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS);
ASSERT_EQ(
controller_->update_and_write_commands(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)),
controller_interface::return_type::OK);
}

TEST_F(AdmittanceControllerTest, only_pos_reference_interface)
{
auto overrides = {
rclcpp::Parameter("chainable_command_interfaces", std::vector<std::string>{"position"})};
SetUpController("test_admittance_controller", overrides);
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS);
}

TEST_F(AdmittanceControllerTest, only_vel_reference_interface)
{
auto overrides = {
rclcpp::Parameter("chainable_command_interfaces", std::vector<std::string>{"velocity"})};
SetUpController("test_admittance_controller", overrides);
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS);
}

TEST_F(AdmittanceControllerTest, invalid_reference_interface)
{
auto overrides = {rclcpp::Parameter(
"chainable_command_interfaces", std::vector<std::string>{"invalid_interface"})};
SetUpController("test_admittance_controller", overrides);
ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR);
}

TEST_F(AdmittanceControllerTest, update_success)
{
SetUpController();
Expand Down
2 changes: 1 addition & 1 deletion admittance_controller/test/test_admittance_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ class AdmittanceControllerTest : public ::testing::Test
// Controller-related parameters
const std::vector<std::string> joint_names_ = {"joint1", "joint2", "joint3",
"joint4", "joint5", "joint6"};
const std::vector<std::string> command_interface_types_ = {"position"};
std::vector<std::string> command_interface_types_ = {"position"};
const std::vector<std::string> state_interface_types_ = {"position"};
const std::string ft_sensor_name_ = "ft_sensor_name";

Expand Down