- 3.0.2 rigid body dynamics module.
TaskspaceCostFunctionTest.h
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich.
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
6 #include <gtest/gtest.h>
7 #include "../../models/testhyq/RobCoGenTestHyQ.h"
8 
9 using namespace ct;
10 using namespace rbd;
11 using namespace optcon;
12 
18 template <size_t state_dim, size_t control_dim>
19 void compareCostFunctionOutput(CostFunctionQuadratic<state_dim, control_dim>& costFunction,
20  CostFunctionQuadratic<state_dim, control_dim>& costFunction2)
21 {
22  ASSERT_NEAR(costFunction.evaluateIntermediate(), costFunction2.evaluateIntermediate(), 1e-9);
23  ASSERT_NEAR(costFunction.evaluateTerminal(), costFunction2.evaluateTerminal(), 1e-9);
24 
25  ASSERT_TRUE(costFunction.stateDerivativeIntermediate().isApprox(costFunction2.stateDerivativeIntermediate()));
26  ASSERT_TRUE(costFunction.stateDerivativeTerminal().isApprox(costFunction2.stateDerivativeTerminal()));
27 
28  ASSERT_TRUE(
29  costFunction.stateSecondDerivativeIntermediate().isApprox(costFunction2.stateSecondDerivativeIntermediate()));
30  ASSERT_TRUE(costFunction.stateSecondDerivativeTerminal().isApprox(costFunction2.stateSecondDerivativeTerminal()));
31 
32  ASSERT_TRUE(costFunction.controlDerivativeIntermediate().isApprox(costFunction2.controlDerivativeIntermediate()));
33  ASSERT_TRUE(costFunction.controlDerivativeTerminal().isApprox(costFunction2.controlDerivativeTerminal()));
34 
35  ASSERT_TRUE(costFunction.controlSecondDerivativeIntermediate().isApprox(
36  costFunction2.controlSecondDerivativeIntermediate()));
37  ASSERT_TRUE(
38  costFunction.controlSecondDerivativeTerminal().isApprox(costFunction2.controlSecondDerivativeTerminal()));
39 
40  ASSERT_TRUE(
41  costFunction.stateControlDerivativeIntermediate().isApprox(costFunction2.stateControlDerivativeIntermediate()));
42  ASSERT_TRUE(costFunction.stateControlDerivativeTerminal().isApprox(costFunction2.stateControlDerivativeTerminal()));
43 
44  // second derivatives have to be symmetric
45  ASSERT_TRUE(costFunction.stateSecondDerivativeIntermediate().isApprox(
46  costFunction.stateSecondDerivativeIntermediate().transpose()));
47  ASSERT_TRUE(costFunction.controlSecondDerivativeIntermediate().isApprox(
48  costFunction.controlSecondDerivativeIntermediate().transpose()));
49 }
50 
51 
52 TEST(TaskspaceCostFunctionTests, TestTaskSpacePositionTerm)
53 {
54  typedef ct::core::ADCGScalar size_type;
55  typedef TestHyQ::tpl::Kinematics<size_type> KinTpl_t;
56 
57  KinTpl_t kynTpl;
58  size_t eeId = 1;
59 
60  const size_t hyqStateDim = 36;
61  const size_t hyqControlDim = 12;
62 
63  Eigen::Matrix<double, 3, 3> Q;
64  Q.setIdentity();
65 
66  std::shared_ptr<optcon::CostFunctionAD<hyqStateDim, hyqControlDim>> Adcf(
67  new optcon::CostFunctionAD<hyqStateDim, hyqControlDim>());
68  std::shared_ptr<TermTaskspacePosition<KinTpl_t, true, hyqStateDim, hyqControlDim>> term1(
69  new TermTaskspacePosition<KinTpl_t, true, hyqStateDim, hyqControlDim>(eeId, Q, Eigen::Vector3d::Random()));
70 
71  Adcf->addFinalADTerm(term1, true);
72  Adcf->addIntermediateADTerm(term1, true);
73 
74  Adcf->initialize();
75 
76  Eigen::Matrix<double, hyqStateDim, 1> x;
77  Eigen::Matrix<double, hyqControlDim, 1> u;
78  x.setRandom();
79  u.setRandom();
80 
81  double t = 1.0;
82 
83  Adcf->setCurrentStateAndControl(x, u, t);
84 
85  // compare auto-diff against num-diff
86  ASSERT_TRUE(Adcf->stateDerivativeIntermediateTest());
87  ASSERT_TRUE(Adcf->controlDerivativeIntermediateTest());
88 
89  // check cloning for this term/costfunction combination
90  std::shared_ptr<optcon::CostFunctionAD<hyqStateDim, hyqControlDim>> Adcf_cloned(Adcf->clone());
91  x.setRandom();
92  u.setRandom();
93  t = 2.0;
94  Adcf->setCurrentStateAndControl(x, u, t);
95  Adcf_cloned->setCurrentStateAndControl(x, u, t);
96 
97  compareCostFunctionOutput(*Adcf_cloned, *Adcf);
98 }
99 
100 
101 TEST(TaskspaceCostFunctionTests, TestTaskSpacePoseTerm)
102 {
103  typedef ct::core::ADCGScalar size_type;
104  typedef TestHyQ::tpl::Kinematics<size_type> KinTpl_t;
105 
106  KinTpl_t kynTpl;
107  size_t eeId = 1;
108 
109  const size_t hyqStateDim = 36;
110  const size_t hyqControlDim = 12;
111 
112  // specify a penalty on the position error
113  Eigen::Matrix<double, 3, 3> Qpos;
114  Qpos.setIdentity();
115 
116  // specify a penalty on the orientation error
117  double Qrot = 1.0;
118 
119  // specify a desired ee position
120  Eigen::Matrix<double, 3, 1> w_pos_ee;
121  w_pos_ee.setRandom();
122 
123  // specify a desired ee orientation as quaternion, to be used in first constructor
124  Eigen::Quaternion<double> w_q_ee;
125  w_q_ee.setIdentity();
126 
127  // get euler angles corresponding to the quaternion, to be used in second constructor
128  Eigen::Matrix<double, 3, 1> w_euler_ee = w_q_ee.toRotationMatrix().eulerAngles(0, 1, 2);
129 
130  std::shared_ptr<optcon::CostFunctionAD<hyqStateDim, hyqControlDim>> Adcf(
131  new optcon::CostFunctionAD<hyqStateDim, hyqControlDim>());
132 
133  // test constructor taking the quaternion
134  std::shared_ptr<TermTaskspacePose<KinTpl_t, true, hyqStateDim, hyqControlDim>> term1(
135  new TermTaskspacePose<KinTpl_t, true, hyqStateDim, hyqControlDim>(eeId, Qpos, Qrot, w_pos_ee, w_q_ee));
136 
137  // test constructor using euler angles
138  std::shared_ptr<TermTaskspacePose<KinTpl_t, true, hyqStateDim, hyqControlDim>> term2(
139  new TermTaskspacePose<KinTpl_t, true, hyqStateDim, hyqControlDim>(eeId, Qpos, Qrot, w_pos_ee, w_euler_ee));
140 
141  Adcf->addFinalADTerm(term1, true);
142  Adcf->addIntermediateADTerm(term1, true);
143 
144  Adcf->initialize();
145 
146  Eigen::Matrix<double, hyqStateDim, 1> x;
147  Eigen::Matrix<double, hyqControlDim, 1> u;
148  x.setRandom();
149  u.setRandom();
150 
151  double t = 1.0;
152 
153  Adcf->setCurrentStateAndControl(x, u, t);
154 
155  // compare auto-diff against num-diff
156  ASSERT_TRUE(Adcf->stateDerivativeIntermediateTest());
157  ASSERT_TRUE(Adcf->controlDerivativeIntermediateTest());
158 
159  // check cloning for this term/costfunction combination
160  std::shared_ptr<optcon::CostFunctionAD<hyqStateDim, hyqControlDim>> Adcf_cloned(Adcf->clone());
161  x.setRandom();
162  u.setRandom();
163  t = 2.0;
164  Adcf->setCurrentStateAndControl(x, u, t);
165  Adcf_cloned->setCurrentStateAndControl(x, u, t);
166  compareCostFunctionOutput(*Adcf_cloned, *Adcf);
167 }
168 
169 
170 TEST(TaskspaceCostFunctionTests, TestTaskSpacePoseTermCG)
171 {
172  typedef ct::core::ADCGScalar size_type;
173  typedef TestHyQ::tpl::Kinematics<size_type> KinTpl_t;
174 
175  // global vars
176  const size_t eeId = 1;
177  const size_t hyqStateDim = 36;
178  const size_t hyqControlDim = 12;
179 
180  // specify a penalty on the position error
181  const Eigen::Matrix<double, 3, 3> Qpos = Eigen::Matrix<double, 3, 3>::Identity();
182 
183  // specify a penalty on the orientation error
184  const double Qrot = 1.0;
185 
186  // specify a desired ee position
187  Eigen::Matrix<double, 3, 1> w_pos_ee;
188  w_pos_ee.setRandom();
189 
190  // specify a desired ee orientation as quaternion, to be used in first constructor
191  Eigen::Quaternion<double> w_q_ee;
192  w_q_ee.setIdentity();
193 
194  // test constructor taking the quaternion
195  std::shared_ptr<TermTaskspacePoseCG<KinTpl_t, true, hyqStateDim, hyqControlDim>> term1(
196  new TermTaskspacePoseCG<KinTpl_t, true, hyqStateDim, hyqControlDim>(eeId, Qpos, Qrot, w_pos_ee, w_q_ee));
197 
198  // create and initialize the cost function
199  std::shared_ptr<optcon::CostFunctionAnalytical<hyqStateDim, hyqControlDim>> costFun(
201 
202  costFun->addIntermediateTerm(term1);
203  costFun->initialize();
204 
205  Eigen::Matrix<double, hyqStateDim, 1> x;
206  Eigen::Matrix<double, hyqControlDim, 1> u;
207  x.setRandom();
208  u.setRandom();
209 
210  double t = 1.0;
211 
212  // TEST 1: compare auto-diff against num-diff
213  // ==========================================
214  ASSERT_TRUE(costFun->stateDerivativeIntermediateTest());
215  ASSERT_TRUE(costFun->controlDerivativeIntermediateTest());
216 
217  // TEST 2: cost must not be the same after the reference position and orientation got changed
218  // ==========================================
219  costFun->setCurrentStateAndControl(x, u, t);
220  double cost_orig = costFun->evaluateIntermediate();
221  Eigen::VectorXd stateDerivative_orig = costFun->stateDerivativeIntermediate();
222  // change reference parameters
223  w_pos_ee.setRandom();
224  Eigen::Quaterniond testq = w_q_ee * Eigen::Quaterniond(0, 1, 0, 0);
225  term1->setReferencePosition(w_pos_ee);
226  term1->setReferenceOrientation(testq);
227  // new evaluation
228  double cost_new = costFun->evaluateIntermediate();
229  Eigen::VectorXd stateDerivative_new = costFun->stateDerivativeIntermediate();
230  ASSERT_TRUE(cost_orig - cost_new > 1e-8);
231  ASSERT_TRUE((stateDerivative_orig - stateDerivative_new).array().maxCoeff() > 1e-8);
232 
233  // TEST 3: check that the reference position and orientation got updated correctly
234  // ==========================================
235  Eigen::Vector3d w_pos_ee_retrieved = term1->getReferencePosition();
236  ASSERT_TRUE((w_pos_ee - w_pos_ee_retrieved).array().maxCoeff() < 1e-6);
237  Eigen::Matrix3d matOriginal = testq.toRotationMatrix();
238  Eigen::Matrix3d matRetrieved = term1->getReferenceOrientation().toRotationMatrix();
239  ASSERT_TRUE((matOriginal - matRetrieved).array().maxCoeff() < 1e-6);
240 
241  // TEST 4: check cloning for this term/costfunction combination
242  // ==========================================
243  std::shared_ptr<optcon::CostFunctionAnalytical<hyqStateDim, hyqControlDim>> costFun_cloned(costFun->clone());
244  x.setRandom();
245  u.setRandom();
246  t = 2.0;
247  costFun->setCurrentStateAndControl(x, u, t);
248  costFun_cloned->setCurrentStateAndControl(x, u, t);
249  compareCostFunctionOutput(*costFun_cloned, *costFun);
250 }
size_t eeId
Definition: rbdJITtests.h:24
ct::core::ControlVector< control_dim > u
Cored::Vector3 Vector3d
Definition: rbd.h:137
const size_t hyqStateDim
some global variables required for the TaskSpaceTerm test
Definition: rbdJITtests.h:19
const size_t hyqControlDim
Definition: rbdJITtests.h:20
TestHyQ::tpl::Kinematics< size_type > KinTpl_t
Definition: rbdJITtests.h:22
clear all close all load ct GNMSLog0 mat reformat t
void compareCostFunctionOutput(CostFunctionQuadratic< state_dim, control_dim > &costFunction, CostFunctionQuadratic< state_dim, control_dim > &costFunction2)
This method is called from different unit tests in order to compare the cost, first and second order ...
Definition: TaskspaceCostFunctionTest.h:19
KinTpl_t kynTpl
Definition: rbdJITtests.h:23
TEST(TaskspaceCostFunctionTests, TestTaskSpacePositionTerm)
Definition: TaskspaceCostFunctionTest.h:52
double Qrot
Definition: rbdJITtests.h:28
ct::core::StateVector< state_dim > x
const Eigen::Matrix< double, 3, 3 > Qpos
Definition: rbdJITtests.h:27
ct::core::ADCGScalar size_type
Definition: rbdJITtests.h:21