Open TheSpeedM opened 3 months ago
Hey, Had the same problem and had to fixed it first with a small function like yours. Further looking into it showed me, that the problematic points always were the first and last point inside the blend radius.
!!BE CAREFUL before you test this script with a real robot, In my case not only the time was off, but the velocity and acceleration at these points too, so the robot moves in an abrupt and jittery way when transitioning!!
In the MoveIt Humble Docs I found 'Time Parameterization' and the Time-Optimal Parameter Generation method which fixed time, acceleration and velocity for me. Unfortunately I only found a C++ version of this. Alternatively you can look into Ruckig-Smoothing of the trajectory. Hope I could point you in the right direction
First of all thank your proposed solution and heads-up. I haven't tested this on a real robot yet, though this is something that I will make a priority because of your experience.
In the MoveIt Humble Docs I found 'Time Parameterization' and the Time-Optimal Parameter Generation method which fixed time, acceleration and velocity for me.
The problem with this solution is that adding the AddTimeOptimalParameterization
request adapter to pilz_industrial_motion_planner.yaml
doesn't work in my case. This is probably the same problem this commenter in ros-planning/moveit#2905 was having; I can't use a blend with this request adapter enabled.
I might have to look into other ways of smoothing the trajectory.
Oh yeah, forgot to mention that the adapter didn't work for me either.
I had to manually create a class object of TimeOptimalTrajectoryGeneration
and recalculate the trajectory with the computeTimeStamps
function. For this to work I had to change the moveit-RobotTrajectory into a robot_trajectory-RobotTrajectory, get the new waypoints and convert back.
But this was all in C++ and unfortunately I don't know if there's a python class for the TOTG :/
@AGuthmann could you be so kind to share a snippet of your code showcasing the approach you took?
I am facing same problem, in my case , the code is in C++.
sure, here you go:
#include <rclcpp/rclcpp.hpp>
#include <moveit/move_group_interface/move_group_interface.h>
#include <moveit_core/moveit/trajectory_processing/time_optimal_trajectory_generation.h>
void optimize_trajectory(moveit_msgs::msg::RobotTrajectory &trajectory, double max_velocity_scaling_factor, double max_acceleration_scaling_factor){
moveit::core::RobotState robot_state(move_group_interface_->getRobotModel());
robot_trajectory::RobotTrajectory robot_trajectory(move_group_interface_->getRobotModel(), robot_state.getJointModelGroup(PLANNING_GROUP)->getName());
robot_trajectory.setRobotTrajectoryMsg(robot_state, trajectory); // convert moveit_msgs::msg::RobotTrajectory into robot_trajectory::RobotTrajectory
trajectory_processing::TimeOptimalTrajectoryGeneration totg; // Create Optimization Object
totg.computeTimeStamps(robot_trajectory, 0.1, 0.1); // First optimization with default scalings
totg.computeTimeStamps(robot_trajectory,max_velocity_scaling_factor, max_acceleration_scaling_factor); // Second optimization with user chosen scalings
RCLCPP_INFO(logger_, "First Iteration: %d, Second Iteration: %d", first, second);
robot_trajectory.getRobotTrajectoryMsg(trajectory); // convert robot_trajectory::RobotTrajectory back to moveit_msgs::msg::RobotTrajectory
}
I had to optimize twice because sometimes longer trajectories weren't optimized at all. Couldn't figure out where this comes from...
Additionally if you have 180° turns in your trajectory the optimization will probably fail, because these aren't implemented / supported yet. For my tests it was sufficient to offset the Points before or after the 180° turn by 1mm perpendicular to the movement of the trajectory.
I have tested the 'dirty solution' on a real robot and it indeed jitters a lot at these points. I also found that Pilz normally creates points with an interval of 0.1 seconds, so i opted to offset the point with 0.1 seconds instead of 1 ns and it works very smoothly.
def shift_robottrajectory(trajectory: RobotTrajectory) -> None:
time_shift_ns = 0
for index, point in enumerate(trajectory.joint_trajectory.points):
if index == 0:
continue
point.time_from_start.nanosec += time_shift_ns
if trajectory.joint_trajectory.points[index-1].time_from_start == point.time_from_start:
# Not sure if this works for seconds rollover but I didn't have any problem
point.time_from_start.nanosec += int(1e8)
time_shift_ns += int(1e8)
Thank you @AGuthmann .
@TheSpeedM just so I understand correctly: offsetting the point with identical time_from_start
and all following points by 0.1 seconds fixed the jittery motion? That's nice to hear!
@ilijaljubicic you're welcome!
@AGuthmann yes you're correct. The Pilz planner generates points at a 0.1s interval, except at the start and end of a blend. So the 'wrong' points - with the same time as the previous points - of a blend have to be offset by 0.1s and all of the following points have to be shifted too (so they won't overlap). This shifting adds up the more points there have to be corrected, see the diagram below.
This issue is being labeled as stale because it has been open 45 days with no activity. It will be automatically closed after another 45 days without follow-ups.
Hi @TheSpeedM. Im trying to reproduce your steps but the code gets stuck on self._plan_action_client.wait_for_server()
Indeed, a ros2 action list
shows there is no /sequence_move_group
being advertised after launching the panda demo file.
I am using humble
, could this be the issue?
I have encountered the same issue as well. There is an ongoing issue at Moveit1 here https://github.com/moveit/moveit/issues/3583.
I could solve it by doing the bypass commented here https://github.com/moveit/moveit/issues/3583#issuecomment-2035540755 and making some changes for ROS2:
// Ensure time_from_start is strictly increasing
double epsilon = 0.01;
for (size_t i = 1; i < plan.trajectory_.joint_trajectory.points.size(); ++i)
{
auto& current_point = plan.trajectory_.joint_trajectory.points[i];
auto& prev_point = plan.trajectory_.joint_trajectory.points[i - 1];
if (current_point.time_from_start == prev_point.time_from_start)
{
// Shift current point by 0.1 seconds (100 milliseconds)
current_point.time_from_start.sec = prev_point.time_from_start.sec;
current_point.time_from_start.nanosec += 100000000;
RCLCPP_WARN(this->get_logger(), "Adjusted time_from_start to be strictly increasing at point %zu", i);
}
}
I do still rarely encounter the issues described in this https://github.com/moveit/moveit/issues/3553 with accelerations when working on the real robot only.
Definitely solving that issue and being able to backport to MoveIt2 would be appreciated.
Description
Using
pilz_industrial_motion_planner
to generate a motionsequence with a blend radius generates (multiple) points with the same value forRobotTrajectory.joint_trajectory.points[].time_from_start
. Looks like it generates two pairs of wrong points per point with a blend.It does generate and execute the trajectory when blend radius is set to 0.0. Had the problem using the Universal_Robots_ROS2_Driver and was able to reproduce it with the MoveIt example robot (used for this bug report).
Also ran into this issue from MoveIt1 while trying to reproduce. Looks related.
Your environment
Steps to reproduce
Send MoveGroupSequence goal to
/sequence_move_group
with a blend radius using the following Python code.Expected behaviour
Generate and execute a trajectory through these points with them blended.
Actual behaviour
Generates the points and sends them to executor, but that throws an error.
Backtrace or Console output
Dirty fix
Set
plan_only
to true and pass the planned_trajectories to the following function before execution. This shifts the generated points with the same time away from eachother by one ns. Trajectory does execute when doing this.