How are Joint Limits enforced?


I am having trouble understanding how the joint limits from the URDF are enforced, specifically the velocity and effort limits. I am using the effort_controller/JointPositionController and from looking at the src code I can only see the position limits being enforced:

Where/how are the velocity and effort limits enforced when running the Gazebo simulation?

I am also trying to enforce the joint limits on my physical robot in my custom hardware interface. I have used the open_manipulator_controllers template from the ROS Control course:

However, it looks they have not added the joint_limit_interfaces to be able to enforce joint limits on the physical robot.
How should I go about doing this? I have looked through the course content, however there does not seem to be any description?

Thank you very much for the great content.

Kind regards,

Hello @volvo2,

You are right, this is not covered by the course as we thinks this is more for advanced users and it would be just too much material for students to cover.

When you create a controller, you have to inherit from one of these clases:

  • hardware_interface::EffortJointInterface
  • hardware_interface::VelocityJointInterface
  • hardware_interface::PositionJointInterface

To create a controller you must implement at least the update method of the base class. But there are other methods that you can implement, one of those methods is the enforceJointLimits method, one example is shown in the link that you included in your answer.

If you open that source code file, you will see that enforceJointLimits method is applied inside the update loop method. Therefore, when a command is sent that is outside of the robot joint limits, the enforceJointLimits method will just command the maximal allowed joint position and not the commanded position.

See here where enforceJointLimits method is applied inside the update loop method:

Basically Gazebo doesn’t do the enforcement of the joint limits, it is inside ros_control, when you send a command that is outside the joints limits the enforceJointLimits method will adapt that command to be inside the joint limits. So the command that Gazebo and/or the real robot receives is always inside the joint limits because of this.

Hope this makes it clearer.


PS: by the way, it is a very good practice to look for the source code and investigate how things are written there in code, well done!

Hi @rzegers
Thank you for the answer again!
It definitely cleared things up.
I also found out that, although the position limits are enforced inside the JointPositionController, the effort and velocity limits are enforced as part of the JointLimitsInterface. So, when running the simulated model in Gazebo the JointLimitsInterface is implemented when loading the ros_control_gazebo plugin that has the default hardware abstraction inherited from hardware_interface::RobotHWSim. The joint limits are enforced in the joint_limits_interface.h file.
However when creating the abstraction layer for a custom physical robot, I found out that I have to include the JointStateInterface manually in my hardware interface inherited from the hardware_interface::RobotHW class.

Yes, I have found out that looking through the src code helps alot…but it also take alot of time… :smiley:

Kind regards,

1 Like