stomp_3dof.cpp
Go to the documentation of this file.
1 
26 #include <iostream>
27 #include <Eigen/Dense>
28 #include <gtest/gtest.h>
29 #include "stomp_core/stomp.h"
30 #include "stomp_core/task.h"
31 
32 using Trajectory = Eigen::MatrixXd;
34 const std::size_t NUM_DIMENSIONS = 3;
35 const std::size_t NUM_TIMESTEPS = 20;
36 const double DELTA_T = 0.1;
37 const std::vector<double> START_POS = {1.4, 1.4, 0.5};
38 const std::vector<double> END_POS = {-1.25, 1.0, -0.26};
39 const std::vector<double> BIAS_THRESHOLD = {0.050,0.050,0.050};
40 const std::vector<double> STD_DEV = {1.0, 1.0, 1.0};
43 using namespace stomp_core;
44 
46 class DummyTask: public Task
47 {
48 public:
55  DummyTask(const Trajectory& parameters_bias,
56  const std::vector<double>& bias_thresholds,
57  const std::vector<double>& std_dev):
58  parameters_bias_(parameters_bias),
59  bias_thresholds_(bias_thresholds),
60  std_dev_(std_dev)
61  {
62 
63  // generate smoothing matrix
64  int num_timesteps = parameters_bias.cols();
65  generateSmoothingMatrix(num_timesteps,1.0,smoothing_M_);
66  srand(1);
67 
68  }
69 
71  bool generateNoisyParameters(const Eigen::MatrixXd& parameters,
72  std::size_t start_timestep,
73  std::size_t num_timesteps,
74  int iteration_number,
75  int rollout_number,
76  Eigen::MatrixXd& parameters_noise,
77  Eigen::MatrixXd& noise) override
78  {
79  double rand_noise;
80  for(std::size_t d = 0; d < parameters.rows(); d++)
81  {
82  for(std::size_t t = 0; t < parameters.cols(); t++)
83  {
84  rand_noise = static_cast<double>(rand()%RAND_MAX)/static_cast<double>(RAND_MAX - 1); // 0 to 1
85  rand_noise = 2*(0.5 - rand_noise);
86  noise(d,t) = rand_noise*std_dev_[d];
87  }
88  }
89 
90  parameters_noise = parameters + noise;
91 
92  return true;
93  }
94 
95  bool computeCosts(const Trajectory& parameters,
96  std::size_t start_timestep,
97  std::size_t num_timesteps,
98  int iteration_number,
99  Eigen::VectorXd& costs,
100  bool& validity) override
101  {
102  return computeNoisyCosts(parameters,start_timestep,num_timesteps,iteration_number,-1,costs,validity);
103  }
104 
105  bool computeNoisyCosts(const Trajectory& parameters,
106  std::size_t start_timestep,
107  std::size_t num_timesteps,
108  int iteration_number,
109  int rollout_number,
110  Eigen::VectorXd& costs,
111  bool& validity) override
112  {
113  costs.setZero(num_timesteps);
114  double diff;
115  double cost = 0.0;
116  validity = true;
117 
118  for(std::size_t t = 0u; t < num_timesteps; t++)
119  {
120  cost = 0;
121  for(std::size_t d = 0u; d < parameters.rows() ; d++)
122  {
123 
124  diff = std::abs(parameters(d,t) - parameters_bias_(d,t));
125  if( diff > std::abs(bias_thresholds_[d]))
126  {
127  cost += diff;
128  validity = false;
129  }
130  }
131 
132  costs(t) = cost;
133  }
134 
135  return true;
136  }
137 
138 
139  bool filterParameterUpdates(std::size_t start_timestep,
140  std::size_t num_timesteps,
141  int iteration_number,
142  const Eigen::MatrixXd& parameters,
143  Eigen::MatrixXd& updates) override
144  {
145  return smoothParameterUpdates(start_timestep,num_timesteps,iteration_number,updates);
146  }
147 
148 
149 protected:
150 
159  bool smoothParameterUpdates(std::size_t start_timestep,
160  std::size_t num_timesteps,
161  int iteration_number,
162  Eigen::MatrixXd& updates)
163  {
164 
165  for(auto d = 0u; d < updates.rows(); d++)
166  {
167  updates.row(d).transpose() = smoothing_M_*(updates.row(d).transpose());
168  }
169 
170  return true;
171  }
172 
173 protected:
174 
176  std::vector<double> bias_thresholds_;
177  std::vector<double> std_dev_;
178  Eigen::MatrixXd smoothing_M_;
179 };
180 
188 bool compareDiff(const Trajectory& optimized, const Trajectory& desired,
189  const std::vector<double>& thresholds)
190 {
191  auto num_dimensions = optimized.rows();
192  Trajectory diff = Trajectory::Zero(num_dimensions,optimized.cols());
193  for(auto d = 0u;d < num_dimensions ; d++)
194  {
195  diff.row(d) = optimized.row(d)- desired.row(d);
196  diff.row(d).cwiseAbs();
197  if((diff.row(d).array() > thresholds[d] ).any() )
198  {
199  return false;
200  }
201  }
202 
203  return true;
204 }
205 
211 {
214  c.num_iterations = 40;
216  c.delta_t = DELTA_T;
217  c.control_cost_weight = 0.0;
218  c.initialization_method = TrajectoryInitializations::LINEAR_INTERPOLATION;
220  c.num_rollouts = 20;
221  c.max_rollouts = 20;
222 
223  return c;
224 }
225 
233 void interpolate(const std::vector<double>& start, const std::vector<double>& end,
234  std::size_t num_timesteps, Trajectory& traj)
235 {
236  auto dimensions = start.size();
237  traj = Eigen::MatrixXd::Zero(dimensions,num_timesteps);
238  for(auto d = 0u; d < dimensions; d++)
239  {
240  double delta = (end[d] - start[d])/(num_timesteps - 1);
241  for(auto t = 0u; t < num_timesteps; t++)
242  {
243  traj(d,t) = start[d] + t*delta;
244  }
245  }
246 }
247 
249 TEST(Stomp3DOF,construction)
250 {
251  Trajectory trajectory_bias;
252  interpolate(START_POS,END_POS,NUM_TIMESTEPS,trajectory_bias);
253  TaskPtr task(new DummyTask(trajectory_bias,BIAS_THRESHOLD,STD_DEV));
254 
255  Stomp stomp(create3DOFConfiguration(),task);
256 }
257 
259 TEST(Stomp3DOF,solve_default)
260 {
261  Trajectory trajectory_bias;
262  interpolate(START_POS,END_POS,NUM_TIMESTEPS,trajectory_bias);
263  TaskPtr task(new DummyTask(trajectory_bias,BIAS_THRESHOLD,STD_DEV));
264 
266  Stomp stomp(config,task);
267 
268  Trajectory optimized;
269  stomp.solve(START_POS,END_POS,optimized);
270 
271  EXPECT_EQ(optimized.rows(),NUM_DIMENSIONS);
272  EXPECT_EQ(optimized.cols(),NUM_TIMESTEPS);
273  EXPECT_TRUE(compareDiff(optimized,trajectory_bias,BIAS_THRESHOLD));
274 
275  // calculate difference
276  Trajectory diff;
277  diff = trajectory_bias - optimized;
278 
279  std::string line_separator = "\n------------------------------------------------------\n";
280  std::cout<<line_separator;
281  std::cout<<stomp_core::toString(trajectory_bias);
282  std::cout<<line_separator;
283  std::cout<<toString(optimized)<<"\n";
284  std::cout<<"Differences"<<"\n"<<toString(diff)<<line_separator;
285 }
286 
288 TEST(Stomp3DOF,solve_interpolated_initial)
289 {
290  Trajectory trajectory_bias;
291  interpolate(START_POS,END_POS,NUM_TIMESTEPS,trajectory_bias);
292  TaskPtr task(new DummyTask(trajectory_bias,BIAS_THRESHOLD,STD_DEV));
293 
295  config.initialization_method = TrajectoryInitializations::LINEAR_INTERPOLATION;
296  Stomp stomp(config,task);
297 
298  Trajectory optimized;
299  stomp.solve(trajectory_bias,optimized);
300 
301  EXPECT_EQ(optimized.rows(),NUM_DIMENSIONS);
302  EXPECT_EQ(optimized.cols(),NUM_TIMESTEPS);
303  EXPECT_TRUE(compareDiff(optimized,trajectory_bias,BIAS_THRESHOLD));
304 
305  // calculate difference
306  Trajectory diff;
307  diff = trajectory_bias - optimized;
308 
309  std::string line_separator = "\n------------------------------------------------------\n";
310  std::cout<<line_separator;
311  std::cout<<stomp_core::toString(trajectory_bias);
312  std::cout<<line_separator;
313  std::cout<<toString(optimized)<<"\n";
314  std::cout<<"Differences"<<"\n"<<toString(diff)<<line_separator;
315 }
316 
318 TEST(Stomp3DOF,solve_cubic_polynomial_initial)
319 {
320  Trajectory trajectory_bias;
321  interpolate(START_POS,END_POS,NUM_TIMESTEPS,trajectory_bias);
322  TaskPtr task(new DummyTask(trajectory_bias,BIAS_THRESHOLD,STD_DEV));
323 
325  config.initialization_method = TrajectoryInitializations::CUBIC_POLYNOMIAL_INTERPOLATION;
326  Stomp stomp(config,task);
327 
328  Trajectory optimized;
329  stomp.solve(trajectory_bias,optimized);
330 
331  EXPECT_EQ(optimized.rows(),NUM_DIMENSIONS);
332  EXPECT_EQ(optimized.cols(),NUM_TIMESTEPS);
333  EXPECT_TRUE(compareDiff(optimized,trajectory_bias,BIAS_THRESHOLD));
334 
335  // calculate difference
336  Trajectory diff;
337  diff = trajectory_bias - optimized;
338 
339  std::string line_separator = "\n------------------------------------------------------\n";
340  std::cout<<line_separator;
341  std::cout<<stomp_core::toString(trajectory_bias);
342  std::cout<<line_separator;
343  std::cout<<toString(optimized)<<"\n";
344  std::cout<<"Differences"<<"\n"<<toString(diff)<<line_separator;
345 }
346 
348 TEST(Stomp3DOF,solve_min_control_cost_initial)
349 {
350  Trajectory trajectory_bias;
351  interpolate(START_POS,END_POS,NUM_TIMESTEPS,trajectory_bias);
352  TaskPtr task(new DummyTask(trajectory_bias,BIAS_THRESHOLD,STD_DEV));
353 
355  config.initialization_method = TrajectoryInitializations::MININUM_CONTROL_COST;
356  Stomp stomp(config,task);
357 
358  Trajectory optimized;
359  stomp.solve(trajectory_bias,optimized);
360 
361  EXPECT_EQ(optimized.rows(),NUM_DIMENSIONS);
362  EXPECT_EQ(optimized.cols(),NUM_TIMESTEPS);
363  EXPECT_TRUE(compareDiff(optimized,trajectory_bias,BIAS_THRESHOLD));
364 
365  // calculate difference
366  Trajectory diff;
367  diff = trajectory_bias - optimized;
368 
369  std::string line_separator = "\n------------------------------------------------------\n";
370  std::cout<<line_separator;
371  std::cout<<stomp_core::toString(trajectory_bias);
372  std::cout<<line_separator;
373  std::cout<<toString(optimized)<<"\n";
374  std::cout<<"Differences"<<"\n"<<toString(diff)<<line_separator;
375 }
376 
378 TEST(Stomp3DOF,solve_40_timesteps)
379 {
380  Trajectory trajectory_bias;
381  int num_timesteps = 40;
382  interpolate(START_POS,END_POS,num_timesteps,trajectory_bias);
383  TaskPtr task(new DummyTask(trajectory_bias,BIAS_THRESHOLD,STD_DEV));
384 
386  config.initialization_method = TrajectoryInitializations::LINEAR_INTERPOLATION;
387  config.num_iterations = 100;
388  config.num_timesteps = num_timesteps;
389  Stomp stomp(config,task);
390 
391  Trajectory optimized;
392  stomp.solve(START_POS,END_POS,optimized);
393 
394  EXPECT_EQ(optimized.rows(),NUM_DIMENSIONS);
395  EXPECT_EQ(optimized.cols(),num_timesteps);
396  EXPECT_TRUE(compareDiff(optimized,trajectory_bias,BIAS_THRESHOLD));
397 
398  // calculate difference
399  Trajectory diff;
400  diff = trajectory_bias - optimized;
401 
402  std::string line_separator = "\n------------------------------------------------------\n";
403  std::cout<<line_separator;
404  std::cout<<stomp_core::toString(trajectory_bias);
405  std::cout<<line_separator;
406  std::cout<<toString(optimized)<<"\n";
407  std::cout<<"Differences"<<"\n"<<toString(diff)<<line_separator;
408 }
409 
411 TEST(Stomp3DOF,solve_60_timesteps)
412 {
413  Trajectory trajectory_bias;
414  int num_timesteps = 60;
415  interpolate(START_POS,END_POS,num_timesteps,trajectory_bias);
416  TaskPtr task(new DummyTask(trajectory_bias,BIAS_THRESHOLD,STD_DEV));
417 
419  //config.initialization_method = TrajectoryInitializations::MININUM_CONTROL_COST; // this initialization method is currently behaving oddly
420  config.num_iterations = 100;
421  config.num_timesteps = num_timesteps;
422  Stomp stomp(config,task);
423 
424  Trajectory optimized;
425  stomp.solve(START_POS,END_POS,optimized);
426 
427  EXPECT_EQ(optimized.rows(),NUM_DIMENSIONS);
428  EXPECT_EQ(optimized.cols(),num_timesteps);
429  EXPECT_TRUE(compareDiff(optimized,trajectory_bias,BIAS_THRESHOLD));
430 
431  // calculate difference
432  Trajectory diff;
433  diff = trajectory_bias - optimized;
434 
435  std::string line_separator = "\n------------------------------------------------------\n";
436  std::cout<<line_separator;
437  std::cout<<stomp_core::toString(trajectory_bias);
438  std::cout<<line_separator;
439  std::cout<<toString(optimized)<<"\n";
440  std::cout<<"Differences"<<"\n"<<toString(diff)<<line_separator;
441 }
442 
bool filterParameterUpdates(std::size_t start_timestep, std::size_t num_timesteps, int iteration_number, const Eigen::MatrixXd &parameters, Eigen::MatrixXd &updates) override
Filters the given parameters which is applied after the update. It could be used for clipping of join...
Definition: stomp_3dof.cpp:139
std::shared_ptr< Task > TaskPtr
Definition: task.h:37
const std::vector< double > STD_DEV
Definition: stomp_3dof.cpp:40
d
int num_rollouts
Number of noisy trajectories.
Definition: utils.h:95
const std::vector< double > END_POS
Definition: stomp_3dof.cpp:38
TEST(Stomp3DOF, construction)
This tests the Stomp constructor.
Definition: stomp_3dof.cpp:249
void interpolate(const std::vector< double > &start, const std::vector< double > &end, std::size_t num_timesteps, Trajectory &traj)
Compute a linear interpolated trajectory given a start and end state.
Definition: stomp_3dof.cpp:233
bool smoothParameterUpdates(std::size_t start_timestep, std::size_t num_timesteps, int iteration_number, Eigen::MatrixXd &updates)
Perform a smooth update given a noisy update.
Definition: stomp_3dof.cpp:159
const std::vector< double > START_POS
Definition: stomp_3dof.cpp:37
bool compareDiff(const Trajectory &optimized, const Trajectory &desired, const std::vector< double > &thresholds)
Compares whether two trajectories are close to each other within a threshold.
Definition: stomp_3dof.cpp:188
DummyTask(const Trajectory &parameters_bias, const std::vector< double > &bias_thresholds, const std::vector< double > &std_dev)
A dummy task for testing Stomp.
Definition: stomp_3dof.cpp:55
Trajectory parameters_bias_
Definition: stomp_3dof.cpp:175
This contains the stomp core algorithm.
int num_iterations
Maximum number of iteration allowed.
Definition: utils.h:84
double control_cost_weight
Percentage of the trajectory accelerations cost to be applied in the total cost calculation > ...
Definition: utils.h:99
bool computeNoisyCosts(const Trajectory &parameters, std::size_t start_timestep, std::size_t num_timesteps, int iteration_number, int rollout_number, Eigen::VectorXd &costs, bool &validity) override
computes the state costs as a function of the noisy parameters for each time step.
Definition: stomp_3dof.cpp:105
int num_dimensions
Parameter dimensionality.
Definition: utils.h:87
const double DELTA_T
Definition: stomp_3dof.cpp:36
The Stomp class.
Definition: stomp.h:38
std::vector< double > std_dev_
Definition: stomp_3dof.cpp:177
std::vector< double > bias_thresholds_
Definition: stomp_3dof.cpp:176
A dummy task for testing STOMP.
Definition: stomp_3dof.cpp:46
The data structure used to store STOMP configuration parameters.
Definition: utils.h:81
bool solve(const std::vector< double > &first, const std::vector< double > &last, Eigen::MatrixXd &parameters_optimized)
Find the optimal solution provided a start and end goal.
Definition: stomp.cpp:192
const std::size_t NUM_DIMENSIONS
Definition: stomp_3dof.cpp:34
bool computeCosts(const Trajectory &parameters, std::size_t start_timestep, std::size_t num_timesteps, int iteration_number, Eigen::VectorXd &costs, bool &validity) override
computes the state costs as a function of the optimized parameters for each time step.
Definition: stomp_3dof.cpp:95
Eigen::MatrixXd smoothing_M_
Definition: stomp_3dof.cpp:178
This defines the stomp task.
int initialization_method
TrajectoryInitializations::TrajectoryInitialization.
Definition: utils.h:89
StompConfiguration create3DOFConfiguration()
Create the STOMP configuration for the 3 DOF problem.
Definition: stomp_3dof.cpp:210
Eigen::MatrixXd Trajectory
int max_rollouts
The combined number of new and old rollouts during each iteration shouldn&#39;t exceed this value...
Definition: utils.h:96
const std::vector< double > BIAS_THRESHOLD
Definition: stomp_3dof.cpp:39
const std::size_t NUM_TIMESTEPS
Definition: stomp_3dof.cpp:35
Defines the STOMP improvement policy.
Definition: task.h:41
double delta_t
Time change between consecutive points.
Definition: utils.h:88
bool generateNoisyParameters(const Eigen::MatrixXd &parameters, std::size_t start_timestep, std::size_t num_timesteps, int iteration_number, int rollout_number, Eigen::MatrixXd &parameters_noise, Eigen::MatrixXd &noise) override
See base clase for documentation.
Definition: stomp_3dof.cpp:71
int num_iterations_after_valid
Stomp will stop optimizing this many iterations after finding a valid solution.
Definition: utils.h:85
int num_timesteps
Number of timesteps.
Definition: utils.h:86


stomp_core
Author(s): Jorge Nicho
autogenerated on Fri May 8 2020 03:35:43