ocra-recipes
Doxygen documentation for the ocra-recipes repository
TestFunction.cpp
Go to the documentation of this file.
3 #include <math.h>
4 
5 
6 using namespace ocra;
7 
12 class Function1: public Function
13 {
14 public:
16 
18  :NamedInstance("function1")
22  {
23  assert(x.getSize() == 3);
24  }
25 
26 protected:
28  void updateValue() const
29  {
30  _value[0] = 3*x[0]*x[0]*x[1] + 2*sqrt(x[2])/x[0];
31  }
32 
34  void updateJacobian() const
35  {
36  _jacobian(0,0) = 6*x[0]*x[1] - 2*sqrt(x[2])/(x[0]*x[0]);
37  _jacobian(0,1) = 3*x[0]*x[0];
38  _jacobian(0,2) = 1/(x[0]*sqrt(x[2]));
39  }
40 
48  void updateHessian() const
49  {
50  MatrixXd& H = *IFunction<PARTIAL_XX>::_val[0]; //alias on the hessian value. There is one hessian per dimension of the function, so we take the first (and only) one
51  H(0,0) = 6*x[1] + 4*sqrt(x[2])/(x[0]*x[0]*x[0]);
52  H(0,1) = H(1,0) = 6*x[0];
53  H(0,2) = H(2,0) = -1/(x[0]*x[0]*sqrt(x[2]));
54  H(1,1) = 0;
55  H(1,2) = H(2,1) = 0;
56  H(2,2) = -1/(2*x[0]*x[2]*sqrt(x[2]));
57  }
58 
61  {
62  if (x.getSize() != 3)
63  throw std::runtime_error("[Function1::doResize] Variable x size is different from 3");
64  }
65 };
66 
67 
68 void examplef1()
69 {
70  //Create the variable and the function
71  BaseVariable xyz("xyz",3);
72  Function1 f1(xyz);
73 
74  //set a value to the variable and get the value, jacobian and hessian of the function
75  xyz.setValue(Vector3d(0.1,-0.2,0.45));
76  std::cout << "f(0.1,-0.2,0.45) = " << f1.getValue() << std::endl << std::endl;
77  std::cout << "df/dx(0.1,-0.2,0.45) = " << std::endl << f1.getJacobian() << std::endl << std::endl;
78  std::cout << "d2f/dx2(0.1,-0.2,0.45) = " << std::endl << f1.get<PARTIAL_XX>(0) << std::endl << std::endl << std::endl;
79 
80  //change the value and get the results on more time
81  xyz.setValue(Vector3d(0.324,0.12,0.06));
82  std::cout << "f(0.324,0.12,0.06) = " << f1.getValue() << std::endl << std::endl;
83  std::cout << "df/dx(0.324,0.12,0.06) = " << std::endl << f1.getJacobian() << std::endl << std::endl;
84  std::cout << "d2f/dx2(0.324,0.12,0.06) = " << std::endl << f1.get<PARTIAL_XX>(0) << std::endl << std::endl;
85 
86  //xyz.resize(4); //this will trigger an exception
87 
88  if (f1.canCompute<PARTIAL_T>())
89  std::cout << f1.get<PARTIAL_T>() << std::endl;
90  else
91  std::cout << "Can't compute partial_t" << std::endl;
92 
93 
94  Constraint<Function1> cstr(&f1, true);
95  std::cout << cstr.getDimension() << std::endl;
96  std::cout << cstr.getValue() << std::endl;
97  std::cout << cstr.get<PARTIAL_XX>(0) << std::endl;
98  cstr.setB(VectorXd::Random(1));
99  std::cout << cstr.isValid<FUN_VALUE>() << std::endl;
100  std::cout << cstr.isRespected() << std::endl;
101  //cstr.getU(); //trigger an assert
102  std::cout << cstr.getType() << std::endl;
103 }
104 
105 
106 
107 
108 
114 class Function2: public Function
115 {
116 public:
118  : NamedInstance("function2")
120  , CoupledInputOutputSize(false)
122  {
123  //initialize the value of constant ability (partial_T)
124  setZeroValues();
125  }
126 protected:
127  void updateValue() const
128  {
129  _value[0] = 1;
130  for (int i=0; i<x.getSize(); ++i)
131  _value[0] *= x[i];
132  _value[0] = std::pow(std::abs(_value[0]),1./x.getSize());
133 // _value[0] = 2;
134  }
135 
136  void updateJacobian() const
137  {
138  double v = getValue(0)/x.getSize();
139  for (int i=0; i<x.getSize(); ++i)
140  _jacobian(0,i) = v/x[i];
141  }
142 
143  void updatePartialT() const
144  {
145  //do nothing, \partial f/ \partial dt is 0, and the value is set when allocating the memory
146  }
147 
150  {
151  //we re-set to 0 the partial time derivative;
152  IFunction<PARTIAL_T>::_val.setZero();
153  }
154 
155  void updateJdot() const
156  {
157  ocra_assert(x.hasTimeDerivative());
158  MatrixXd& Jdot = IFunction<PARTIAL_X_DOT>::_val;
159  Variable& x_dot = x.getTimeDerivative();
160  VectorXd tmp = getJacobian()*static_cast<VectorXd>(x_dot);
161  double v = getValue(0);
162  MatrixXd q = static_cast<VectorXd>(x).array().inverse().transpose();
163  Jdot = tmp[0]*q;
164  Jdot.array() -= v*(static_cast<VectorXd>(x_dot)).transpose().array()*q.array()*q.array();
165  Jdot *= 1./x.getSize();
166  }
167 
168  void updateHessian() const
169  {
170  MatrixXd& H = *IFunction<PARTIAL_XX>::_val[0];
171  VectorXd q = static_cast<VectorXd>(x).array().inverse();
172  H = (x.getSize()*q.array()*q.array()).matrix().asDiagonal();
173  H -= q*q.transpose(); //Can be optimized by taking into account the symmetry of H and qq'
174  H *= -getValue(0)/(x.getSize()*x.getSize());
175  }
176 
178  {
179  //do nothing: this function supports variable resizing.
180  }
181 
184  {
185  setZeroValues();
186  }
187 };
188 
189 
190 void examplef2()
191 {
192  int size = 8;
193  BaseVariable x("x",size);
194  Variable& x_dot = x.getTimeDerivative();
195  Variable& x_ddot = x_dot.getTimeDerivative();
196  Function2 f2(x);
197 
198  VectorXd v(size), dv(size), ddv(size);
199  v << -0.997497, 0.127171, -0.613392, 0.617481, 0.170019, -0.0402539, -0.299417, 0.791925;
200  dv << 0.64568 , 0.49321 , -0.651784, 0.717887, 0.421003, 0.0270699, -0.39201 , -0.970031;
201  ddv << -0.817194, -0.271096, -0.705374, -0.668203, 0.97705 , -0.108615 , -0.761834, -0.990661;
202  x.setValue(v);
203  x_dot.setValue(dv);
204  x_ddot.setValue(ddv);
205  std::cout << "at x=" << static_cast<VectorXd>(x).transpose() << std::endl;
206  std::cout << "at dot{x}=" << static_cast<VectorXd>(x_dot).transpose() << std::endl;
207  std::cout << "at dot{x}=" << static_cast<VectorXd>(x_ddot).transpose() << std::endl << std::endl;
208  /* Return value for f(x)
209  * 0.3065426552821116
210  */
211  std::cout << "f(x) = " << std::endl << f2.getValue() << std::endl << std::endl;
212 
213  /* Return value for df/dx(x)
214  * -0.03841398210747897 0.3013095116831978 -0.06246875066884464 0.06205507847247762 0.2253738223978729 -0.9519035897208457 -0.1279748040701228 0.04838568287434284
215  */
216  std::cout << "df/dx(x) = " << std::endl << f2.getJacobian() << std::endl << std::endl;
217 
218  /* Return value for df/dt(x)
219  * 0
220  */
221  std::cout << "df/dt(x) = " << std::endl << f2.get<PARTIAL_T>() << std::endl << std::endl;
222 
223  /* Return value for dot{f}(x)
224  * 0.2814173015622613
225  */
226  std::cout << "dot{f}(x) = " << std::endl << f2.get<FUN_DOT>() << std::endl << std::endl;
227 
228  /* Return value for dot{df/dx}(x)
229  * -0.06013081008007012 -0.8919620161985622 0.009030064772053717 -0.01517677697627763 -0.3511718846463573 -1.514017217677467 0.05006476001110882 0.1036875651602921
230  */
231  std::cout << "dot{df/dx}(x) = " << std::endl << f2.get<PARTIAL_X_DOT>() << std::endl << std::endl;
232 
233  /* Return value for d2f/dx2(x)
234  * -0.03369657687596465 -0.03775819772931621 0.007828187787638039 -0.00777634901063332 -0.02824241857342339 0.1192865228818791 0.01603699109748235 -0.006063387016996397
235  * -0.03775819772931621 -2.073159939945413 -0.06140231525745318 0.06099570506687612 0.221526352704108 -0.9356531655417172 -0.125790081927211 0.04755966658509294
236  * 0.007828187787638039 -0.06140231525745318 -0.0891112972377192 -0.01264588519097038 -0.04592777179965521 0.1939835353495085 0.02607932693736688 -0.009860269386123156
237  * -0.00777634901063332 0.06099570506687612 -0.01264588519097038 -0.0879350031230401 0.0456236350587858 -0.1926989635553251 -0.0259066279104383 0.009794974030444426
238  * -0.02824241857342339 0.221526352704108 -0.04592777179965521 0.0456236350587858 -1.159882687218127 -0.6998508914598116 -0.0940886048545477 0.03557373210813412
239  * 0.1192865228818791 -0.9356531655417172 0.1939835353495085 -0.1926989635553251 -0.6998508914598116 -20.6915514026154 0.3973987740011614 -0.1502515373489986
240  * 0.01603699109748235 -0.125790081927211 0.02607932693736688 -0.0259066279104383 -0.0940886048545477 0.3973987740011614 -0.3739866258808198 -0.0201999564463369
241  * -0.006063387016996397 0.04755966658509294 -0.009860269386123156 0.009794974030444426 0.03557373210813412 -0.1502515373489986 -0.0201999564463369 -0.05346146732967134
242  */
243  std::cout << "d2f/dx2(x) = " << std::endl << f2.get<PARTIAL_XX>(0) << std::endl << std::endl;
244 
245  /* Return value for ddot{f}(x)
246  * -0.4791048960947238
247  */
248  std::cout << "ddot{f}(x) = " << std::endl << f2.get<FUN_DDOT>() << std::endl << std::endl;
249 
250  x.resize(3);
251  x.setValue(Vector3d(-0.11,0.231,0.406));
252  std::cout << "at x=" << static_cast<VectorXd>(x).transpose() << std::endl;
253  std::cout << "f(x) = " << std::endl << f2.getValue() << std::endl << std::endl;
254 }
255 
256 
267 class Function3: public Function
268 {
269 private:
270  static std::vector<bool> allAbilitiesUpTo(eFunctionAbility a) {return std::vector<bool>(a+1, true);}
271 
272 public:
274  : NamedInstance("function3")
275  , AbilitySet(allAbilitiesUpTo(PARTIAL_T_DOT))
276  , CoupledInputOutputSize(false)
278  , true //time dependant
279  , false) //not time separable
280  , t(0), _t0(0), _stateX(Vector3d::Zero()), _stateY(Vector3d::Zero()), _stateZ(Vector3d::Zero())
281  {
282  ocra_assert(x.getSize() == 3);
283  IFunction<PARTIAL_XX>::_val[0]->setZero();
284  IFunction<PARTIAL_XX>::_val[1]->setZero();
285  IFunction<PARTIAL_XX>::_val[2]->setZero();
286  }
287 
288  void changeInitialState(double t0, const Vector3d& stateX, const Vector3d& stateY, const Vector3d& stateZ)
289  {
290  _t0 = t0;
291  _stateX = stateX;
292  _stateY = stateY;
293  _stateZ = stateZ;
294  invalidateAll();
295  }
296 
297  void setTime(double t)
298  {
299  this->t = t;
300  }
301 
302 protected:
303  void updateValue() const
304  {
305  double dt = t-_t0;
306  Vector3d v(1,dt,dt*dt/2);
307  double f = dt*dt*dt/6;
308  _value[0] = v.dot(_stateX) + x[0]*f;
309  _value[1] = v.dot(_stateY) + x[1]*f;
310  _value[2] = v.dot(_stateZ) + x[2]*f;
311  }
312 
313  void updateJacobian() const
314  {
315  double dt = t-_t0;
316  double f = dt*dt*dt/6;
317  _jacobian.setIdentity();
318  _jacobian.diagonal() *= f;
319  }
320 
321  void updatePartialT() const
322  {
323  double dt = t-_t0;
324  double f = dt*dt/2;
325  IFunction<PARTIAL_T>::_val[0] = _stateX[1] + _stateX[2]*dt + x[0]*f;
326  IFunction<PARTIAL_T>::_val[1] = _stateY[1] + _stateY[2]*dt + x[1]*f;
327  IFunction<PARTIAL_T>::_val[2] = _stateZ[1] + _stateZ[2]*dt + x[2]*f;
328  }
329 
330  void updateJdot() const
331  {
332  double dt = t-_t0;
333  double f = dt*dt/2;
334  IFunction<PARTIAL_X_DOT>::_val.setIdentity();
335  IFunction<PARTIAL_X_DOT>::_val.diagonal() *= f;
336  }
337 
338  void updateHessian() const
339  {
340  //do nothing, it is always 0
341  }
342 
343  void updatePartialTT() const
344  {
345  double dt = t-_t0;
346  IFunction<PARTIAL_TT>::_val[0] =_stateX[2] + x[0]*dt;
347  IFunction<PARTIAL_TT>::_val[1] =_stateY[2] + x[1]*dt;
348  IFunction<PARTIAL_TT>::_val[2] =_stateZ[2] + x[2]*dt;
349  }
350 
351  void updatePartialTX() const
352  {
353  IFunction<PARTIAL_TX>::_val = get<PARTIAL_X_DOT>();
354  }
355 
356  void updatePartialXT() const
357  {
358  IFunction<PARTIAL_XT>::_val = get<PARTIAL_X_DOT>();
359  }
360 
361  void updatePartialTdot() const
362  {
363  ocra_assert(x.hasTimeDerivative());
364  Variable& x_dot = x.getTimeDerivative();
365  double dt = t-_t0;
366  double f = dt*dt/2;
367  IFunction<PARTIAL_T_DOT>::_val = get<PARTIAL_TT>() + x_dot.getValue()*f;
368  }
369 
371  {
372  if (x.getSize() != 3)
373  throw std::runtime_error("[Function3::doResize] Variable x size is different from 3");
374  }
375 
376 
377 
378 private:
379  double t;
380  double _t0;
381  Vector3d _stateX;
382  Vector3d _stateY;
383  Vector3d _stateZ;
384 
385 };
386 
387 
388 
389 void examplef3()
390 {
391  BaseVariable xyz("xyz",3);
392  Variable& xyz_dot = xyz.getTimeDerivative();
393  Variable& xyz_ddot = xyz_dot.getTimeDerivative();
394  Function3 f3(xyz);
395  f3.changeInitialState(0,Vector3d(0.1,0,0),Vector3d(1.05,0,0),Vector3d(0.,0.3,0));
396 
397  xyz.setValue(Vector3d(0.1,-0.2,0.45));
398  xyz_dot.setValue(Vector3d(0.03,0.15,-0.307));
399  xyz_ddot.setValue(Vector3d(-0.008,-0.024,-0.022));
400  f3.setTime(0.1);
401 
402 
403  std::cout << "f = " << f3.getValue() << std::endl << std::endl;
404  std::cout << "df/dx = " << std::endl << f3.getJacobian() << std::endl << std::endl;
405  std::cout << "df/dt = " << std::endl << f3.get<PARTIAL_T >() << std::endl << std::endl;
406  std::cout << "fdot = " << std::endl << f3.get<FUN_DOT >() << std::endl << std::endl;
407  std::cout << "dot{df/dx} = " << std::endl << f3.get<PARTIAL_X_DOT>() << std::endl << std::endl;
408  std::cout << "d2f/dx2 = " << std::endl << f3.get<PARTIAL_XX >(0) << std::endl << std::endl
409  << f3.get<PARTIAL_XX >(1) << std::endl << std::endl
410  << f3.get<PARTIAL_XX >(2) << std::endl << std::endl;
411  std::cout << "fddot = " << std::endl << f3.get<FUN_DDOT >() << std::endl << std::endl;
412  std::cout << "d2f/dt2 = " << std::endl << f3.get<PARTIAL_TT >() << std::endl << std::endl;
413  std::cout << "d2f/dtdx = " << std::endl << f3.get<PARTIAL_TX >() << std::endl << std::endl;
414  std::cout << "d2f/dxdt = " << std::endl << f3.get<PARTIAL_XT >() << std::endl << std::endl;
415  std::cout << "dot{df/dt} = " << std::endl << f3.get<PARTIAL_T_DOT>() << std::endl << std::endl;
416 
417 }
418 
419 
421 {
422  std::cout << "**********************************************" << std::endl;
423  std::cout << "************ Example 1 ***************" << std::endl;
424  std::cout << "**********************************************" << std::endl;
425  examplef1();
426 
427  std::cout << std::endl << std::endl;
428  std::cout << "**********************************************" << std::endl;
429  std::cout << "************ Example 2 ***************" << std::endl;
430  std::cout << "**********************************************" << std::endl;
431  examplef2();
432 
433  std::cout << std::endl << std::endl;
434  std::cout << "**********************************************" << std::endl;
435  std::cout << "************ Example 3 ***************" << std::endl;
436  std::cout << "**********************************************" << std::endl;
437  examplef3();
438 }
439 
440 // cmake:sourcegroup=Function
void updateHessian() const
Computation ability of a ocra function.
Definition: IFunction.h:243
virtual Variable & getTimeDerivative()
Get the time derivative/primitive of the variable.
Definition: Variable.cpp:106
void updatePartialTT() const
void updateHessian() const
void updateJacobian() const
void updateJacobian() const
void updateValue() const
void examplef2()
void setValue(const VectorXd &value)
Definition: Variable.cpp:99
A set of tutorial/test for the Function class.
void updateHessian() const
eFunctionAbility
Enumeration of the computation abilities of a ocra function.
Definition: IFunction.h:64
void examplef1()
void changeInitialState(double t0, const Vector3d &stateX, const Vector3d &stateY, const Vector3d &stateZ)
void updateJdot() const
Optimization-based Robot Controller namespace. a library of classes to write and solve optimization p...
Function functionType_t
Function class.
Definition: Function.h:77
Function2(Variable &x)
void exampleFunction()
void updatePartialTX() const
const IFunction< Ability >::return_type & get() const
Definition: Function.h:353
Constraint class.
Definition: Constraint.h:100
const MatrixXd & getJacobian() const
Definition: Function.h:375
bool canCompute() const
Definition: Function.h:347
void updateJdot() const
int getSize() const
Definition: Variable.cpp:81
void setTime(double t)
void updatePartialT() const
void doUpdateInputSizeBegin()
This class represents a variable in a mathematical sense.
Definition: Variable.h:105
void doUpdateInputSizeBegin()
const VectorXd & getValue() const
Definition: Function.h:365
void updatePartialTdot() const
void updatePartialT() const
void doUpdateInputSizeEnd()
Declaration file of the Constraint class.
void resize(size_t newSize)
Definition: Variable.cpp:344
BaseVariable & getTimeDerivative()
Get the time derivative/primitive of the variable.
Definition: Variable.cpp:370
void setZeroValues()
void updateValue() const
void updateJacobian() const
#define ocra_assert(ocra_expression)
Definition: ocra_assert.h:45
Function3(Variable &x)
Function1(Variable &x)
void examplef3()
Implements a basic variable.
Definition: Variable.h:304
void doUpdateInputSizeBegin()
void updateValue() const
void updatePartialXT() const