How to setup diff_drive_controller to make it work with ros_control's velocity_controllers?
Hello, I'm quite confused with how to setup ros_control
's velocity/position PID controllers source in a differential drive robot with diff_drive_controller
wiki.
Here are some ambiguities on conceptual level with some code snippets to make everything clearer. It is somehow related to #249435, but I think that these examples with some answers will greatly help other beginners to find some info on configuration diff_drive_controller
package, because besides some very general examples I couldn't find much info how to set it up properly. Hence this question.
What I did so far
I've already passed 2 joints of my robot (defined in URDF) to diff_drive_controller
. Controller takes cmd_vel commands quite well. The problem is that when I'm sending linear.x = 0.3 m/s, angular.z = 0.0 rad/s
command, it doesn't drive exactly forward. Another thing is that when I send linear.x = 0.1 m/s
it couldn't overcome friction and is standing still.
Here is a part of the controller_common.yaml
(diff drive controller params) file content:
mobile_base_controller:
enable_odom_tf: true
odom_frame_id: odom
publish_cmd: true
type: diff_drive_controller/DiffDriveController
left_wheel: wheel_0_joint
right_wheel: wheel_1_joint
# and so on, it works straight ahead so I won't paste whole file, params set are listed on wiki page
Here is control.yaml
file's content - 2 velocity controllers I can't make working:
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 50
left_wheel_velocity_controller:
type: velocity_controllers/JointVelocityController
joint: wheel_0_joint # base_to_0_wheel
pid: {p: 00.1, i: 0.00001, d: 0.0001}
right_wheel_velocity_controller:
type: velocity_controllers/JointVelocityController
joint: wheel_1_joint # base_to_1_wheel
pid: {p: 100.0, i: 0.1, d: 10.0}
and here is .launch
file's content:
<rosparam command="load" file="$(find diff_drive_mapping_robot)/config/control.yaml" />
<rosparam command="load" file="$(find diff_drive_mapping_robot)/config/controller_common.yaml" />
<node name="base_controller_spawner" pkg="controller_manager" type="spawner" output="screen" args="mobile_base_controller" />
<node name="joint_controllers_spawner" pkg="controller_manager" type="spawner" respawn="false"
output="screen" args="joint_state_controller
left_wheel_velocity_controller
right_wheel_velocity_controller" >
</node>
<node name="controller_manager_node" pkg="diff_drive_mapping_robot" type="controller_manager_node" output="screen" />
My robot's hardware_interfaces are defined and registered exactly as shown here
I also updated my robot_description
(stored on Parameter Server) to extend joint description with hardware_interface
<!-- =============== WHEEL_LEFT ===============-->
<link name="wheel_0_joint">
<visual>
<geometry>
<cylinder length="0.027" radius="0.03315"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="black">
<color rgba="0 0 0 1"/>
</material>
</visual>
</link>
<joint name="base_to_0_wheel" type="fixed">
<parent link="base_link"/>
<child link="wheel_0_joint"/>
<origin xyz="0 0.0955 0.03315" rpy="1.5708 0 0"/>
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface> <!-- please notice -->
</joint>
<!-- =============== WHEEL_RIGHT ===============-->
<link name="wheel_1_joint">
<visual>
<geometry>
<cylinder length="0.027" radius="0.03315"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="black">
<color rgba="0 0 0 1"/>
</material>
</visual>
</link>
<joint name="base_to_1_wheel" type="fixed">
<parent link="base_link"/>
<child link="wheel_1_joint"/>
<origin xyz="0 -0.0955 0.03315" rpy="1.5708 0 0"/>
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface> <!-- please notice -->
</joint>
Now, with the same joints (same names) for diff drive controller and listed velocity controllers I get this error after starting .launch file:
[ WARN] [1527380810.421256974]: Resource conflict on [wheel_0_joint]. Controllers = [left_wheel_velocity_controller, mobile_base_controller, ]
[ WARN] [1527380810.421355205]: Resource conflict on [wheel_1_joint]. Controllers = [mobile_base_controller, right_wheel_velocity_controller, ]
[ERROR] [1527380810.421450132]: Could not switch controllers, due to resource conflict
[INFO] [1527380810.422338]: Started controllers: mobile_base_controller
When I create 2 extra instances to register interfaces (in the same manner as here ) like this:
for (unsigned int i = 0; i < NUM_JOINTS; ++i)
{
std::ostringstream os;
os << "wheel_" << i << "_joint";
std::ostringstream os_ctrl;
os_ctrl << "base_to_" << i << "_wheel";
hardware_interface::JointStateHandle state_handle(os.str(), &pos[i], &vel[i], &eff[i]);
jnt_state_interface.registerHandle(state_handle);
hardware_interface::JointStateHandle state_handle_urdf(os_ctrl.str(), &pos_ctrl[i], &vel_ctrl[i], &eff_ctrl[i]);
jnt_state_interface.registerHandle(state_handle_urdf);
hardware_interface::JointHandle vel_handle(jnt_state_interface.getHandle(os.str()), &cmd[i]);
jnt_vel_interface.registerHandle(vel_handle);
hardware_interface::JointHandle vel_handle_urdf(jnt_state_interface.getHandle(os_ctrl.str()), &cmd_ctrl[i]);
jnt_vel_interface.registerHandle(vel_handle_urdf);
}
registerInterface(&jnt_state_interface);
registerInterface(&jnt_vel_interface);
and change joint names in control.yaml
to:
left_wheel_velocity_controller:
type: velocity_controllers/JointVelocityController
joint: base_to_0_wheel
pid: {p: 00.1, i: 0.00001, d: 0.0001}
right_wheel_velocity_controller:
type: velocity_controllers/JointVelocityController
joint: base_to_1_wheel
pid: {p: 100.0, i: 0.1, d: 10.0}
I still get the error saying:
[ERROR] [1527380218.473857467]: Exception thrown while initializing controller left_wheel_velocity_controller.
Could not find resource 'base_to_0_wheel' in 'hardware_interface::VelocityJointInterface'.
[ERROR] [1527380218.473907473]: Initializing controller 'left_wheel_velocity_controller' failed
[ERROR] [1527380219.474679]: Failed to load left_wheel_velocity_controller
and the same error for second controller.
Questions
Do I really need to create 2 excessive joints for separate PID velocity controllers (each for one wheel)? What is missing in my configuration?
I remember that when I've been messing with above things I managed to start controllers without errors but robot's behavior didn't change. Should I use some external PID (non ros_control's like this) and make separate node out of it?
Sorry for this long question, I've tried to explain my problem the best I could to simplify finding a solution. I will appreciate any help.
Asked by rayvburn on 2018-05-26 19:47:25 UTC
Comments
Hi there, I am stuck at the very same problem for about 2 weeks now, as there doesnt seem to be much documentation. Did you get any further?
Asked by stuggibo on 2018-11-26 10:16:33 UTC
Unfortunately I had no luck. Finally used this package pid and it worked perfectly. EDIT: I forgot to post a link to my project's code. You may find it a useful example - Github repository
Asked by rayvburn on 2018-11-27 16:04:53 UTC
thanks, this helped me a lot :) did you somehow filter your velocity estimate?
Asked by stuggibo on 2018-12-20 09:49:20 UTC
No, sorry, I didn't need velocity filtering. Anyway, I'm glad I could help you a little.
Asked by rayvburn on 2018-12-23 04:03:32 UTC
This comment is probably not relevant for you anymore and I don't know if it is required either but I think you need to define a transmission tag inside your urdf in case you didn't have it. This seems to be required in simulation and when working with real hardware.
Asked by fjp on 2020-03-18 06:53:31 UTC