30 #include <Eigen/Cholesky> 32 #include <stomp_core/utils.h> 49 Eigen::MatrixXd& trajectory_joints)
51 trajectory_joints.setZero(first.size(),num_timesteps);
52 for(
int unsigned i = 0; i < first.size(); i++)
54 double dtheta = (last[i] - first[i])/(num_timesteps - 1);
55 for(
unsigned int j = 0; j < num_timesteps; j++)
57 trajectory_joints(i,j) = first[i] + j * dtheta;
71 int num_points,
double dt,
72 Eigen::MatrixXd& trajectory_joints)
74 std::vector<double> coeffs(4,0);
75 double total_time = (num_points - 1) * dt;
76 for(
int unsigned i = 0; i < first.size(); i++)
79 coeffs[2] = (3/(pow(total_time,2))) * (last[i] - first[i]);
80 coeffs[3] = (-2/(pow(total_time,3))) * (last[i] - first[i]);
83 for(
unsigned j = 0; j < num_points; j++)
86 trajectory_joints(i,j) = coeffs[0] + coeffs[2]*pow(t,2) + coeffs[3]*pow(t,3);
101 const std::vector<double>& last,
102 const Eigen::MatrixXd& control_cost_matrix_R_padded,
103 const Eigen::MatrixXd& inv_control_cost_matrix_R,
104 Eigen::MatrixXd& trajectory_joints)
108 if(control_cost_matrix_R_padded.rows() != control_cost_matrix_R_padded.cols())
110 ROS_ERROR(
"Control Cost Matrix is not square");
115 int timesteps = control_cost_matrix_R_padded.rows() - 2*(FINITE_DIFF_RULE_LENGTH - 1);
116 int start_index_padded = FINITE_DIFF_RULE_LENGTH - 1;
117 int end_index_padded = start_index_padded + timesteps-1;
118 std::vector<Eigen::VectorXd> linear_control_cost(first.size(),Eigen::VectorXd::Zero(timesteps));
119 trajectory_joints.setZero(first.size(),timesteps);
122 for(
unsigned int d = 0;
d < first.size();
d++)
124 linear_control_cost[
d].transpose() = first[
d] * Eigen::VectorXd::Ones(FINITE_DIFF_RULE_LENGTH - 1).transpose() *
125 control_cost_matrix_R_padded.block(0,start_index_padded,FINITE_DIFF_RULE_LENGTH - 1,timesteps);
127 linear_control_cost[
d].transpose() += last[
d] * Eigen::VectorXd::Ones(FINITE_DIFF_RULE_LENGTH - 1).transpose() *
128 control_cost_matrix_R_padded.block(end_index_padded + 1,start_index_padded,FINITE_DIFF_RULE_LENGTH - 1,
131 linear_control_cost[
d] *=2;
133 trajectory_joints.row(
d) = -0.5*inv_control_cost_matrix_R*linear_control_cost[
d];
134 trajectory_joints(
d,0) = first[
d];
135 trajectory_joints(
d,timesteps - 1) = last[
d];
151 double control_cost_weight,
152 const Eigen::MatrixXd& control_cost_matrix_R,
153 Eigen::MatrixXd& control_costs)
155 std::size_t num_timesteps = parameters.cols();
157 for(
auto d = 0u;
d < parameters.rows();
d++)
159 cost = double(parameters.row(
d)*(control_cost_matrix_R*parameters.row(
d).transpose()));
160 control_costs.row(
d).setConstant( 0.5*(1/dt)*cost );
163 double max_coeff = control_costs.maxCoeff();
164 control_costs /= (max_coeff > 1e-8) ? max_coeff : 1;
165 control_costs *= control_cost_weight;
192 bool Stomp::solve(
const std::vector<double>& first,
const std::vector<double>& last,
193 Eigen::MatrixXd& parameters_optimized)
198 ROS_ERROR(
"Unable to generate initial trajectory");
204 bool Stomp::solve(
const Eigen::VectorXd& first,
const Eigen::VectorXd& last,
205 Eigen::MatrixXd& parameters_optimized)
208 std::vector<double> start(first.size());
209 std::vector<double> end(last.size());
211 Eigen::VectorXd::Map(&start[0],first.size()) = first;
212 Eigen::VectorXd::Map(&end[0],last.size()) = last;
214 return solve(start,end,parameters_optimized);
218 Eigen::MatrixXd& parameters_optimized)
228 ROS_ERROR(
"Initial trajectory dimensions is incorrect");
235 ROS_ERROR(
"Initial trajectory number of time steps is incorrect");
241 unsigned int valid_iterations = 0;
247 ROS_ERROR(
"Failed to calculate initial trajectory cost");
260 ROS_DEBUG(
"Found valid solution, will iterate %i more time(s) ",
267 valid_iterations = 0;
280 ROS_INFO(
"STOMP found a valid solution with cost %f after %i iterations",
310 ROS_DEBUG_STREAM(
"'max_rollouts' must be greater than 'num_rollouts_per_iteration'.");
323 rollout.
noise.setZero();
399 case TrajectoryInitializations::CUBIC_POLYNOMIAL_INTERPOLATION:
403 case TrajectoryInitializations::LINEAR_INTERPOLATION:
407 case TrajectoryInitializations::MININUM_CONTROL_COST:
446 std::vector< std::pair<double,int> > rollout_cost_sorter;
449 rollouts_stored = rollouts_stored < 0 ? 0 : rollouts_stored;
451 int rollouts_total = rollouts_generate + rollouts_stored +1;
455 if(rollouts_reuse > 0)
458 double min_cost = std::numeric_limits<double>::max();
459 double max_cost = std::numeric_limits<double>::min();
460 for (
int r=1; r<rollouts_stored; ++r)
469 double cost_denom = max_cost - min_cost;
470 if (cost_denom < 1e-8)
475 double weighted_prob;
476 for (
auto r = 0u; r<rollouts_stored; ++r)
483 cost_prob = exp(-h*(
noisy_rollouts_[r].total_cost - min_cost)/cost_denom);
485 rollout_cost_sorter.push_back(std::make_pair(-weighted_prob,r));
489 std::sort(rollout_cost_sorter.begin(), rollout_cost_sorter.end());
492 for (
auto r = 0u; r<rollouts_stored; ++r)
494 int reuse_index = rollout_cost_sorter[r].second;
499 for (
auto r = 0u; r<rollouts_reuse; ++r)
513 for(
auto r = 0u; r < rollouts_generate; r++)
541 bool filtered =
false;
572 double total_state_cost ;
573 double total_control_cost;
581 total_control_cost = 0;
586 total_control_cost += ccost;
589 rollout.
total_cost = total_state_cost + total_control_cost;
605 bool all_valid =
true;
621 ROS_ERROR(
"Trajectory cost computation failed for rollout %i.",r);
662 double probl_sum = 0.0;
684 denom = max_cost - min_cost;
724 denom = max_cost - min_cost;
753 parameters_updates_.row(
d) += (rollout.noise.row(
d).array() * rollout.probabilities.row(
d).array()).matrix();
761 ROS_ERROR(
"Updates filtering step failed");
std::shared_ptr< Task > TaskPtr
Eigen::MatrixXd finite_diff_matrix_A_padded_
The finite difference matrix including padding.
static void computeCubicInterpolation(const std::vector< double > &first, const std::vector< double > &last, int num_points, double dt, Eigen::MatrixXd &trajectory_joints)
Compute a cubic interpolated trajectory given a start and end state.
int num_rollouts
Number of noisy trajectories.
Eigen::MatrixXd control_cost_matrix_R_padded_
The control cost matrix including padding.
The data structure used to store information about a single rollout.
bool resetVariables()
Reset all internal variables.
int num_active_rollouts_
Number of active rollouts.
Stomp(const StompConfiguration &config, TaskPtr task)
Stomp Constructor.
std::atomic< bool > proceed_
Used to determine if the optimization has been cancelled.
bool runSingleIteration()
Run a single iteration of the stomp algorithm.
int num_timesteps_padded_
The number of timesteps to pad the optimization with: timesteps + 2*(FINITE_DIFF_RULE_LENGTH - 1) ...
bool cancel()
Cancel optimization in progress. (Thread-Safe) This method is thead-safe.
int start_index_padded_
The index corresponding to the start of the non-paded section in the padded arrays.
This contains the stomp core algorithm.
bool generateNoisyRollouts()
Generate a set of noisy rollouts.
Eigen::VectorXd state_costs
A vector [num_time_steps] of the cost at each timestep.
int num_iterations
Maximum number of iteration allowed.
StompConfiguration config_
Configuration parameters.
double control_cost_weight
Percentage of the trajectory accelerations cost to be applied in the total cost calculation > ...
bool computeMinCostTrajectory(const std::vector< double > &first, const std::vector< double > &last, const Eigen::MatrixXd &control_cost_matrix_R_padded, const Eigen::MatrixXd &inv_control_cost_matrix_R, Eigen::MatrixXd &trajectory_joints)
Compute a minimum cost trajectory given a start and end state.
int num_dimensions
Parameter dimensionality.
double exponentiated_cost_sensitivity
Default exponetiated cost sensitivity coefficient.
unsigned int current_iteration_
Current iteration for the optimization.
std::vector< Rollout > noisy_rollouts_
Holds the noisy rollouts.
void setConfig(const StompConfiguration &config)
Sets the configuration and resets all internal variables.
bool computeOptimizedCost()
Computes the optimized trajectory cost [Control Cost + State Cost] If the current cost is not less th...
TaskPtr task_
The task to be optimized.
bool computeRolloutsStateCosts()
Computes the cost at every timestep for each noisy rollout.
Eigen::VectorXd parameters_state_costs_
A vector [timesteps] of the parameters state costs.
bool computeRolloutsControlCosts()
Compute the control cost for each noisy rollout. This is the sum of the acceleration squared...
double parameters_total_cost_
Total cost of the optimized parameters.
Eigen::MatrixXd control_cost_matrix_R_
A matrix [timesteps][timesteps], Referred to as 'R = A x A_transpose' in the literature.
double current_lowest_cost_
Hold the lowest cost of the optimized parameters.
bool filterNoisyRollouts()
Applies the optimization task's filter methods to the noisy trajectories.
Eigen::MatrixXd inv_control_cost_matrix_R_
A matrix [timesteps][timesteps], R^-1 ' matrix.
Eigen::MatrixXd probabilities
A matrix [num_dimensions][num_time_steps] of the probability for each parameter at every timestep...
std::vector< double > full_costs
A vector [num_dimensions] of the full coss, state_cost + control_cost for each joint over the entire ...
static const double MIN_COST_DIFFERENCE
bool computeProbabilities()
Computes the probability from the state cost at every timestep for each noisy rollout.
bool computeInitialTrajectory(const std::vector< double > &first, const std::vector< double > &last)
Computes an inital guess at a solution given a start and end state.
void computeParametersControlCosts(const Eigen::MatrixXd ¶meters, double dt, double control_cost_weight, const Eigen::MatrixXd &control_cost_matrix_R, Eigen::MatrixXd &control_costs)
Compute the parameters control costs.
The data structure used to store STOMP configuration parameters.
#define ROS_DEBUG_STREAM(args)
Eigen::MatrixXd parameters_noise
A matrix [num_dimensions][num_time_steps] of the sum of parameters + noise.
bool solve(const std::vector< double > &first, const std::vector< double > &last, Eigen::MatrixXd ¶meters_optimized)
Find the optimal solution provided a start and end goal.
Eigen::MatrixXd parameters_optimized_
A matrix [dimensions][timesteps] of the optimized parameters.
bool parameters_valid_prev_
whether or not the optimized parameters from the previous iteration are valid
bool clear()
Resets all internal variables.
int initialization_method
TrajectoryInitializations::TrajectoryInitialization.
double importance_weight
importance sampling weight
bool updateParameters()
Computes update from probabilities using convex combination.
double total_cost
combined state + control cost over the entire trajectory for all joints
Eigen::MatrixXd noise
A matrix [num_dimensions][num_time_steps] of random noise applied to the parameters.
bool computeNoisyRolloutsCosts()
Computes the total cost for each of the noisy rollouts.
static const double MIN_CONTROL_COST_WEIGHT
bool parameters_valid_
whether or not the optimized parameters are valid
int max_rollouts
The combined number of new and old rollouts during each iteration shouldn't exceed this value...
#define ROS_ERROR_STREAM(args)
Eigen::MatrixXd parameters_control_costs_
A matrix [dimensions][timesteps] of the parameters control costs.
static void computeLinearInterpolation(const std::vector< double > &first, const std::vector< double > &last, int num_timesteps, Eigen::MatrixXd &trajectory_joints)
Compute a linear interpolated trajectory given a start and end state.
std::vector< double > full_probabilities
A vector [num_dimensions] of the probabilities for the full trajectory.
double delta_t
Time change between consecutive points.
Eigen::MatrixXd total_costs
A matrix [num_dimensions][num_time_steps] of the total cost, where total_cost[d] = state_costs_ + con...
Eigen::MatrixXd parameters_updates_
A matrix [dimensions][timesteps] of the parameter updates.
std::vector< Rollout > reused_rollouts_
Used for reordering arrays based on cost.
int num_iterations_after_valid
Stomp will stop optimizing this many iterations after finding a valid solution.
Eigen::MatrixXd control_costs
A matrix [num_dimensions][num_time_steps] of the control cost for each parameter at every timestep...
int num_timesteps
Number of timesteps.
static const double DEFAULT_NOISY_COST_IMPORTANCE_WEIGHT