Skip to content

Use new handles API in ros2_controllers to fix deprecation warnings #1566

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

Open
wants to merge 54 commits into
base: master
Choose a base branch
from

Conversation

kumar-sanjeeev
Copy link
Contributor

@kumar-sanjeeev kumar-sanjeeev commented Mar 3, 2025

This PR applies the new API changes in the handles of ros2_control in following controllers in same fashion as #1565:

  • ackermann_steering_controller
  • bicycle_steering_controller
  • admittance_controller
  • effort_controllers
  • forward_command_controller
  • gpio_controllers
  • gripper_controllers
  • mecanum_drive_controller
  • parallel_gripper_controller
  • tricycle_controller
  • pid_controller
  • tricycle_steering_controller
  • mecum_driver_contoller
  • force_torque_sensor_broadcaster
  • steering_controllers_library
  • joint_state_broadcaster
  • position_controllers
  • joint_trajectory_controller (partial fixed)
  • diff_drive_controller

Copy link
Contributor

@christophfroehlich christophfroehlich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine, thanks!

@kumar-sanjeeev
Copy link
Contributor Author

Looks fine, thanks!

@christophfroehlich hi, one question - I have made progress on other controllers as well locally on my system. Can I push these changes into this PR as well (will update description), or should I wait for more reviews on current submitted PR ?

@christophfroehlich
Copy link
Contributor

@saikishor ?

Copy link
Member

@saikishor saikishor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes already look good to me. I just forgot to comment.
@kumar-sanjeeev yes, please proceed with other packages as well

@kumar-sanjeeev
Copy link
Contributor Author

@saikishor and @christophfroehlich , one question, would you like me to complete all the controller packages first, and then you would review them of all together? Or would you prefer to first provide feedback on the commits that have already been pushed in this PR?

@christophfroehlich
Copy link
Contributor

apply the changes to all of them please

@saikishor
Copy link
Member

Yes please

Copy link
Contributor Author

@kumar-sanjeeev kumar-sanjeeev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comments, and sorry for the late reply.

what should we do if setting a command fails? return or try to set the other commands? This is not consistent

In the current implementation, it always returns with a message. In some cases, I am setting the value to 0.0 but still returning with a message.

for filling the publisher with data: I'd suggest to resume and just leave the message field untouched (should be the old vale then if the msg struct is pre-allocated). what do you think?

Could you please explain this point with an example? I’m not able to understand the message clearly.

  • I have marked some conversations as resolved, but for few others, I need guidance.

@christophfroehlich
Copy link
Contributor

for filling the publisher with data: I'd suggest to resume and just leave the message field untouched (should be the old vale then if the msg struct is pre-allocated). what do you think?

Could you please explain this point with an example? I’m not able to understand the message clearly.

For example here:

state_publisher_->msg_.dof_states[i].output = command_interfaces_[i].get_value();

The value is saved in state_publisher_->msg_ unless its overridden. If the get_value() fails, don't return here but just leave this message field untouched and proceed.

@kumar-sanjeeev
Copy link
Contributor Author

for filling the publisher with data: I'd suggest to resume and just leave the message field untouched (should be the old vale then if the msg struct is pre-allocated). what do you think?

Could you please explain this point with an example? I’m not able to understand the message clearly.

For example here:

state_publisher_->msg_.dof_states[i].output = command_interfaces_[i].get_value();

The value is saved in state_publisher_->msg_ unless its overridden. If the get_value() fails, don't return here but just leave this message field untouched and proceed.

If I understood correctly, this approach i.e., not return when get_value() fails, is only meant to be used in cases where the message structure is pre-allocated (for example, in a publisher). Am I right?

If yes, then in such cases, can I proceed with the following fix? Or should I also skip printing any warning or debug message?

      state_publisher_->msg_.dof_states[i].time_step = period.seconds();
      // Command can store the old calculated values. This should be obvious because at least one
      // another value is NaN.
      const auto command_interface_value_op = command_interfaces_[i].get_optional();

      if (!command_interface_value_op.has_value())
      {
        RCLCPP_DEBUG(
          get_node()->get_logger(), "Unable to retrieve the command interface value for %s",
          command_interfaces_[i].get_name().c_str());
          # removed return statement

      }

      state_publisher_->msg_.dof_states[i].output = command_interface_value_op.value();
    }

@christophfroehlich
Copy link
Contributor

The value is saved in state_publisher_->msg_ unless its overridden. If the get_value() fails, don't return here but just leave this message field untouched and proceed.

If I understood correctly, this approach i.e., not return when get_value() fails, is only meant to be used in cases where the message structure is pre-allocated (for example, in a publisher). Am I right?

Exactly!

If yes, then in such cases, can I proceed with the following fix? Or should I also skip printing any warning or debug message?

      state_publisher_->msg_.dof_states[i].time_step = period.seconds();
      // Command can store the old calculated values. This should be obvious because at least one
      // another value is NaN.
      const auto command_interface_value_op = command_interfaces_[i].get_optional();

      if (!command_interface_value_op.has_value())
      {
        RCLCPP_DEBUG(
          get_node()->get_logger(), "Unable to retrieve the command interface value for %s",
          command_interfaces_[i].get_name().c_str());
          # removed return statement

      }

      state_publisher_->msg_.dof_states[i].output = command_interface_value_op.value();
    }

A debug message is fine, but I'd suggest no higher log level.

@kumar-sanjeeev
Copy link
Contributor Author

The value is saved in state_publisher_->msg_ unless its overridden. If the get_value() fails, don't return here but just leave this message field untouched and proceed.

If I understood correctly, this approach i.e., not return when get_value() fails, is only meant to be used in cases where the message structure is pre-allocated (for example, in a publisher). Am I right?

Exactly!

If yes, then in such cases, can I proceed with the following fix? Or should I also skip printing any warning or debug message?

      state_publisher_->msg_.dof_states[i].time_step = period.seconds();
      // Command can store the old calculated values. This should be obvious because at least one
      // another value is NaN.
      const auto command_interface_value_op = command_interfaces_[i].get_optional();

      if (!command_interface_value_op.has_value())
      {
        RCLCPP_DEBUG(
          get_node()->get_logger(), "Unable to retrieve the command interface value for %s",
          command_interfaces_[i].get_name().c_str());
          # removed return statement

      }

      state_publisher_->msg_.dof_states[i].output = command_interface_value_op.value();
    }

A debug message is fine, but I'd suggest no higher log level.

thanks for explanation, I understood. I will make correction where it needs to be done.

@kumar-sanjeeev
Copy link
Contributor Author

Thanks for your comments, and sorry for the late reply.

what should we do if setting a command fails? return or try to set the other commands? This is not consistent

In the current implementation, it always returns with a message. In some cases, I am setting the value to 0.0 but still returning with a message.

@christophfroehlich does my reply answer your question? In addition to my given answer, I have set the value to 0.0 in cases where it had already been done, before I made the modification for the deprecation fix.

@christophfroehlich
Copy link
Contributor

In the current implementation, it always returns with a message. In some cases, I am setting the value to 0.0 but still returning with a message.

@christophfroehlich does my reply answer your question? In addition to my given answer, I have set the value to 0.0 in cases where it had already been done, before I made the modification for the deprecation fix.

In these cases, it makes sense

@saikishor
Copy link
Member

saikishor commented Jun 10, 2025

Hello @kumar-sanjeeev

In the current implementation, it always returns with a message. In some cases, I am setting the value to 0.0 but still returning with a message.

In what cases are you setting the value to 0.0?. Can you please point me to the code?

If I understood correctly, this approach i.e., not return when get_value() fails, is only meant to be used in cases where the message structure is pre-allocated (for example, in a publisher). Am I right?

If yes, then in such cases, can I proceed with the following fix? Or should I also skip printing any warning or debug message?

Exactly, this part is perfect.

@kumar-sanjeeev
Copy link
Contributor Author

Hello @kumar-sanjeeev

In the current implementation, it always returns with a message. In some cases, I am setting the value to 0.0 but still returning with a message.

In what cases are you setting the value to 0.0?. Can you please point me to the code?

Hello @saikishor , I have put comments where I have set value to 0.0. Let me know your thoughts.

@saikishor
Copy link
Member

Hello @saikishor , I have put comments where I have set value to 0.0. Let me know your thoughts.

Thank you LGTM

command_interfaces_map_.at(full_command_interface_name)
.get()
.set_value(gpio_commands.interface_values[gpio_index].values[command_interface_index]);
if (!command_interfaces_map_.at(full_command_interface_name).get().set_value(command_value))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's okay

Comment on lines +416 to +417
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
}
else
{

here you will continue and access .value(). Here you will need a else statement

Comment on lines +419 to 420
state_msg_interface_value_op.value();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
state_msg_interface_value_op.value();
}
state_msg_interface_value_op.value();
}
}

{
RCLCPP_DEBUG(get_node()->get_logger(), "Unable to retrieve data of joint position");
}
command_struct_.position_cmd_ = position_op.value();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::unique_lock<std::shared_mutex> lock(handle->get_mutex());
std::ignore = handle->set_value(lock, value);

Something like this

RCLCPP_DEBUG(
get_node()->get_logger(), "Unable to retrieve the state interface value for %s",
state_interfaces_[i].get_name().c_str());
return controller_interface::return_type::OK;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants