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

diff_drive_controller ignores acceleration limits

asked 2021-07-09 03:07:57 -0600

PaddyCube gravatar image

updated 2021-07-09 13:19:01 -0600

Hello community,

I have a real 2-wheeled robot and use diff_drive_controller. I'm able to drive around using teleop. It seems to work so far. But I'm curious about max_jerk and max_acceleration setting as they are not used for some reason. I tried different values and now even very low values but it doesn't make any difference.

From my understanding, diff_drive_controller subscribes to /cmd_vel and translate this to separate commands for each joint(wheel).

So when the current linear velocity is 0m/s and I publish a message to /cmd_vel telling to set linear velocity to 1m/s, robot instantly drives whith this speed. If I switch between forward/backward with max velocity, it jumps around.

My assumption is that diff_drive_controller takes care of acceleration limits resulting in a smooth movement of robot. I tried different max_velocity values just for check and these are used by diff_drive_controller

Any ideas of what is wrong here?

    hoverboard_joint_publisher:
  type: "joint_state_controller/JointStateController"
  publish_rate: 50
  left_wheel  : 'left_wheel'
  right_wheel : 'right_wheel'

hoverboard_velocity_controller:
  type        : "diff_drive_controller/DiffDriveController"
  left_wheel  : 'left_wheel'
  right_wheel : 'right_wheel'
  publish_rate: 50.0               # default: 50
  pose_covariance_diagonal : [0.001, 0.001, 1000000.0, 1000000.0, 1000000.0, 1000.0]
  twist_covariance_diagonal: [0.001, 0.001, 1000000.0, 1000000.0, 1000000.0, 1000.0]

  # Wheel separation and diameter. These are both optional.
  # diff_drive_controller will attempt to read either one or both from the
  # URDF if not specified as a parameter
  wheel_separation : 0.32
  wheel_radius : 0.0825

  # Wheel separation and radius multipliers
  wheel_separation_multiplier: 1.0 # default: 1.0
  wheel_radius_multiplier    : 1.0 # default: 1.0

  # Velocity commands timeout [s], default 0.5
  cmd_vel_timeout: 0.5

  # Base frame_id
  base_frame_id: base_footprint #default: base_link
  allow_multiple_cmd_vel_publishers: true
  odom_frame_id: '/raw_odom'
  enable_odom_tf: false

  # Velocity and acceleration limits
  # Whenever a min_* is unspecified, default to -max_*
  linear:
    x:
      has_velocity_limits    : true
      max_velocity           : 0.5  # m/s
      has_acceleration_limits: true
      max_acceleration       : 0.01  # m/s^2
      has_jerk_limits        : true
      max_jerk               : 0.001  # m/s^3
  angular:
    z:
      has_velocity_limits    : true # was true
      max_velocity           : 6.28  # rad/s
      has_acceleration_limits: true # was true
      max_acceleration       : 1.04  # rad/s^2
      has_jerk_limits        : true
      max_jerk               : 3.14  # rad/s^3

This is how launch file looks like

<launch>
    <rosparam file="$(find hoverboard_driver)/config/hardware.yaml" command="load"/>
    <rosparam file="$(find hoverboard_driver)/config/controllers.yaml" command="load"/>

      <!-- PS4 joypad -->
  <remap from="/cmd_vel" to="/hoverboard_velocity_controller/cmd_vel"/>    
  <include file="$(find ds4_driver)/launch/ds4_twist.launch">
    <arg name="dof" value="2"/>
    <!--<arg name="topic" value="joy_vel"/> -->

  </include>


    <node name="hoverboard_driver" pkg="hoverboard_driver" type="hoverboard_driver" output="screen"/>
    <node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false" output="screen" ns="/"
        args="hoverboard_joint_publisher hoverboard_velocity_controller" />
</launch>

rostopic list:

ubuntu@ubuntu:~$ rostopic list
/hoverboard/battery_voltage
/hoverboard/left_wheel/cmd
/hoverboard/left_wheel/position
/hoverboard/left_wheel/velocity
/hoverboard/right_wheel/cmd
/hoverboard/right_wheel/position
/hoverboard/right_wheel/velocity
/hoverboard/temperature
/hoverboard_velocity_controller/cmd_vel
/hoverboard_velocity_controller/odom
/hoverboard_velocity_controller/parameter_descriptions
/hoverboard_velocity_controller/parameter_updates
/joint_states
/pid/left/parameter_descriptions
/pid/left/parameter_updates
/pid/right/parameter_descriptions
/pid/right/parameter_updates
/rosout
/rosout_agg
/tf

Here the output of /joint_state. At beginning, robots velocity is set to 0m/s and ... (more)

edit retag flag offensive close merge delete

Comments

The diff_drive_controller source files do contain code to limit the acceleration. What makes you think it is not being used when you are using the navigation stack? Is this simulation or a real robot? If you monitor the JointState, does that jump too?

Mike Scheutzow gravatar image Mike Scheutzow  ( 2021-07-09 07:42:25 -0600 )edit

Please edit your question and append the output from rosnode list.

Mike Scheutzow gravatar image Mike Scheutzow  ( 2021-07-09 08:23:38 -0600 )edit

This is a real robot. If I send cmd_vel with linear velocity of 1m/s, robot immediately starts to run with this speed. I just publish this message either by console or joystick. Does acceleration limit only gets respected when used navigation stack? Right now, my robot is just some kind of RC car as you see.

PaddyCube gravatar image PaddyCube  ( 2021-07-09 13:08:02 -0600 )edit

Anything published to cmd_vel should have accel limits applied. You are correct that joint velocity should not jump up like that in a couple hundred milliseconds. What are /pid/left and /pid/right? How have you configured them?

Mike Scheutzow gravatar image Mike Scheutzow  ( 2021-07-09 14:23:15 -0600 )edit

I found a bug inside my main loop.

    while (ros::ok()) {
    const ros::Time time = ros::Time::now();
    const ros::Duration period = time - prev_time;

    hoverboard.read();
    cm.update(time, period);
    hoverboard.write(time, period);

    rate.sleep();
}

prev_time was only set outside the loop but never inside the loop. I added prev_time = time right before rate.sleep. It works now if I set acceleration very low (0.1 m/s²) but if I set it higher, it still accelerates slow and starts to oscilate afterwards by running forward, backward, forward, backward even if there is no /cmd_vel message is applied anymore

PaddyCube gravatar image PaddyCube  ( 2021-07-11 13:30:16 -0600 )edit

This is my currend PID setting. The entire code has been developed by other people and I still try to understand how it works.

from dynamic_reconfigure.parameter_generator_catkin import *
gen = ParameterGenerator()
#        Name            Type      Level  Description                           Default   Min    Max
gen.add( "f" ,           double_t, 1,     "Feed forward gain.",                 10.0,     -100,  100)
gen.add( "p" ,           double_t, 1,     "Proportional gain.",                 10.0,     -100,  100)
gen.add( "i" ,           double_t, 1,     "Integral gain.",                     0.1,      -100,  100)
gen.add( "d" ,           double_t, 1,     "Derivative gain.",                   1.0,      -100,  100)
gen.add( "i_clamp_min" , double_t, 1,     "Min bounds for the integral windup", -10.0,    -100,    0)
gen.add( "i_clamp_max" , double_t, 1,     "Max bounds for the integral windup", 10.0,     0,     100)
gen.add( "antiwindup" ,  bool_t,   1,     "Antiwindup.",
PaddyCube gravatar image PaddyCube  ( 2021-07-11 13:39:00 -0600 )edit

Good work figuring out that bug. That oscillation happens because the PID controller is not configured properly, so the velocity output to the motor is unstable. If it were me, as a starting point for the PID, I would set p=0.1, i=0, d=0. I have no way to determine what f should be; whoever did this hardware interface layer should have provided the proper value, which I suspect is based on what the motor wants to see at its input.

Mike Scheutzow gravatar image Mike Scheutzow  ( 2021-07-12 07:23:10 -0600 )edit

1 Answer

Sort by » oldest newest most voted
0

answered 2021-07-12 07:28:07 -0600

Mike Scheutzow gravatar image

There is a hardware_interface layer that sits between the diff_drive_controller and the motors. This layer has to work properly, and the PID controllers be tuned properly, for the robot to move smoothly and at the requested velocity. As far as I can tell from our discussion, the diff_drive_controller is functioning as expected.

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2021-07-09 03:07:57 -0600

Seen: 368 times

Last updated: Jul 12 '21