New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add command queue to servo to account for latency #2594
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #2594 +/- ##
==========================================
+ Coverage 50.31% 50.48% +0.18%
==========================================
Files 386 386
Lines 32151 32228 +77
==========================================
+ Hits 16172 16266 +94
+ Misses 15979 15962 -17 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could get rid of the complexity of the rolling window and simply always keep 2 waypoints in committed_commands_
. I bet the majority of the performance gain comes from the latency
parameter and the stop command point.
The latency parameter is identical to #886 but the stop command point is a good idea.
Adding that |
17ebf29
to
f75ea3b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to rethink the end_state
The one problem I see with using the One option is to actually call
Another option is to not explicitly account for this case because the low-level controller will likely have a stopping mechanism. But I think it's safer to have it just in case. @AndyZe Do you have a suggestion to handle the edge case of extreme latency? |
I guess the halt point is fine. |
// keep track of previously generated joint commands for constructing trajectory messages | ||
std::deque<KinematicState> committed_commands_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// keep track of previously generated joint commands for constructing trajectory messages | |
std::deque<KinematicState> committed_commands_; | |
// rolling window of joint commands | |
std::deque<KinematicState> joint_cmd_rolling_window_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of the "committed" terminology. I think people normally think of this as a rolling window.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed all references of "committed" to "joint_cmd_rolling_window"
Between @sea-bass comments about making the change more functional, e.g. passing the rolling window in, and @AndyZe concerns about performance, I think it is best to factor out the command queueing logic and have the calling code maintain it. I'll move the logic into the |
Well, props for figuring out this long-standing issue! |
12f1039
to
797d8f5
Compare
Fix wording Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>
Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>
Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>
Signed-off-by: Paul Gesel <paulgesel@gmail.com>
5f9956c
to
0d95e93
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see @AndyZe's point about scaling acceleration doing weird things to the direction being tracked, and left a comment inline asking if there is a way to "time scale" the bundled up trajectory in a way that is more correct.
The other comment about trying velocity filtering with the Butterworth plugin is something we could explore? I tried with these changes and it made my Gazebo simulation do horrible things, but that could have been a combination of Gazebo's physics and some other issues that may have been resolved since (including in this PR). I guess it's worth a shot to try it and get some data.
@@ -284,6 +284,15 @@ bool Servo::validateParams(const servo::Params& servo_params) const | |||
params_valid = false; | |||
} | |||
|
|||
if (servo_params.max_expected_latency / 3 < servo_params.publish_period) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 3
in here is a magic number, but I'm assuming this is related to you wanting 3 points in your trajectory, right? Is this the same as MIN_POINTS_FOR_TRAJ_MSG
you defined in common.cpp
?
If that's not the case, you can probably leave in the literal here (especially since it's also in the error message), but definitely add a comment explaining.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's correct to relate the 3 here to MIN_POINTS_FOR_TRAJ_MSG
. Do you think I should move MIN_POINTS_FOR_TRAJ_MSG
to moveit_servo/utils/common.hpp
so it can be accessed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so!
// apply scaling to target velocity based on robot's limits | ||
Eigen::VectorXd acceleration = -target_state.velocities / servo_params_.publish_period; | ||
const double joint_acceleration_limit_scale = jointLimitAccelerationScalingFactor(acceleration, joint_bounds, 1.0); | ||
target_state.velocities += joint_acceleration_limit_scale * acceleration * servo_params_.publish_period; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @AndyZe's comment about direction switching is valid, and I hadn't thought of that since I was thinking about the full trajectory planning case where scaling down acceleration + scaling up time accelerating works equivalently to the unscaled case, as far as the space swept by the robot motion.
Is there any way to do the same within the current servo framework now that we have the rolling window? Like, time scaling https://www2.ece.ohio-state.edu/~zhang/RoboticsClass/docs/LN9_TrajectoryGeneration.pdf -- meaning, taking the existing trajectory's accelerations and scaling up the time_from_start
to be higher as needed to meet the limits?
@AndyZe If we filter in velocity, won't we run into the same issue of the robot not moving in the direction commanded? That is the main criticism of acceleration limiting. |
True. Well, it's an optional plugin. Hopefully Ruckig will come along and solve all of our issues. Happy to help make that happen |
e72cdb9
to
0544301
Compare
…ce the time stamp is set in the updateSlidingWindow function now. Signed-off-by: Paul Gesel <paulgesel@gmail.com>
0544301
to
72d4f92
Compare
Signed-off-by: Paul Gesel <paulgesel@gmail.com>
459a5b0
to
37e590f
Compare
@AndyZe Okay great. I removed the acceleration-based limits from this PR. I will follow up with an |
Signed-off-by: Paul Gesel <paulgesel@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yay!
a596a0d
to
3aace07
Compare
…s current state if no command generated 4) fix smooth hault: stop command was not generated if smoothing disabled 5) call resetSmoothing when there are no commands Signed-off-by: Paul Gesel <paulgesel@gmail.com>
3aace07
to
1acf7e4
Compare
@pac48 Can you address the conflicts? Then we should merge this, nice work! |
This pull request is in conflict. Could you fix it @pac48? |
I just addressed them, they were simple and from my recent PR, so let's do this! |
* add command queue to servo to account for latency * run pre-commit * fix unsigned compare * Update moveit_ros/moveit_servo/config/servo_parameters.yaml Fix wording Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * Update moveit_ros/moveit_servo/src/servo.cpp Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * Update moveit_ros/moveit_servo/src/servo.cpp Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * add comments and change variable names * add checks to determine what state information should be published Signed-off-by: Paul Gesel <paulgesel@gmail.com> * change latency parameter name Signed-off-by: Paul Gesel <paulgesel@gmail.com> * factor command queue out of servo instance Signed-off-by: Paul Gesel <paulgesel@gmail.com> * update demos Signed-off-by: Paul Gesel <paulgesel@gmail.com> * needs clean up but working well * deal with duplicate timestamps for sim * add acceleration limiting smoothing * add timeout check in filter Signed-off-by: Paul Gesel <paulgesel@gmail.com> * factor out robot state from servo call Signed-off-by: Paul Gesel <paulgesel@gmail.com> * update comments in smoothing pluin Signed-off-by: Paul Gesel <paulgesel@gmail.com> * fix tests Signed-off-by: Paul Gesel <paulgesel@gmail.com> * change velocity calculation to make interpolation not overshoot Signed-off-by: Paul Gesel <paulgesel@gmail.com> * Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * Update moveit_ros/moveit_servo/config/servo_parameters.yaml Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * Update moveit_ros/moveit_servo/demos/cpp_interface/demo_joint_jog.cpp Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * fix time calculation Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add check to ensure time interval is positive Signed-off-by: Paul Gesel <paulgesel@gmail.com> * simplify demos Signed-off-by: Paul Gesel <paulgesel@gmail.com> * wait for first robot state before starting servo loop Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add comments to acceleration filter Signed-off-by: Paul Gesel <paulgesel@gmail.com> * fix wait time units * fix logic bug in smoothHalt and remove stopping point from trajectory message. Still some overshoot. Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add acceleration limit to servo Signed-off-by: Paul Gesel <paulgesel@gmail.com> * remove acceleration filter Signed-off-by: Paul Gesel <paulgesel@gmail.com> * remove other filter files from moveit_core Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add doc string and basic clean up * refactor getRobotState to utils and add a test Signed-off-by: Paul Gesel <paulgesel@gmail.com> * make some things const and fix comments Signed-off-by: Paul Gesel <paulgesel@gmail.com> * use joint_limts params to get robot acceleration limits Signed-off-by: Paul Gesel <paulgesel@gmail.com> * update demo config and set velocities in demos Signed-off-by: Paul Gesel <paulgesel@gmail.com> * fix acceleration calculation Signed-off-by: Paul Gesel <paulgesel@gmail.com> * apply collision_velocity_scale_ in smooth hault, add comments, and rename variables Signed-off-by: Paul Gesel <paulgesel@gmail.com> * use bounds on scaling factors in [0... 1] Signed-off-by: Paul Gesel <paulgesel@gmail.com> * remove joint_acceleration parameter Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add test for jointLimitAccelerationScaling Signed-off-by: Paul Gesel <paulgesel@gmail.com> * refactor velocity and acceleration scaling into common function Signed-off-by: Paul Gesel <paulgesel@gmail.com> * general clean up, add comments, fix parameters, set timestamp in updateSlidingWindow, etc. Signed-off-by: Paul Gesel <paulgesel@gmail.com> * Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml Co-authored-by: AndyZe <andyz@utexas.edu> * Update moveit_ros/moveit_servo/src/servo.cpp Co-authored-by: AndyZe <andyz@utexas.edu> * remove override_acceleration_scaling_factor Signed-off-by: Paul Gesel <paulgesel@gmail.com> * fix variable name Signed-off-by: Paul Gesel <paulgesel@gmail.com> * enable use_smoothing in demos Signed-off-by: Paul Gesel <paulgesel@gmail.com> * Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml Co-authored-by: AndyZe <andyz@utexas.edu> * add current state to command queue if it is empty. This is needed since the time stamp is set in the updateSlidingWindow function now. Signed-off-by: Paul Gesel <paulgesel@gmail.com> * remove acceleration smoothing Signed-off-by: Paul Gesel <paulgesel@gmail.com> * revert jointLimitVelocityScalingFactor refactor Signed-off-by: Paul Gesel <paulgesel@gmail.com> * 1) fix spelling 2) add comments 3) make sure rolling_window always has current state if no command generated 4) fix smooth hault: stop command was not generated if smoothing disabled 5) call resetSmoothing when there are no commands Signed-off-by: Paul Gesel <paulgesel@gmail.com> --------- Signed-off-by: Paul Gesel <paulgesel@gmail.com> Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> Co-authored-by: AndyZe <andyz@utexas.edu>
* add command queue to servo to account for latency * run pre-commit * fix unsigned compare * Update moveit_ros/moveit_servo/config/servo_parameters.yaml Fix wording Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * Update moveit_ros/moveit_servo/src/servo.cpp Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * Update moveit_ros/moveit_servo/src/servo.cpp Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * add comments and change variable names * add checks to determine what state information should be published Signed-off-by: Paul Gesel <paulgesel@gmail.com> * change latency parameter name Signed-off-by: Paul Gesel <paulgesel@gmail.com> * factor command queue out of servo instance Signed-off-by: Paul Gesel <paulgesel@gmail.com> * update demos Signed-off-by: Paul Gesel <paulgesel@gmail.com> * needs clean up but working well * deal with duplicate timestamps for sim * add acceleration limiting smoothing * add timeout check in filter Signed-off-by: Paul Gesel <paulgesel@gmail.com> * factor out robot state from servo call Signed-off-by: Paul Gesel <paulgesel@gmail.com> * update comments in smoothing pluin Signed-off-by: Paul Gesel <paulgesel@gmail.com> * fix tests Signed-off-by: Paul Gesel <paulgesel@gmail.com> * change velocity calculation to make interpolation not overshoot Signed-off-by: Paul Gesel <paulgesel@gmail.com> * Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * Update moveit_ros/moveit_servo/config/servo_parameters.yaml Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * Update moveit_ros/moveit_servo/demos/cpp_interface/demo_joint_jog.cpp Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> * fix time calculation Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add check to ensure time interval is positive Signed-off-by: Paul Gesel <paulgesel@gmail.com> * simplify demos Signed-off-by: Paul Gesel <paulgesel@gmail.com> * wait for first robot state before starting servo loop Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add comments to acceleration filter Signed-off-by: Paul Gesel <paulgesel@gmail.com> * fix wait time units * fix logic bug in smoothHalt and remove stopping point from trajectory message. Still some overshoot. Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add acceleration limit to servo Signed-off-by: Paul Gesel <paulgesel@gmail.com> * remove acceleration filter Signed-off-by: Paul Gesel <paulgesel@gmail.com> * remove other filter files from moveit_core Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add doc string and basic clean up * refactor getRobotState to utils and add a test Signed-off-by: Paul Gesel <paulgesel@gmail.com> * make some things const and fix comments Signed-off-by: Paul Gesel <paulgesel@gmail.com> * use joint_limts params to get robot acceleration limits Signed-off-by: Paul Gesel <paulgesel@gmail.com> * update demo config and set velocities in demos Signed-off-by: Paul Gesel <paulgesel@gmail.com> * fix acceleration calculation Signed-off-by: Paul Gesel <paulgesel@gmail.com> * apply collision_velocity_scale_ in smooth hault, add comments, and rename variables Signed-off-by: Paul Gesel <paulgesel@gmail.com> * use bounds on scaling factors in [0... 1] Signed-off-by: Paul Gesel <paulgesel@gmail.com> * remove joint_acceleration parameter Signed-off-by: Paul Gesel <paulgesel@gmail.com> * add test for jointLimitAccelerationScaling Signed-off-by: Paul Gesel <paulgesel@gmail.com> * refactor velocity and acceleration scaling into common function Signed-off-by: Paul Gesel <paulgesel@gmail.com> * general clean up, add comments, fix parameters, set timestamp in updateSlidingWindow, etc. Signed-off-by: Paul Gesel <paulgesel@gmail.com> * Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml Co-authored-by: AndyZe <andyz@utexas.edu> * Update moveit_ros/moveit_servo/src/servo.cpp Co-authored-by: AndyZe <andyz@utexas.edu> * remove override_acceleration_scaling_factor Signed-off-by: Paul Gesel <paulgesel@gmail.com> * fix variable name Signed-off-by: Paul Gesel <paulgesel@gmail.com> * enable use_smoothing in demos Signed-off-by: Paul Gesel <paulgesel@gmail.com> * Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml Co-authored-by: AndyZe <andyz@utexas.edu> * add current state to command queue if it is empty. This is needed since the time stamp is set in the updateSlidingWindow function now. Signed-off-by: Paul Gesel <paulgesel@gmail.com> * remove acceleration smoothing Signed-off-by: Paul Gesel <paulgesel@gmail.com> * revert jointLimitVelocityScalingFactor refactor Signed-off-by: Paul Gesel <paulgesel@gmail.com> * 1) fix spelling 2) add comments 3) make sure rolling_window always has current state if no command generated 4) fix smooth hault: stop command was not generated if smoothing disabled 5) call resetSmoothing when there are no commands Signed-off-by: Paul Gesel <paulgesel@gmail.com> --------- Signed-off-by: Paul Gesel <paulgesel@gmail.com> Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com> Co-authored-by: AndyZe <andyz@utexas.edu>
There is an issue where some robots experience non-smooth and noisy servo performance #2275. Currently, servo sends trajectory messages to the ros2_control JTC one waypoint at a time. However, This causes issues because when the JTC receives a new message, it replaces the old one entirely. My proposal to solve this issue is to send more than one waypoint at a time and make sure everything is time-synchronized. Below is an example diagram.
When messages are sent from servo to the JTC, there is an inherent noisy delay that should be accounted for. One strategy is to use a buffer that contains all generated servo commands from the current time to the current time plus the maximum expected latency. This range is shown in red. Any commands that are put in the buffer are considered "committed", meaning they will be executed by the JTC. For any time after the red region, there is still an opportunity to change commands. This is illustrated with the green trajectory.
I recorded and plotted the commands received by the JTC with the current servo implementation (left) vs. this PR (right) using the 'demo_pose.cpp' example in the servo package.