Skip to content

Commit

Permalink
Abstract variable bounds functions into variable, fix memetic initial…
Browse files Browse the repository at this point in the history
…ization bug
  • Loading branch information
sea-bass committed Nov 13, 2023
1 parent 6c3f99f commit 9cf7eb7
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 39 deletions.
23 changes: 18 additions & 5 deletions include/pick_ik/robot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,27 @@ namespace pick_ik {

struct Robot {
struct Variable {
/// @brief Min and max position values of the variable.
double min, max;
/// @brief Min, max, and middle position values of the variable.
double min, max, mid;

/// @brief Whether the variable's position is bounded.
bool bounded;

/// @brief The span (min - max) of the variable, or a default value if unbounded.
double span;
/// @brief The half-span (min - max) / 2.0 of the variable, or a default value if unbounded.
double half_span;

double max_velocity_rcp;
double minimal_displacement_factor;

/// @brief Generates a valid variable value given an optional initial value (for unbounded
/// joints).
auto generate_valid_value(double init_val = 0.0) const -> double;

/// @brief Returns true if a value is valid given the variable bounds.
auto is_valid(double val) const -> bool;

/// @brief Clamps a configuration to joint limits.
auto clamp_to_limits(double val) const -> double;
};
std::vector<Variable> variables;

Expand All @@ -32,7 +42,10 @@ struct Robot {
moveit::core::JointModelGroup const* jmg,
std::vector<size_t> tip_link_indices) -> Robot;

/** @brief Sets a variable vector to a random valid configuration. */
/**
* @brief Sets a variable vector to a random configuration.
* @details Here, "valid" denotes that the joint values are with their specified limits.
*/
auto set_random_valid_configuration(std::vector<double>& config) const -> void;

/** @brief Check is a configuration is valid. */
Expand Down
8 changes: 4 additions & 4 deletions src/goal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ auto make_avoid_joint_limits_cost_fn(Robot robot) -> CostFn {

auto const position = active_positions[i];
auto const weight = variable.minimal_displacement_factor;
auto const mid = (variable.min + variable.max) * 0.5;
auto const span = variable.span;
sum +=
std::pow(std::fmax(0.0, std::fabs(position - mid) * 2.0 - span * 0.5) * weight, 2);
sum += std::pow(
std::fmax(0.0, std::fabs(position - variable.mid) * 2.0 - variable.half_span) *
weight,
2);
}
return sum;
};
Expand Down
8 changes: 1 addition & 7 deletions src/ik_gradient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,7 @@ auto step(GradientIk& self, Robot const& robot, CostFn const& cost_fn, double st
for (size_t i = 0; i < count; ++i) {
auto const& var = robot.variables[i];
auto updated_value = self.local[i] - self.gradient[i] * joint_diff;
if (var.bounded) {
self.working[i] = std::clamp(updated_value, var.min, var.max);
} else {
self.working[i] = std::clamp(updated_value,
self.local[i] - var.span / 2.0,
self.local[i] + var.span / 2.0);
}
self.working[i] = var.clamp_to_limits(updated_value);
}

// Always accept the solution and continue
Expand Down
14 changes: 6 additions & 8 deletions src/ik_memetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ void MemeticIk::initPopulation(Robot const& robot,
population_[i] = Individual{initial_guess, 0.0, 1.0, zero_grad};
}

// Initialize fitnesses and extinctions
for (auto& individual : population_) {
individual.fitness = cost_fn(individual.genes);
}
computeExtinctions();
previous_fitness_.reset();
}
Expand Down Expand Up @@ -152,17 +156,11 @@ void MemeticIk::reproduce(Robot const& robot, CostFn const& cost_fn) {

// Mutate
if (rsl::uniform_real(0.0, 1.0) < mutation_prob) {
gene += extinction * joint.span * rsl::uniform_real(-0.5, 0.5);
gene += extinction * joint.half_span * rsl::uniform_real(-1.0, 1.0);
}

// Clamp to valid joint values
if (joint.bounded) {
gene = std::clamp(gene, joint.min, joint.max);
} else {
gene = std::clamp(gene,
original_gene - joint.span / 2.0,
original_gene + joint.span / 2.0);
}
gene = robot.variables[j_idx].clamp_to_limits(gene);

// Approximate gradient
population_[i].gradient[j_idx] = gene - original_gene;
Expand Down
41 changes: 26 additions & 15 deletions src/robot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,33 @@
#include <moveit/robot_state/robot_state.h>

namespace {
constexpr double kUnboundedVariableSpan = 2.0 * M_PI;
constexpr double kUnboundedVariableHalfSpan = M_PI;
constexpr double kUnboundedJointSampleSpread = M_PI;
} // namespace

namespace pick_ik {

auto Robot::Variable::generate_valid_value(double init_val /* = 0.0*/) const -> double {
if (bounded) {
return rsl::uniform_real(min, max);
} else {
return rsl::uniform_real(init_val - kUnboundedJointSampleSpread,
init_val + kUnboundedJointSampleSpread);
}
}

auto Robot::Variable::is_valid(double val) const -> bool {
return (!bounded) || (val <= max && val >= min);
}

auto Robot::Variable::clamp_to_limits(double val) const -> double {
if (bounded) {
return std::clamp(val, min, max);
} else {
return std::clamp(val, val - half_span, val + half_span);
}
}

auto Robot::from(std::shared_ptr<moveit::core::RobotModel const> const& model,
moveit::core::JointModelGroup const* jmg,
std::vector<size_t> tip_link_indices) -> Robot {
Expand All @@ -41,8 +62,8 @@ auto Robot::from(std::shared_ptr<moveit::core::RobotModel const> const& model,
var.bounded = bounds.position_bounded_;
var.min = bounds.min_position_;
var.max = bounds.max_position_;

var.span = var.bounded ? var.max - var.min : kUnboundedVariableSpan;
var.mid = 0.5 * (var.min + var.max);
var.half_span = var.bounded ? (var.max - var.min) / 2.0 : kUnboundedVariableHalfSpan;

auto const max_velocity = bounds.max_velocity_;
var.max_velocity_rcp = max_velocity > 0.0 ? 1.0 / max_velocity : 0.0;
Expand All @@ -69,24 +90,14 @@ auto Robot::set_random_valid_configuration(std::vector<double>& config) const ->
config.resize(num_vars);
}
for (size_t idx = 0; idx < num_vars; ++idx) {
auto const& var = variables[idx];
if (var.bounded) {
config[idx] = rsl::uniform_real(var.min, var.max);
} else {
config[idx] = rsl::uniform_real(config[idx] - kUnboundedJointSampleSpread,
config[idx] + kUnboundedJointSampleSpread);
}
config[idx] = variables[idx].generate_valid_value(config[idx]);
}
}

auto Robot::is_valid_configuration(std::vector<double> const& config) const -> bool {
auto const num_vars = variables.size();
for (size_t idx = 0; idx < num_vars; ++idx) {
auto const var = variables[idx];
if (!var.bounded) {
continue;
}
if (config[idx] > var.max || config[idx] < var.min) {
if (!variables[idx].is_valid(config[idx])) {
return false;
}
}
Expand Down

0 comments on commit 9cf7eb7

Please sign in to comment.