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 then instantly to 1m/s. It accelerates way faster as it should do from my opinion. Max velocity has been set to 0.5m/s which is close to 6rad/s as radius of wheel is 0.0825
header:
seq: 38106
stamp:
secs: 1625854242
nsecs: 451236534
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.2536604613725, 310.38935417467155]
velocity: [0.0, 0.0]
effort: [0.0, 0.0]
---
header:
seq: 38107
stamp:
secs: 1625854242
nsecs: 471224839
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.32347363145226, 310.45916734475134]
velocity: [0.5236, 0.62832]
effort: [0.0, 0.0]
---
header:
seq: 38108
stamp:
secs: 1625854242
nsecs: 491229967
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.39328680153204, 310.5289805148311]
velocity: [4.08408, 3.76992]
effort: [0.0, 0.0]
---
header:
seq: 38109
stamp:
secs: 1625854242
nsecs: 511226762
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.4630999716118, 310.5987936849109]
velocity: [3.6651999999999996, 4.1888]
effort: [0.0, 0.0]
---
header:
seq: 38110
stamp:
secs: 1625854242
nsecs: 521235628
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.5329131416916, 310.5987936849109]
velocity: [1.4660799999999998, 4.1888]
effort: [0.0, 0.0]
---
header:
seq: 38111
stamp:
secs: 1625854242
nsecs: 541368724
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.60272631177133, 310.6686068549907]
velocity: [4.50296, 3.6651999999999996]
effort: [0.0, 0.0]
---
header:
seq: 38112
stamp:
secs: 1625854242
nsecs: 571235323
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.7423526519309, 310.8082331951502]
velocity: [4.50296, 4.29352]
effort: [0.0, 0.0]
---
header:
seq: 38113
stamp:
secs: 1625854242
nsecs: 591233940
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.8121658220107, 310.87804636523]
velocity: [5.02656, 3.87464]
effort: [0.0, 0.0]
---
header:
seq: 38114
stamp:
secs: 1625854242
nsecs: 601232806
frame_id: ''
name:
- left_wheel
- right_wheel
position: [316.88197899209047, 310.94785953530976]
velocity: [4.1888, 4.9218399999999995]
effort: [0.0, 0.0]
---
header:
seq: 38115
stamp:
secs: 1625854242
nsecs: 631224613
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.09141850232976, 311.0874858754693]
velocity: [4.7124, 4.7124]
effort: [0.0, 0.0]
---
header:
seq: 38116
stamp:
secs: 1625854242
nsecs: 641237749
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.09141850232976, 311.0874858754693]
velocity: [4.7124, 4.7124]
effort: [0.0, 0.0]
---
header:
seq: 38117
stamp:
secs: 1625854242
nsecs: 671225077
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.2310448424893, 311.2969253857086]
velocity: [5.131279999999999, 5.02656]
effort: [0.0, 0.0]
---
header:
seq: 38118
stamp:
secs: 1625854242
nsecs: 691222496
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.3008580125691, 311.3667385557884]
velocity: [5.131279999999999, 5.236]
effort: [0.0, 0.0]
---
header:
seq: 38119
stamp:
secs: 1625854242
nsecs: 701232664
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.3706711826489, 311.4365517258682]
velocity: [5.236, 5.44544]
effort: [0.0, 0.0]
---
header:
seq: 38120
stamp:
secs: 1625854242
nsecs: 731246137
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.5102975228084, 311.5761780660277]
velocity: [5.340719999999999, 5.55016]
effort: [0.0, 0.0]
---
header:
seq: 38121
stamp:
secs: 1625854242
nsecs: 751225536
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.64992386296797, 311.71580440618726]
velocity: [6.07376, 5.44544]
effort: [0.0, 0.0]
---
header:
seq: 38122
stamp:
secs: 1625854242
nsecs: 771221758
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.78955020312753, 311.8554307463468]
velocity: [5.44544, 5.6548799999999995]
effort: [0.0, 0.0]
---
header:
seq: 38123
stamp:
secs: 1625854242
nsecs: 791225011
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.8593633732073, 311.92524391642655]
velocity: [5.6548799999999995, 5.55016]
effort: [0.0, 0.0]
---
header:
seq: 38124
stamp:
secs: 1625854242
nsecs: 811237274
frame_id: ''
name:
- left_wheel
- right_wheel
position: [317.9989897133668, 312.0648702565861]
velocity: [5.55016, 5.6548799999999995]
effort: [0.0, 0.0]
---
header:
seq: 38125
stamp:
secs: 1625854242
nsecs: 831210683
frame_id: ''
name:
- left_wheel
- right_wheel
position: [318.1386160535264, 312.2044965967457]
velocity: [5.55016, 5.864319999999999]
effort: [0.0, 0.0]
---
header:
seq: 38126
stamp:
secs: 1625854242
nsecs: 841238403
frame_id: ''
name:
- left_wheel
- right_wheel
position: [318.2084292236062, 312.27430976682547]
velocity: [5.6548799999999995, 5.864319999999999]
effort: [0.0, 0.0]
---
header:
seq: 38127
stamp:
secs: 1625854242
nsecs: 871228543
frame_id: ''
name:
- left_wheel
- right_wheel
position: [318.34805556376574, 312.413936106985]
velocity: [5.7596, 5.96904]
effort: [0.0, 0.0]
---
header:
seq: 38128
stamp:
secs: 1625854242
nsecs: 891231848
frame_id: ''
name:
- left_wheel
- right_wheel
position: [318.48768190392525, 312.55356244714454]
velocity: [5.7596, 5.7596]
effort: [0.0, 0.0]
---
header:
seq: 38129
stamp:
secs: 1625854242
nsecs: 901243526
frame_id: ''
name:
- left_wheel
- right_wheel
position: [318.55749507400503, 312.6233756172243]
velocity: [5.7596, 5.864319999999999]
effort: [0.0, 0.0]
---
header:
seq: 38130
stamp:
secs: 1625854242
nsecs: 931226687
frame_id: ''
name:
- left_wheel
- right_wheel
position: [318.6971214141646, 312.76300195738384]
velocity: [5.7596, 5.7596]
effort: [0.0, 0.0]
---
header:
seq: 38131
stamp:
secs: 1625854242
nsecs: 951222700
frame_id: ''
name:
- left_wheel
- right_wheel
position: [318.8367477543241, 312.9026282975434]
velocity: [5.236, 6.07376]
effort: [0.0, 0.0]
---
header:
seq: 38132
stamp:
secs: 1625854242
nsecs: 971380119
frame_id: ''
name:
- left_wheel
- right_wheel
position: [318.9763740944837, 313.04225463770297]
velocity: [6.07376, 5.96904]
effort: [0.0, 0.0]
Originally posted by PaddyCube on ROS Answers with karma: 76 on 2021-07-09
Post score: 0
Original comments
Comment by Mike Scheutzow on 2021-07-09:
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?
Comment by Mike Scheutzow on 2021-07-09:
Please edit your question and append the output from rosnode list
.
Comment by PaddyCube on 2021-07-09:
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.
Comment by Mike Scheutzow on 2021-07-09:
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?
Comment by PaddyCube on 2021-07-11:
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
Comment by PaddyCube on 2021-07-11:
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.",
Comment by Mike Scheutzow on 2021-07-12:
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.