ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

PID controller oscillations worsen when D term is increased

asked 2020-05-05 17:49:07 -0500

pomelilola gravatar image

updated 2020-05-05 18:23:01 -0500

I am using the diff_drive_controller, pid, and rosserial_arduino packages to control my two-wheeled robot. Currently I'm trying to tune each wheel's PID velocity controller but have been having some trouble. Here is how the nodes are currently organized.

In the above, the diff_drive_controller node has been omitted for the sake of tuning; the setpoints are instead being published from two custom-written nodes. fw_node (rosserial_arduino) runs on an Arduino Nano 33 BLE, subscribes to the control_effort topics and writes their values to the robot motors, and publishes the vel topics to the PID controllers as plant state. All other nodes run on my laptop (Ubuntu 16.04, x86, 4.15.0-99-generic).

When I follow the traditional tuning method of increasing P until wild oscillation and then increasing D for dampening, what happens is that increasing D actually worsens the oscillations.

Here are some plots to show this. A rosbag in which I try to tune the left PID can also be found here; you can see the topics /left_wheel/pid_node/parameter_updates for the gains and /left_wheel/vel for the plant state.

P = 8.5, I = 0, D = 0, just enough for wild oscillation

P = 8.5, I = 0, D = 0.4, in an attempt to dampen oscillation. The oscillations grow when D is changed from 0 to 0.4

I've tried the following changes but haven't had much success:

  • Making sure that each PID controller receives the setpoint and plant state at the same time
  • Decreasing control loop frequency from 100 to 50 Hz

Here are the settings for my PID controllers (ignore Kp, Ki, and Kd since those are adjusted anyways):

<node name="pid_node" pkg="pid" type="controller" ns="left_wheel" output="screen">
    <param name="Kp" value="5.0"/>
    <param name="Ki" value="0.0"/>
    <param name="Kd" value="0.1"/>
    <param name="upper_limit" value="255"/>
    <param name="lower_limit" value="-255"/>
    <param name="windup_limit" value="10"/>

    <!-- topic_from_controller = control_effort -->
    <!-- setpoint_topic = setpoint -->
    <param name="topic_from_plant" value="vel"/>

 <!-- same settings for right pid controller -->

Any ideas on what could be wrong and how to fix my problem? I have verified that setpoint and plant state message values are accurate.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted

answered 2020-05-05 20:19:43 -0500

PI control is a completely valid way of doing control if you can get the response you're looking for without the derivative term. Given I see the word "arduino" I'm guessing you're working with hobbyist hardware. Even with cheaper but reasonable pro hardware, the derivative term of a controller can be finicky because small amounts of noise or interpolation errors can mess with the derivative estimate. You'd want either (or both) a high resolution encoder and a high gearing ratio. I'd think that reducing from 100hz to 50hz could make it worse, though since you have more measurements to work with from the encoder, the encoder error will look less bad since you have a longer sampling duration.

If you find that the derivative term results in bad behavior, setting it to 0 is reasonable. Work on your integral term though, that should help you out a bunch.

edit flag offensive delete link more

Question Tools



Asked: 2020-05-05 17:49:07 -0500

Seen: 851 times

Last updated: May 05 '20