Skip to content
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 velocity and acceleration scaling when using custom limits in Time Parameterization #1832

Merged
merged 7 commits into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,44 @@ namespace trajectory_processing
class RuckigSmoothing
{
public:
/**
* \brief Apply smoothing to a time-parameterized trajectory so that jerk limits are not violated.
* \param[in,out] trajectory A path which needs smoothing.
* \param max_velocity_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
* \param max_acceleration_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
*/
static bool applySmoothing(robot_trajectory::RobotTrajectory& trajectory,
const double max_velocity_scaling_factor = 1.0,
const double max_acceleration_scaling_factor = 1.0);

/**
* \brief Apply smoothing to a time-parameterized trajectory so that jerk limits are not violated.
* \param[in,out] trajectory A path which needs smoothing.
* \param velocity_limits Joint names and velocity limits in rad/s
* \param acceleration_limits Joint names and acceleration limits in rad/s^2
* \param jerk_limits Joint names and jerk limits in rad/s^3
* \param max_velocity_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
* \param max_acceleration_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
*/
static bool applySmoothing(robot_trajectory::RobotTrajectory& trajectory,
const std::unordered_map<std::string, double>& velocity_limits,
const std::unordered_map<std::string, double>& acceleration_limits,
const std::unordered_map<std::string, double>& jerk_limits);
const std::unordered_map<std::string, double>& jerk_limits,
const double max_velocity_scaling_factor = 1.0,
const double max_acceleration_scaling_factor = 1.0);

/**
* \brief Apply smoothing to a time-parameterized trajectory so that jerk limits are not violated.
* \param[in,out] trajectory A path which needs smoothing.
* \param joint_limits Joint names and corresponding velocity limits in rad/s, acceleration limits in rad/s^2,
* and jerk limits in rad/s^3
* \param max_velocity_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
* \param max_acceleration_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
*/
static bool applySmoothing(robot_trajectory::RobotTrajectory& trajectory,
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
const std::vector<moveit_msgs::msg::JointLimits>& joint_limits,
const double max_velocity_scaling_factor = 1.0,
const double max_acceleration_scaling_factor = 1.0);

private:
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@

namespace trajectory_processing
{
enum LimitType
{
VELOCITY,
ACCELERATION
};

const std::unordered_map<LimitType, std::string> LIMIT_TYPES = { { VELOCITY, "velocity" },
{ ACCELERATION, "acceleration" } };
class PathSegment
{
public:
Expand Down Expand Up @@ -196,11 +204,35 @@ class TimeOptimalTrajectoryGeneration : public TimeParameterization
* time-parameterized; this function will re-time-parameterize it.
* \param velocity_limits Joint names and velocity limits in rad/s
* \param acceleration_limits Joint names and acceleration limits in rad/s^2
* \param max_velocity_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
* \param max_acceleration_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
*/
// clang-format on
bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory,
const std::unordered_map<std::string, double>& velocity_limits,
const std::unordered_map<std::string, double>& acceleration_limits) const override;
const std::unordered_map<std::string, double>& acceleration_limits,
const double max_velocity_scaling_factor = 1.0,
const double max_acceleration_scaling_factor = 1.0) const override;

// clang-format off
/**
* \brief Compute a trajectory with waypoints spaced equally in time (according to resample_dt_).
* Resampling the trajectory doesn't change the start and goal point,
* and all re-sampled waypoints will be on the path of the original trajectory (within path_tolerance_).
* However, controller execution is separate from MoveIt and may deviate from the intended path between waypoints.
* path_tolerance_ is defined in configuration space, so the unit is rad for revolute joints,
* meters for prismatic joints.
* \param[in,out] trajectory A path which needs time-parameterization. It's OK if this path has already been
* time-parameterized; this function will re-time-parameterize it.
* \param joint_limits Joint names and corresponding velocity limits in rad/s and acceleration limits in rad/s^2
* \param max_velocity_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
* \param max_acceleration_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
*/
// clang-format on
bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory,
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
const std::vector<moveit_msgs::msg::JointLimits>& joint_limits,
const double max_velocity_scaling_factor = 1.0,
const double max_acceleration_scaling_factor = 1.0) const override;

private:
bool doTimeParameterizationCalculations(robot_trajectory::RobotTrajectory& trajectory,
Expand All @@ -214,6 +246,15 @@ class TimeOptimalTrajectoryGeneration : public TimeParameterization
*/
bool hasMixedJointTypes(const moveit::core::JointModelGroup* group) const;

/**
* @brief Check if the max scaling factor is valid and if not, set it to the specified default value
* \param[in,out] scaling_factor The default scaling factor that should be applied
* if the `max_scaling_factor` is invalid
* \param max_scaling_factor The desired maximum scaling factor to apply to the velocity or acceleration limits
* \param limit_type Whether the velocity or acceleration scaling factor is being verified
*/
void verifyScalingFactor(double& scaling_factor, const double max_scaling_factor, const LimitType limit_type) const;
mechwiz marked this conversation as resolved.
Show resolved Hide resolved

const double path_tolerance_;
const double resample_dt_;
const double min_angle_change_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,44 @@ class TimeParameterization
{
public:
virtual ~TimeParameterization() = default;

/**
* \brief Compute a trajectory with waypoints spaced equally in time
* \param[in,out] trajectory A path which needs time-parameterization. It's OK if this path has already been
* time-parameterized; this function will re-time-parameterize it.
* \param max_velocity_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
* \param max_acceleration_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
*/
virtual bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory,
const double max_velocity_scaling_factor = 1.0,
const double max_acceleration_scaling_factor = 1.0) const = 0;

/**
* \brief Compute a trajectory with waypoints spaced equally in time
* \param[in,out] trajectory A path which needs time-parameterization. It's OK if this path has already been
* time-parameterized; this function will re-time-parameterize it.
* \param velocity_limits Joint names and velocity limits in rad/s
* \param acceleration_limits Joint names and acceleration limits in rad/s^2
* \param max_velocity_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
* \param max_acceleration_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
*/
virtual bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory,
const std::unordered_map<std::string, double>& velocity_limits,
const std::unordered_map<std::string, double>& acceleration_limits) const = 0;
const std::unordered_map<std::string, double>& acceleration_limits,
const double max_velocity_scaling_factor = 1.0,
const double max_acceleration_scaling_factor = 1.0) const = 0;

/**
* \brief Compute a trajectory with waypoints spaced equally in time
* \param[in,out] trajectory A path which needs time-parameterization. It's OK if this path has already been
* time-parameterized; this function will re-time-parameterize it.
* \param joint_limits Joint names and corresponding velocity limits in rad/s and acceleration limits in rad/s^2
* \param max_velocity_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
* \param max_acceleration_scaling_factor A factor in the range [0,1] which can slow down the trajectory.
*/
virtual bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory,
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
const std::vector<moveit_msgs::msg::JointLimits>& joint_limits,
const double max_velocity_scaling_factor = 1.0,
const double max_acceleration_scaling_factor = 1.0) const = 0;
};
} // namespace trajectory_processing
37 changes: 32 additions & 5 deletions moveit_core/trajectory_processing/src/ruckig_traj_smoothing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ bool RuckigSmoothing::applySmoothing(robot_trajectory::RobotTrajectory& trajecto
bool RuckigSmoothing::applySmoothing(robot_trajectory::RobotTrajectory& trajectory,
const std::unordered_map<std::string, double>& velocity_limits,
const std::unordered_map<std::string, double>& acceleration_limits,
const std::unordered_map<std::string, double>& jerk_limits)
const std::unordered_map<std::string, double>& jerk_limits,
const double max_velocity_scaling_factor,
const double max_acceleration_scaling_factor)
{
if (!validateGroup(trajectory))
{
Expand All @@ -111,8 +113,6 @@ bool RuckigSmoothing::applySmoothing(robot_trajectory::RobotTrajectory& trajecto
moveit::core::JointModelGroup const* const group = trajectory.getGroup();
const size_t num_dof = group->getVariableCount();
ruckig::InputParameter<ruckig::DynamicDOFs> ruckig_input{ num_dof };
double max_velocity_scaling_factor = 1.0;
double max_acceleration_scaling_factor = 1.0;
if (!getRobotModelBounds(max_velocity_scaling_factor, max_acceleration_scaling_factor, group, ruckig_input))
{
RCLCPP_ERROR(LOGGER, "Error while retrieving kinematic limits (vel/accel/jerk) from RobotModel.");
Expand All @@ -128,13 +128,13 @@ bool RuckigSmoothing::applySmoothing(robot_trajectory::RobotTrajectory& trajecto
auto it = velocity_limits.find(vars[j]);
if (it != velocity_limits.end())
{
ruckig_input.max_velocity.at(j) = it->second;
ruckig_input.max_velocity.at(j) = it->second * max_velocity_scaling_factor;
}
// Acceleration
it = acceleration_limits.find(vars[j]);
if (it != acceleration_limits.end())
{
ruckig_input.max_acceleration.at(j) = it->second;
ruckig_input.max_acceleration.at(j) = it->second * max_acceleration_scaling_factor;
}
// Jerk
it = jerk_limits.find(vars[j]);
Expand Down Expand Up @@ -213,6 +213,33 @@ RuckigSmoothing::runRuckigInBatches(const size_t num_waypoints, const robot_traj
return std::make_optional<robot_trajectory::RobotTrajectory>(output_trajectory, true /* deep copy */);
}

bool RuckigSmoothing::applySmoothing(robot_trajectory::RobotTrajectory& trajectory,
const std::vector<moveit_msgs::msg::JointLimits>& joint_limits,
const double max_velocity_scaling_factor,
const double max_acceleration_scaling_factor)
{
std::unordered_map<std::string, double> velocity_limits;
std::unordered_map<std::string, double> acceleration_limits;
std::unordered_map<std::string, double> jerk_limits;
for (const auto& limit : joint_limits)
{
if (limit.has_velocity_limits)
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
{
velocity_limits[limit.joint_name] = limit.max_velocity;
}
if (limit.has_acceleration_limits)
{
acceleration_limits[limit.joint_name] = limit.max_acceleration;
}
if (limit.has_jerk_limits)
{
jerk_limits[limit.joint_name] = limit.max_jerk;
}
}
return applySmoothing(trajectory, velocity_limits, acceleration_limits, jerk_limits, max_velocity_scaling_factor,
max_acceleration_scaling_factor);
}

bool RuckigSmoothing::validateGroup(const robot_trajectory::RobotTrajectory& trajectory)
{
moveit::core::JointModelGroup const* const group = trajectory.getGroup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -881,36 +881,10 @@ bool TimeOptimalTrajectoryGeneration::computeTimeStamps(robot_trajectory::RobotT

// Validate scaling
double velocity_scaling_factor = 1.0;
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
if (max_velocity_scaling_factor > 0.0 && max_velocity_scaling_factor <= 1.0)
{
velocity_scaling_factor = max_velocity_scaling_factor;
}
else if (max_velocity_scaling_factor == 0.0)
{
RCLCPP_DEBUG(LOGGER, "A max_velocity_scaling_factor of 0.0 was specified, defaulting to %f instead.",
velocity_scaling_factor);
}
else
{
RCLCPP_WARN(LOGGER, "Invalid max_velocity_scaling_factor %f specified, defaulting to %f instead.",
max_velocity_scaling_factor, velocity_scaling_factor);
}
verifyScalingFactor(velocity_scaling_factor, max_velocity_scaling_factor, VELOCITY);

double acceleration_scaling_factor = 1.0;
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
if (max_acceleration_scaling_factor > 0.0 && max_acceleration_scaling_factor <= 1.0)
{
acceleration_scaling_factor = max_acceleration_scaling_factor;
}
else if (max_acceleration_scaling_factor == 0.0)
{
RCLCPP_DEBUG(LOGGER, "A max_acceleration_scaling_factor of 0.0 was specified, defaulting to %f instead.",
acceleration_scaling_factor);
}
else
{
RCLCPP_WARN(LOGGER, "Invalid max_acceleration_scaling_factor %f specified, defaulting to %f instead.",
max_acceleration_scaling_factor, acceleration_scaling_factor);
}
verifyScalingFactor(acceleration_scaling_factor, max_acceleration_scaling_factor, ACCELERATION);

const std::vector<std::string>& vars = group->getVariableNames();
const moveit::core::RobotModel& rmodel = group->getParentModel();
Expand Down Expand Up @@ -967,9 +941,32 @@ bool TimeOptimalTrajectoryGeneration::computeTimeStamps(robot_trajectory::RobotT
return doTimeParameterizationCalculations(trajectory, max_velocity, max_acceleration);
}

bool TimeOptimalTrajectoryGeneration::computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory,
const std::vector<moveit_msgs::msg::JointLimits>& joint_limits,
const double max_velocity_scaling_factor,
const double max_acceleration_scaling_factor) const
{
std::unordered_map<std::string, double> velocity_limits;
std::unordered_map<std::string, double> acceleration_limits;
for (const auto& limit : joint_limits)
{
if (limit.has_velocity_limits)
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
{
velocity_limits[limit.joint_name] = limit.max_velocity;
}
if (limit.has_acceleration_limits)
{
acceleration_limits[limit.joint_name] = limit.max_acceleration;
}
}
return computeTimeStamps(trajectory, velocity_limits, acceleration_limits, max_velocity_scaling_factor,
max_acceleration_scaling_factor);
}

bool TimeOptimalTrajectoryGeneration::computeTimeStamps(
robot_trajectory::RobotTrajectory& trajectory, const std::unordered_map<std::string, double>& velocity_limits,
const std::unordered_map<std::string, double>& acceleration_limits) const
const std::unordered_map<std::string, double>& acceleration_limits, const double max_velocity_scaling_factor,
const double max_acceleration_scaling_factor) const
{
if (trajectory.empty())
return true;
Expand All @@ -981,6 +978,14 @@ bool TimeOptimalTrajectoryGeneration::computeTimeStamps(
RCLCPP_ERROR(LOGGER, "It looks like the planner did not set the group the plan was computed for");
return false;
}

// Validate scaling
double velocity_scaling_factor = 1.0;
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
verifyScalingFactor(velocity_scaling_factor, max_velocity_scaling_factor, VELOCITY);

double acceleration_scaling_factor = 1.0;
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
verifyScalingFactor(acceleration_scaling_factor, max_acceleration_scaling_factor, ACCELERATION);

const unsigned num_joints = group->getVariableCount();
const std::vector<std::string>& vars = group->getVariableNames();
const moveit::core::RobotModel& rmodel = group->getParentModel();
Expand All @@ -997,7 +1002,7 @@ bool TimeOptimalTrajectoryGeneration::computeTimeStamps(
auto it = velocity_limits.find(vars[j]);
if (it != velocity_limits.end())
{
max_velocity[j] = it->second;
max_velocity[j] = it->second * velocity_scaling_factor;
set_velocity_limit = true;
}

Expand All @@ -1010,7 +1015,8 @@ bool TimeOptimalTrajectoryGeneration::computeTimeStamps(
bounds.max_velocity_, vars[j].c_str());
return false;
}
max_velocity[j] = std::min(std::fabs(bounds.max_velocity_), std::fabs(bounds.min_velocity_));
max_velocity[j] =
std::min(std::fabs(bounds.max_velocity_), std::fabs(bounds.min_velocity_)) * velocity_scaling_factor;
set_velocity_limit = true;
}

Expand All @@ -1029,7 +1035,7 @@ bool TimeOptimalTrajectoryGeneration::computeTimeStamps(
it = acceleration_limits.find(vars[j]);
if (it != acceleration_limits.end())
{
max_acceleration[j] = it->second;
max_acceleration[j] = it->second * acceleration_scaling_factor;
set_acceleration_limit = true;
}

Expand All @@ -1042,7 +1048,8 @@ bool TimeOptimalTrajectoryGeneration::computeTimeStamps(
bounds.max_acceleration_, vars[j].c_str());
return false;
}
max_acceleration[j] = std::min(std::fabs(bounds.max_acceleration_), std::fabs(bounds.min_acceleration_));
max_acceleration[j] = std::min(std::fabs(bounds.max_acceleration_), std::fabs(bounds.min_acceleration_)) *
acceleration_scaling_factor;
set_acceleration_limit = true;
}
if (!set_acceleration_limit)
Expand Down Expand Up @@ -1203,4 +1210,31 @@ bool TimeOptimalTrajectoryGeneration::hasMixedJointTypes(const moveit::core::Joi

return have_prismatic && have_revolute;
}

void TimeOptimalTrajectoryGeneration::verifyScalingFactor(double& scaling_factor, const double max_scaling_factor,
const LimitType limit_type) const
{
std::string limit_type_str;
auto limit_type_it = LIMIT_TYPES.find(limit_type);
mechwiz marked this conversation as resolved.
Show resolved Hide resolved

if (limit_type_it != LIMIT_TYPES.end())
{
limit_type_str = limit_type_it->second + "_";
}

if (max_scaling_factor > 0.0 && max_scaling_factor <= 1.0)
{
scaling_factor = max_scaling_factor;
}
else if (max_scaling_factor == 0.0)
{
RCLCPP_DEBUG(LOGGER, "A max_%sscaling_factor of 0.0 was specified, defaulting to %f instead.",
limit_type_str.c_str(), scaling_factor);
}
else
{
RCLCPP_WARN(LOGGER, "Invalid max_%sscaling_factor %f specified, defaulting to %f instead.", limit_type_str.c_str(),
max_scaling_factor, scaling_factor);
}
mechwiz marked this conversation as resolved.
Show resolved Hide resolved
}
} // namespace trajectory_processing