0
$\begingroup$

Rosanswers logo

I am trying to connect my robot with actuators. I am using MoveIt and ros_control. My controller is of type position_controllers/JointTrajectoryController. My actuators need velocities. If I check the "/joint_controller/state" topic I can see 3 different types of values: desired, actual and error.

When I issue a trajectory, the desired joint values for position, velocity and acceleration are automatically computed. So from this I assumed that I could simply use these computed desired velocities to command my actuators. So I implemented my own hardware interface with a JointStateInterface, PositionJointInterface and VelocityJointInterface.

In the read/write loop of the hardware interface I see that if I change the position array registered with the JointStateInterface the "actual.positions" value in the "/joint_controller/state" topic changes accordingly, so that works well.

If I read the position_cmd array registered with the PositionJointInterface I see that it corresponds to the "desired.positions" value in the "/joint_controller/state" topic, so that also works as I expected.

But when I read the velocity_cmd array registered with the VelocityJointInterface, all the values are always 0. I thought I could read the "desired.velocities" value from this interface but it seems I was wrong. I guess it has something to do with how I am using position_controllers, but then where are these "desired.velocities" coming from? How are they being calculated and how can I make use of them within my hardware interface? I know I could simply subscribe to the "/joint_controller/state" topic and access the "desired.velocities" value from there but that doesn't feel like the right way of doing this.


Originally posted by willemstuijt on ROS Answers with karma: 42 on 2022-01-12

Post score: 0

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

You seem to misunderstand how hardware_interface::RobotHW is designed to work. With ros_control, the user chooses one of many different JointControllers to sit on top of the RobotHW software layer. A "position_controller" will write a position goal to RobotHW, a "velocity_controller" will write a velocity goal to RobotHW, etc. The RobotHW layer gets to choose which types of JointControllers it wants to support.

For RobotHW, in the typical case, the "write a command goal" and the "read joint state from sensor" parts of the code are completely independent of each other. The standard higher-level software layers of ros_control will send commands down to RobotHW to resolve any error between the joint goal and the current joint state; the author of RobotHW is not responsible for handling this.

But when I try to access the desired values only the position_cmd gets updated on my hardware interface,

This is expected since you have a position_controller sitting on top of RobotHW.


Originally posted by Mike Scheutzow with karma: 4903 on 2022-01-13

This answer was ACCEPTED on the original site

Post score: 2


Original comments

Comment by gvdhoorn on 2022-01-13:
In addition to what Mike writes here, I noticed this:

My actuators need velocities

if that's the case, then I'm wondering why any position interfaces have been registered -- unless the actuators support both position and velocity control modes. If the latter, the type of controller would indeed determine which type of actuation signals your RobotHW will receive.

Note that there is also support for PosVelJointInterface, which would be used for joints which require both a position and a velocity.

And to clarify:

My controller is of type position_controllers/JointTrajectoryController.

this is a JointTrajectoryController which outputs position commands.

The velocity_controllers/JointTrajectoryController is the same JointTrajectoryController, but this one only outputs velocity commands.

(and for completeness: there is also a pos_vel_controllers variant, and some closed-loop versions)

Comment by willemstuijt on 2022-01-13:
Yes I also think I misunderstand how hardware_interface works. I think the documentation is not really beginner friendly. Anyways.

I also thought I was just going to get position commands since I was just using position_controllers. What confuses me the most is the values I get from "desired.velocities" in the controller state topic. ros_control seems to be calculating some desired velocities. Where are these velocities coming from? And how do I access these?

I updated my question a little bit to provide better context.

Comment by willemstuijt on 2022-01-13:
@gvdhoorn I thought MoveIt was only meant to be used with position_controllers/JointTrajectoryController. I tried getting velocity controllers to work with MoveIt but I was unable to.

Comment by gvdhoorn on 2022-01-13:\

I also thought I was just going to get position commands since I was just using position_controllers.

well, you are, aren't you? You write yourself:

If I read the position_cmd array registered with the PositionJointInterface I see that it corresponds to the "desired.positions" value in the "/joint_controller/state" topic

The values you find in the state topic are for debugging only. They provide insight into internal state of the JointTrajectoryController. The 'type' of the controller determines what it will output to your hw iface.

if you register both position and velocity interfaces, you can run either position or velocity based controllers on top of your hw iface. But position controllers are not going to give you velocity commands (as you already observed).

If in fact, you only require / support velocity commands, remove the position interface from your hw iface, and load the velocity_controllers/JointTrajectoryController.

Comment by gvdhoorn on 2022-01-13:\

I thought MoveIt was only meant to be used with position_controllers/JointTrajectoryController. I tried getting velocity controllers to work with MoveIt but I was unable to.

MoveIt is not involved here.

MoveIt controllers != ros_control controllers.

All variants of the JointTrajectoryController expose a FollowJointTrajectoryAction interface, which is what MoveIt can use.

Changing your ros_control configuration does not need updates on the MoveIt side (in this case).

I tried getting velocity controllers to work with MoveIt but I was unable to.

you may be confusing input with output.

MoveIt cannot generate "velocity trajectories" for you, so you cannot use a ros_control controller which only takes velocity input.

MoveIt can generate trajectories with positions for you, so you pass those to a controller which accepts position inputs.

MoveIt doesn't care whether that position controller then outputs positions, velocities or something else.

Comment by willemstuijt on 2022-01-13:
Thanks. I managed to get it working. My head was all over the place with Gazebo, ros_control, MoveIt. I think I finally understand how everything comes together (kind off).

Comment by gvdhoorn on 2022-01-13:
So what was the solution in the end?

Comment by willemstuijt on 2022-01-13:
I switched to velocity_controllers/JointTrajectoryController. I had to make sure to add pid gain values for the controller configuration which the gazebo controller didn't previously need. Embarassingly simple to fix haha. It just confused me why, despite using position_controllers, I could still see desired velocities being calculated. But now I think I understand.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.