36 #include <rclcpp/logger.hpp> 
   37 #include <rclcpp/logging.hpp> 
   40 #include <Eigen/Geometry> 
   49 const rclcpp::Logger 
LOGGER = rclcpp::get_logger(
"moveit_trajectory_processing.ruckig_traj_smoothing");
 
   50 constexpr 
double DEFAULT_MAX_VELOCITY = 5;       
 
   51 constexpr 
double DEFAULT_MAX_ACCELERATION = 10;  
 
   52 constexpr 
double DEFAULT_MAX_JERK = 1000;        
 
   53 constexpr 
double MAX_DURATION_EXTENSION_FACTOR = 10.0;
 
   54 constexpr 
double DURATION_EXTENSION_FRACTION = 1.1;
 
   58                                      const double max_velocity_scaling_factor,
 
   59                                      const double max_acceleration_scaling_factor)
 
   61   if (!validateGroup(trajectory))
 
   67   if (num_waypoints < 2)
 
   70                 "Trajectory does not have enough points to smooth with Ruckig. Returning an unmodified trajectory.");
 
   76   const size_t num_dof = 
group->getVariableCount();
 
   77   ruckig::InputParameter<ruckig::DynamicDOFs> ruckig_input{ num_dof };
 
   78   if (!getRobotModelBounds(max_velocity_scaling_factor, max_acceleration_scaling_factor, 
group, ruckig_input))
 
   80     RCLCPP_ERROR(LOGGER, 
"Error while retrieving kinematic limits (vel/accel/jerk) from RobotModel.");
 
   84   return runRuckig(trajectory, ruckig_input);
 
   88                                      const std::unordered_map<std::string, double>& velocity_limits,
 
   89                                      const std::unordered_map<std::string, double>& acceleration_limits,
 
   90                                      const std::unordered_map<std::string, double>& jerk_limits)
 
   92   if (!validateGroup(trajectory))
 
   98   if (num_waypoints < 2)
 
  101                 "Trajectory does not have enough points to smooth with Ruckig. Returning an unmodified trajectory.");
 
  107   const size_t num_dof = 
group->getVariableCount();
 
  108   ruckig::InputParameter<ruckig::DynamicDOFs> ruckig_input{ num_dof };
 
  109   double max_velocity_scaling_factor = 1.0;
 
  110   double max_acceleration_scaling_factor = 1.0;
 
  111   if (!getRobotModelBounds(max_velocity_scaling_factor, max_acceleration_scaling_factor, 
group, ruckig_input))
 
  113     RCLCPP_ERROR(LOGGER, 
"Error while retrieving kinematic limits (vel/accel/jerk) from RobotModel.");
 
  118   const std::vector<std::string>& vars = 
group->getVariableNames();
 
  119   const unsigned num_joints = 
group->getVariableCount();
 
  120   for (
size_t j = 0; j < num_joints; ++j)
 
  123     auto it = velocity_limits.find(vars[j]);
 
  124     if (it != velocity_limits.end())
 
  126       ruckig_input.max_velocity.at(j) = it->second;
 
  129     it = acceleration_limits.find(vars[j]);
 
  130     if (it != acceleration_limits.end())
 
  132       ruckig_input.max_acceleration.at(j) = it->second;
 
  135     it = jerk_limits.find(vars[j]);
 
  136     if (it != jerk_limits.end())
 
  138       ruckig_input.max_jerk.at(j) = it->second;
 
  142   return runRuckig(trajectory, ruckig_input);
 
  150     RCLCPP_ERROR(LOGGER, 
"The planner did not set the group the plan was computed for");
 
  156 bool RuckigSmoothing::getRobotModelBounds(
const double max_velocity_scaling_factor,
 
  157                                           const double max_acceleration_scaling_factor,
 
  159                                           ruckig::InputParameter<ruckig::DynamicDOFs>& ruckig_input)
 
  161   const size_t num_dof = 
group->getVariableCount();
 
  162   const std::vector<std::string>& vars = 
group->getVariableNames();
 
  164   for (
size_t i = 0; i < num_dof; ++i)
 
  171       ruckig_input.max_velocity.at(i) = max_velocity_scaling_factor * bounds.
max_velocity_;
 
  175       RCLCPP_WARN_STREAM_ONCE(LOGGER,
 
  176                               "Joint velocity limits are not defined. Using the default " 
  177                                   << DEFAULT_MAX_VELOCITY
 
  178                                   << 
" rad/s. You can define velocity limits in the URDF or joint_limits.yaml.");
 
  179       ruckig_input.max_velocity.at(i) = max_velocity_scaling_factor * DEFAULT_MAX_VELOCITY;
 
  183       ruckig_input.max_acceleration.at(i) = max_acceleration_scaling_factor * bounds.
max_acceleration_;
 
  187       RCLCPP_WARN_STREAM_ONCE(LOGGER,
 
  188                               "Joint acceleration limits are not defined. Using the default " 
  189                                   << DEFAULT_MAX_ACCELERATION
 
  190                                   << 
" rad/s^2. You can define acceleration limits in the URDF or joint_limits.yaml.");
 
  191       ruckig_input.max_acceleration.at(i) = max_acceleration_scaling_factor * DEFAULT_MAX_ACCELERATION;
 
  196       ruckig_input.max_jerk.at(i) = bounds.
max_jerk_;
 
  200       RCLCPP_WARN_STREAM_ONCE(LOGGER, 
"Joint jerk limits are not defined. Using the default " 
  202                                           << 
" rad/s^3. You can define jerk limits in joint_limits.yaml.");
 
  203       ruckig_input.max_jerk.at(i) = DEFAULT_MAX_JERK;
 
  211                                 ruckig::InputParameter<ruckig::DynamicDOFs>& ruckig_input)
 
  215   const size_t num_dof = 
group->getVariableCount();
 
  216   ruckig::OutputParameter<ruckig::DynamicDOFs> ruckig_output{ num_dof };
 
  217   const std::vector<int>& move_group_idx = 
group->getVariableIndexList();
 
  224   std::unique_ptr<ruckig::Ruckig<ruckig::DynamicDOFs>> ruckig_ptr;
 
  225   ruckig_ptr = std::make_unique<ruckig::Ruckig<ruckig::DynamicDOFs>>(num_dof, timestep);
 
  232   ruckig::Result ruckig_result;
 
  233   double duration_extension_factor = 1;
 
  234   bool smoothing_complete = 
false;
 
  235   while ((duration_extension_factor < MAX_DURATION_EXTENSION_FACTOR) && !smoothing_complete)
 
  237     for (
size_t waypoint_idx = 0; waypoint_idx < num_waypoints - 1; ++waypoint_idx)
 
  239       moveit::core::RobotStatePtr next_waypoint = trajectory.
getWayPointPtr(waypoint_idx + 1);
 
  241       getNextRuckigInput(trajectory.
getWayPointPtr(waypoint_idx), next_waypoint, 
group, ruckig_input);
 
  244       ruckig_result = ruckig_ptr->update(ruckig_input, ruckig_output);
 
  246       if ((waypoint_idx == num_waypoints - 2) && ruckig_result == ruckig::Result::Finished)
 
  248         smoothing_complete = 
true;
 
  253       if (ruckig_result != ruckig::Result::Finished)
 
  255         duration_extension_factor *= DURATION_EXTENSION_FRACTION;
 
  258         for (
size_t time_stretch_idx = 1; time_stretch_idx < num_waypoints; ++time_stretch_idx)
 
  265           const auto prev_state = trajectory.
getWayPointPtr(time_stretch_idx - 1);
 
  267           for (
size_t joint = 0; joint < num_dof; ++joint)
 
  269             target_state->setVariableVelocity(move_group_idx.at(joint),
 
  270                                               (1 / duration_extension_factor) *
 
  271                                                   target_state->getVariableVelocity(move_group_idx.at(joint)));
 
  273             double prev_velocity = prev_state->getVariableVelocity(move_group_idx.at(joint));
 
  274             double curr_velocity = target_state->getVariableVelocity(move_group_idx.at(joint));
 
  275             target_state->setVariableAcceleration(move_group_idx.at(joint), (curr_velocity - prev_velocity) / timestep);
 
  277           target_state->update();
 
  279         ruckig_ptr = std::make_unique<ruckig::Ruckig<ruckig::DynamicDOFs>>(num_dof, timestep);
 
  287   if (ruckig_result != ruckig::Result::Finished)
 
  289     RCLCPP_ERROR_STREAM(LOGGER, 
"Ruckig trajectory smoothing failed. Ruckig error: " << ruckig_result);
 
  298                                             ruckig::InputParameter<ruckig::DynamicDOFs>& ruckig_input,
 
  299                                             ruckig::OutputParameter<ruckig::DynamicDOFs>& ruckig_output)
 
  304   std::vector<double> current_positions_vector(num_dof);
 
  305   std::vector<double> current_velocities_vector(num_dof);
 
  306   std::vector<double> current_accelerations_vector(num_dof);
 
  308   for (
size_t i = 0; i < num_dof; ++i)
 
  314     current_velocities_vector.at(i) =
 
  315         std::clamp(current_velocities_vector.at(i), -ruckig_input.max_velocity.at(i), ruckig_input.max_velocity.at(i));
 
  316     current_accelerations_vector.at(i) = std::clamp(
 
  317         current_accelerations_vector.at(i), -ruckig_input.max_acceleration.at(i), ruckig_input.max_acceleration.at(i));
 
  319   std::copy_n(current_positions_vector.begin(), num_dof, ruckig_input.current_position.begin());
 
  320   std::copy_n(current_velocities_vector.begin(), num_dof, ruckig_input.current_velocity.begin());
 
  321   std::copy_n(current_accelerations_vector.begin(), num_dof, ruckig_input.current_acceleration.begin());
 
  323   ruckig_output.new_position = ruckig_input.current_position;
 
  324   ruckig_output.new_velocity = ruckig_input.current_velocity;
 
  325   ruckig_output.new_acceleration = ruckig_input.current_acceleration;
 
  328 void RuckigSmoothing::getNextRuckigInput(
const moveit::core::RobotStatePtr& current_waypoint,
 
  329                                          const moveit::core::RobotStatePtr& next_waypoint,
 
  331                                          ruckig::InputParameter<ruckig::DynamicDOFs>& ruckig_input)
 
  336   for (
size_t joint = 0; joint < num_dof; ++joint)
 
  338     ruckig_input.current_position.at(joint) = current_waypoint->getVariablePosition(idx.at(joint));
 
  339     ruckig_input.current_velocity.at(joint) = current_waypoint->getVariableVelocity(idx.at(joint));
 
  340     ruckig_input.current_acceleration.at(joint) = current_waypoint->getVariableAcceleration(idx.at(joint));
 
  343     ruckig_input.target_position.at(joint) = next_waypoint->getVariablePosition(idx.at(joint));
 
  344     ruckig_input.target_velocity.at(joint) = next_waypoint->getVariableVelocity(idx.at(joint));
 
  345     ruckig_input.target_acceleration.at(joint) = next_waypoint->getVariableAcceleration(idx.at(joint));
 
  348     ruckig_input.current_velocity.at(joint) =
 
  349         std::clamp(ruckig_input.current_velocity.at(joint), -ruckig_input.max_velocity.at(joint),
 
  350                    ruckig_input.max_velocity.at(joint));
 
  351     ruckig_input.current_acceleration.at(joint) =
 
  352         std::clamp(ruckig_input.current_acceleration.at(joint), -ruckig_input.max_acceleration.at(joint),
 
  353                    ruckig_input.max_acceleration.at(joint));
 
  354     ruckig_input.target_velocity.at(joint) =
 
  355         std::clamp(ruckig_input.target_velocity.at(joint), -ruckig_input.max_velocity.at(joint),
 
  356                    ruckig_input.max_velocity.at(joint));
 
  357     ruckig_input.target_acceleration.at(joint) =
 
  358         std::clamp(ruckig_input.target_acceleration.at(joint), -ruckig_input.max_acceleration.at(joint),
 
  359                    ruckig_input.max_acceleration.at(joint));
 
unsigned int getVariableCount() const
Get the number of variables that describe this joint group. This includes variables necessary for mim...
 
const std::vector< int > & getVariableIndexList() const
Get the index locations in the complete robot state for all the variables in this group.
 
Definition of a kinematic model. This class is not thread safe, however multiple instances can be cre...
 
const VariableBounds & getVariableBounds(const std::string &variable) const
Get the bounds for a specific variable. Throw an exception of variable is not found.
 
Representation of a robot's state. This includes position, velocity, acceleration and effort.
 
double getVariableAcceleration(const std::string &variable) const
Get the acceleration of a particular variable. An exception is thrown if the variable is not known.
 
double getVariableVelocity(const std::string &variable) const
Get the velocity of a particular variable. An exception is thrown if the variable is not known.
 
double getVariablePosition(const std::string &variable) const
Get the position of a particular variable. An exception is thrown if the variable is not known.
 
Maintain a sequence of waypoints and the time durations between these waypoints.
 
RobotTrajectory & setWayPointDurationFromPrevious(std::size_t index, double value)
 
double getAverageSegmentDuration() const
 
const moveit::core::JointModelGroup * getGroup() const
 
RobotTrajectory & unwind()
 
moveit::core::RobotStatePtr & getWayPointPtr(std::size_t index)
 
std::size_t getWayPointCount() const
 
double getWayPointDurationFromPrevious(std::size_t index) const
 
moveit::core::RobotStatePtr & getFirstWayPointPtr()
 
static bool applySmoothing(robot_trajectory::RobotTrajectory &trajectory, const double max_velocity_scaling_factor=1.0, const double max_acceleration_scaling_factor=1.0)
 
const rclcpp::Logger LOGGER
 
bool acceleration_bounded_