DMP_BBO library
DmpContextualTwoStep.cpp
Go to the documentation of this file.
1 
24 #include "dmp/Dmp.hpp"
26 
27 #include "dmp/Trajectory.hpp"
30 
31 #include <boost/serialization/vector.hpp>
32 
33 #include <iostream>
34 #include <eigen3/Eigen/Core>
35 
36 using namespace std;
37 using namespace Eigen;
38 
39 namespace DmpBbo {
40 
41 DmpContextualTwoStep::DmpContextualTwoStep(int n_dims_dmp, std::vector<FunctionApproximator*> function_approximators, FunctionApproximator* policy_parameter_function, DmpType dmp_type)
42 : DmpContextual(n_dims_dmp, function_approximators, dmp_type)
43 {
44  policy_parameter_function_ = vector<vector<FunctionApproximator*> >(dim_orig());
45  for (int dd=0; dd<dim_orig(); dd++)
46  {
47  policy_parameter_function_[dd] = vector<FunctionApproximator*>(1);
48  policy_parameter_function_[dd][0] = policy_parameter_function->clone();
49  }
50 }
51 
52 // Overloads in DMP computeFunctionApproximatorOutput
54  const Eigen::Ref<const Eigen::MatrixXd>& phase_state, Eigen::MatrixXd& fa_output) const
55 {
56  int n_time_steps = phase_state.rows();
57  fa_output.resize(n_time_steps,dim_orig());
58  fa_output.fill(0.0);
59 
60  if (task_parameters_.rows()==0)
61  {
62  // When the task parameters are not set, we cannot compute the output of the function approximator.
63  return;
64  }
65 
66  MatrixXd task_parameters = task_parameters_;
67  if (task_parameters.rows()==1)
68  {
69  task_parameters = task_parameters.row(0).replicate(n_time_steps,1).eval();
70  }
71  else if (task_parameters.cols()==1)
72  {
73  task_parameters = task_parameters.col(0).transpose().replicate(n_time_steps,1).eval();
74  }
75 
76  assert(n_time_steps==task_parameters.rows());
77 
78  //int n_task_parameters = task_parameters.cols();
79 
80  VectorXd model_parameters;
81  MatrixXd output(1,1);
82  for (int dd=0; dd<dim_orig(); dd++)
83  {
84  int n_parameters = function_approximator(dd)->getParameterVectorSelectedSize();
85  model_parameters.resize(n_parameters);
86  for (int pp=0; pp<n_parameters; pp++)
87  {
88  policy_parameter_function_[dd][pp]->predict(task_parameters,output);
89  model_parameters[pp] = output(0,0);
90  }
92  }
93 
94  // The parameters of the function_approximators have been set, get their outputs now.
95  for (int dd=0; dd<dim_orig(); dd++)
96  {
97  function_approximator(dd)->predict(phase_state,output);
98  if (output.size()>0)
99  {
100  fa_output.col(dd) = output;
101  }
102  }
103 
104 }
105 
107 {
108  for (int dd=0; dd<dim_orig(); dd++)
109  for (unsigned int pp=0; pp<policy_parameter_function_[dd].size(); pp++)
110  if (!policy_parameter_function_[dd][pp]->isTrained())
111  return false;
112 
113  return true;
114 }
115 
116 void DmpContextualTwoStep::train(const vector<Trajectory>& trajectories, const vector<MatrixXd>& task_parameters, string save_directory, bool overwrite)
117 {
118  // Here's the basic structure of this function
119  // 1) Do some checks
120  // 2) Train a separate Dmp for each demonstration, and get the resulting model parameters
121  // 3) Gather all task parameter values for all demonstrations
122  // 4) Train the policy parameter function for each dimension and each model parameter
123 
124 
125  //-----------------------------------------------------
126  // 1) Do some checks
127 
128  // Check if inputs are of the right size.
129  unsigned int n_demonstrations = trajectories.size();
130  assert(n_demonstrations==task_parameters.size());
131 
132 
133  // Then check if the trajectories have the same duration and initial/final state
134  // Later on, if they are not the same, they should be learned also.
135  checkTrainTrajectories(trajectories);
136 
137  // Set tau, initial_state and attractor_state from the trajectories
138  set_tau(trajectories[0].duration());
139  set_initial_state(trajectories[0].initial_y());
140  set_attractor_state(trajectories[0].final_y());
141 
142  //-----------------------------------------------------
143  // 2) Train a separate Dmp for each demonstration, and get the resulting model parameters
144  std::set<std::string> selected;
145  selected.insert("offsets");
146  selected.insert("slopes");
147 
148  MatrixXd cur_task_parameters;
149  VectorXd cur_model_parameters;// todo Remove redundant tmp variable
150  vector<MatrixXd> all_model_parameters(n_demonstrations);
151  for (unsigned int i_demo=0; i_demo<n_demonstrations; i_demo++)
152  {
153 
154  string save_directory_demo;
155  if (!save_directory.empty())
156  save_directory_demo = save_directory + "/demo" + to_string(i_demo);
157 
158  Dmp::train(trajectories[i_demo],save_directory_demo,overwrite);
159 
160  for (int i_dim=0; i_dim<dim_orig(); i_dim++)
161  {
162 
163  // todo Should be argument of constructor
164  function_approximator(i_dim)->setSelectedParameters(selected);
165 
166  function_approximator(i_dim)->getParameterVectorSelected(cur_model_parameters);
167  //cout << cur_model_parameters << endl;
168  if (i_demo==0)
169  all_model_parameters[i_dim].resize(n_demonstrations,cur_model_parameters.size());
170  else
171  assert(cur_model_parameters.size()==all_model_parameters[i_dim].cols());
172 
173  all_model_parameters[i_dim].row(i_demo) = cur_model_parameters;
174 
175  }
176  }
177 
178 
179  //-----------------------------------------------------
180  // 3) Gather all task parameter values for all demonstrations
181 
182  // Gather task parameters in a matrix
183  int n_task_parameters = task_parameters[0].cols();
184  // This is the first time task_parameters_ is set, because this is the first time we know
185  // n_task_parameters.
186  // We set it so that set_task_parameters can check if task_parameters_.cols()==n_task_parameters
187  task_parameters_ = MatrixXd::Zero(1,n_task_parameters);
188  VectorXd cur_task_parameters_t0;
189 
190  MatrixXd inputs(n_demonstrations,n_task_parameters);
191  for (unsigned int i_demo=0; i_demo<n_demonstrations; i_demo++)
192  {
193  // These are the task parameters for the current demonstration at t=0
194  cur_task_parameters_t0 = task_parameters[i_demo].row(0);
195 
196  // Task parameter may not change over time for 2-Step contextual DMP
197  // Start comparison to i_time=0 at i_time=1
198  for (int i_time=1; i_time<task_parameters[i_demo].rows(); i_time++)
199  {
200  if ( (cur_task_parameters_t0.array() != task_parameters[i_demo].row(i_time).array()).any())
201  {
202  cerr << __FILE__ << ":" << __LINE__ << ":";
203  cerr << "WARNING. For DmpContextualTwoStep, task parameters may not vary over time during training. Using task parameters at t=0 only." << endl;
204  }
205  }
206 
207  // Take the first row, i.e. at time_i = 0. We checked above if they are constant over time.
208  inputs.row(i_demo) = cur_task_parameters_t0;
209  }
210 
211  //-----------------------------------------------------
212  // 4) Train the policy parameter function for each dimension and each model parameter
213 
214  // Input to policy parameter functions: task_parameters
215  // Target for each policy parameter function: all_model_parameters.col(param)
216 
217  for (int i_dim=0; i_dim<dim_orig(); i_dim++)
218  {
219  int n_pol_pars = all_model_parameters[i_dim].cols();
220  for (int i_pol_par=1; i_pol_par<n_pol_pars; i_pol_par++)
221  {
222  policy_parameter_function_[i_dim].push_back(policy_parameter_function_[i_dim][0]->clone());
223  //cout << *(policy_parameter_function_[i_dim][i_pol_par]) << endl;
224  }
225 
226  for (int i_pol_par=0; i_pol_par<n_pol_pars; i_pol_par++)
227  {
228  MatrixXd targets = all_model_parameters[i_dim].col(i_pol_par);
229  //cout << "_________________" << endl;
230  //cout << inputs.transpose() << endl << endl;
231  //cout << targets.transpose() << endl;
232 
233  string save_directory_cur;
234  if (!save_directory.empty())
235  save_directory_cur = save_directory + "/dim" + to_string(i_dim) + "_polpar" + to_string(i_pol_par);
236 
237  policy_parameter_function_[i_dim][i_pol_par]->train(inputs,targets,save_directory_cur,overwrite);
238 
239  }
240  }
241 
242 
243 }
244 
245 template<class Archive>
246 void DmpContextualTwoStep::serialize(Archive & ar, const unsigned int version)
247 {
248  // serialize base class information
249  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(DmpContextual);
250 
251  ar & BOOST_SERIALIZATION_NVP(policy_parameter_function_);
252 
253 }
254 
255 }
virtual void set_attractor_state(const Eigen::VectorXd &y_attr)
Accessor function for the attractor state of the system.
Definition: Dmp.cpp:873
Trajectory class header file.
int dim_orig(void) const
Get the dimensionality of the dynamical system, i.e.
FunctionApproximator class header file.
virtual void set_tau(double tau)
Accessor function for the time constant.
Definition: Dmp.cpp:853
bool isTrained(void) const
Return whether the DMP is trained or not.
void setParameterVectorSelected(const Eigen::VectorXd &values, bool normalized=false)
Set all the values of the selected parameters with one vector.
Dmp class header file.
void computeFunctionApproximatorOutput(const Eigen::Ref< const Eigen::MatrixXd > &phase_state, Eigen::MatrixXd &fa_output) const
Compute the outputs of the function approximators.
void getParameterVectorSelected(Eigen::VectorXd &values, bool normalized=false) const
Get the values of the selected parameters in one vector.
Base class for all function approximators.
Implementation of Contextual Dynamical Movement Primitives.
virtual void predict(const Eigen::Ref< const Eigen::MatrixXd > &inputs, Eigen::MatrixXd &outputs)=0
Query the function approximator to make a prediction.
DmpType
Different types of DMPs that can be initialized.
Definition: Dmp.hpp:61
void train(const std::vector< Trajectory > &trajectories, const std::vector< Eigen::MatrixXd > &task_parameters, std::string save_directory="", bool overwrite=true)
Train a contextual Dmp with a set of trajectories (and save results to file) This function is useful ...
virtual void train(const Trajectory &trajectory)
Train a DMP with a trajectory.
Definition: Dmp.cpp:643
Contextual Dmp class header file.
Dmp * clone(void) const
Return a deep copy of this object.
Definition: Dmp.cpp:252
FunctionApproximator * function_approximator(int i_dim) const
Get a pointer to the function approximator for a certain dimension.
Definition: Dmp.hpp:345
virtual FunctionApproximator * clone(void) const =0
Return a pointer to a deep copy of the FunctionApproximator object.
Eigen::MatrixXd task_parameters_
The current task parameters.
void setSelectedParameters(const std::set< std::string > &selected_values_labels)
Determine which subset of parameters is represented in the vector returned by Parameterizable::getPar...
virtual void set_initial_state(const Eigen::VectorXd &y_init)
Accessor function for the initial state of the system.
Definition: Dmp.cpp:864
int getParameterVectorSelectedSize(void) const
Get the size of the vector of selected parameters, as returned by getParameterVectorSelected(.
void checkTrainTrajectories(const std::vector< Trajectory > &trajectories)
Check if several trajectories have the same duration and initial/final states.
FunctionApproximatorLWR class header file.