unittest/energy.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2016-2020 CNRS INRIA
3 //
4 
10 
12 
13 #include <iostream>
14 #include <boost/test/unit_test.hpp>
15 #include <boost/utility/binary.hpp>
16 #include <boost/test/tools/floating_point_comparison.hpp>
17 
18 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
19 
20 BOOST_AUTO_TEST_CASE(test_kinetic_energy)
21 {
22  using namespace Eigen;
23  using namespace pinocchio;
24 
25  Model model;
27  Data data(model);
28 
29  const VectorXd qmax = VectorXd::Ones(model.nq);
30  VectorXd q = randomConfiguration(model, -qmax, qmax);
31  VectorXd v = VectorXd::Random(model.nv);
32 
34  data.M.triangularView<Eigen::StrictlyLower>() =
35  data.M.transpose().triangularView<Eigen::StrictlyLower>();
36 
37  double kinetic_energy_ref = 0.5 * v.transpose() * data.M * v;
38  double kinetic_energy = computeKineticEnergy(model, data, q, v);
39 
40  BOOST_CHECK_SMALL(kinetic_energy_ref - kinetic_energy, 1e-12);
41 }
42 
43 BOOST_AUTO_TEST_CASE(test_kinetic_energy_with_armature)
44 {
45  using namespace Eigen;
46  using namespace pinocchio;
47 
48  Model model;
50  Data data(model), data_ref(model);
51 
52  model.armature = VectorXd::Random(model.nv) + VectorXd::Ones(model.nv);
53 
54  const VectorXd qmax = VectorXd::Ones(model.nq);
55  VectorXd q = randomConfiguration(model, -qmax, qmax);
56  VectorXd v = VectorXd::Random(model.nv);
57 
58  crba(model, data_ref, q, Convention::WORLD);
59  data_ref.M.triangularView<Eigen::StrictlyLower>() =
60  data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
61 
62  double kinetic_energy_ref = 0.5 * v.transpose() * data_ref.M * v;
63  double kinetic_energy = computeKineticEnergy(model, data, q, v);
64 
65  BOOST_CHECK_SMALL(
66  kinetic_energy_ref - kinetic_energy, Eigen::NumTraits<double>::dummy_precision());
67 }
68 
69 BOOST_AUTO_TEST_CASE(test_potential_energy)
70 {
71  using namespace Eigen;
72  using namespace pinocchio;
73 
74  Model model;
76  Data data(model), data_ref(model);
77 
78  const VectorXd qmax = VectorXd::Ones(model.nq);
79  VectorXd q = randomConfiguration(model, -qmax, qmax);
80 
81  double potential_energy = computePotentialEnergy(model, data, q);
82  centerOfMass(model, data_ref, q);
83 
84  double potential_energy_ref = -data_ref.mass[0] * (data_ref.com[0].dot(model.gravity.linear()));
85 
86  BOOST_CHECK_SMALL(
87  potential_energy_ref - potential_energy, Eigen::NumTraits<double>::dummy_precision());
88 }
89 
90 BOOST_AUTO_TEST_CASE(test_mechanical_energy)
91 {
92  using namespace Eigen;
93  using namespace pinocchio;
94 
95  Model model;
97  Data data(model), data_ref(model);
98 
99  const VectorXd qmax = VectorXd::Ones(model.nq);
100  VectorXd q = randomConfiguration(model, -qmax, qmax);
101  VectorXd v = VectorXd::Random(model.nv);
102 
103  computeKineticEnergy(model, data_ref, q, v);
104  computePotentialEnergy(model, data_ref, q);
105 
106  const double mechanical_energy_ref = data_ref.kinetic_energy + data_ref.potential_energy;
107  double mechanical_energy = computeMechanicalEnergy(model, data, q, v);
108 
109  BOOST_CHECK_SMALL(
110  mechanical_energy_ref - mechanical_energy, Eigen::NumTraits<double>::dummy_precision());
111 }
112 
113 template<typename ConfigVectorType, typename TangentVectorType>
114 Eigen::VectorXd evalMv(
115  const pinocchio::Model & model,
116  const Eigen::MatrixBase<ConfigVectorType> & q,
117  const Eigen::MatrixBase<TangentVectorType> & v)
118 {
121  data.M.triangularView<Eigen::StrictlyLower>() =
122  data.M.transpose().triangularView<Eigen::StrictlyLower>();
123  return data.M * v;
124 }
125 
126 BOOST_AUTO_TEST_CASE(test_against_rnea)
127 {
128  using namespace Eigen;
129  using namespace pinocchio;
130 
131  Model model;
133  model.armature = VectorXd::Random(model.nv) + VectorXd::Ones(model.nv);
134  model.armature.head<6>().setZero(); // Because we do not take into account the influcent of the
135  // armature on the Coriolis terms
136  // model.gravity.setZero();
137  Data data(model), data_ref(model);
138 
139  const VectorXd qmax = VectorXd::Ones(model.nq);
140  VectorXd q = randomConfiguration(model, -qmax, qmax);
141  VectorXd v = VectorXd::Random(model.nv); // v.setZero();
142  VectorXd a = VectorXd::Random(model.nv); // a.setZero();
143 
144  const VectorXd tau_ref = rnea(model, data_ref, q, v, a);
145  VectorXd tau_fd = VectorXd::Zero(model.nv);
146 
147  const double eps = 1e-8;
149  const double mechanical_energy = data.kinetic_energy - data.potential_energy;
151  const SE3 oM1 = data.oMi[1];
152  Data data_plus(model);
153  for (Eigen::DenseIndex k = 0; k < model.nv; ++k)
154  {
155  VectorXd q_plus = integrate(model, q, VectorXd::Unit(model.nv, k) * eps);
156  computeMechanicalEnergy(model, data_plus, q_plus, v);
157  const double mechanical_energy_plus = data_plus.kinetic_energy - data_plus.potential_energy;
158  const SE3 oM1_plus = data_plus.oMi[1];
159  const SE3 Mdiff = oM1.actInv(oM1_plus);
160  if (k < 6)
161  {
162  Force f = Force::Zero();
163  f.toVector()[k] = mechanical_energy;
164  Force f_plus = Force::Zero();
165  f_plus.toVector()[k] = mechanical_energy_plus;
166  tau_fd.head<6>() -= (Mdiff.act(f_plus) - f).toVector() / eps;
167  }
168  else
169  {
170  tau_fd[k] = -(mechanical_energy_plus - mechanical_energy) / eps;
171  }
172  }
173 
174  const VectorXd Mv = evalMv(model, q, v);
175  const VectorXd q_plus = integrate(model, q, v * eps);
176  const VectorXd v_plus = v + a * eps;
177  VectorXd Mv_plus = evalMv(model, q_plus, v_plus);
178 
179  forwardKinematics(model, data, q_plus);
180  const SE3 oM1_plus = data.oMi[1];
181  const SE3 Mdiff = oM1.actInv(oM1_plus);
182  Mv_plus.head<6>() =
183  Mdiff.act(Force(Mv_plus.head<6>()))
184  .toVector(); // The torque at the free flyer level is expressed in a translated frame.
185 
186  tau_fd += (Mv_plus - Mv) / eps;
187  std::cout << "tau_fd: " << tau_fd.transpose() << std::endl;
188  std::cout << "tau_ref: " << tau_ref.transpose() << std::endl;
189 
190  BOOST_CHECK(tau_fd.isApprox(tau_ref, sqrt(eps)));
191 }
192 
193 BOOST_AUTO_TEST_SUITE_END()
pinocchio::DataTpl::M
MatrixXs M
The joint space inertia matrix (a square matrix of dim model.nv).
Definition: multibody/data.hpp:199
pinocchio::WORLD
@ WORLD
Definition: multibody/fwd.hpp:48
pinocchio::computePotentialEnergy
Scalar computePotentialEnergy(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
Computes the potential energy of the system, i.e. the potential energy linked to the gravity field....
Eigen
pinocchio::DataTpl
Definition: context/generic.hpp:25
pinocchio::DataTpl::mass
std::vector< Scalar > mass
Vector of subtree mass. In other words, mass[j] is the mass of the subtree supported by joint ....
Definition: multibody/data.hpp:444
pinocchio::forwardKinematics
void forwardKinematics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Update the joint placements according to the current joint configuration.
pinocchio::DataTpl::kinetic_energy
Scalar kinetic_energy
Kinetic energy of the system.
Definition: multibody/data.hpp:453
pinocchio::SE3Tpl< context::Scalar, context::Options >
pinocchio::Convention::WORLD
@ WORLD
setup.data
data
Definition: cmake/cython/setup.in.py:48
pinocchio::buildModels::humanoidRandom
void humanoidRandom(ModelTpl< Scalar, Options, JointCollectionTpl > &model, bool usingFF=true)
Create a humanoid kinematic tree with 6-DOF limbs and random joint placements.
pinocchio::crba
const DataTpl< Scalar, Options, JointCollectionTpl >::MatrixXs & crba(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Convention convention=Convention::LOCAL)
Computes the upper triangular part of the joint space inertia matrix M by using the Composite Rigid B...
autodiff-rnea.f
f
Definition: autodiff-rnea.py:24
pinocchio::randomConfiguration
void randomConfiguration(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorIn1 > &lowerLimits, const Eigen::MatrixBase< ConfigVectorIn2 > &upperLimits, const Eigen::MatrixBase< ReturnType > &qout)
Generate a configuration vector uniformly sampled among provided limits.
Definition: joint-configuration.hpp:325
rnea.hpp
pinocchio::DataTpl::potential_energy
Scalar potential_energy
Potential energy of the system.
Definition: multibody/data.hpp:456
anymal-simulation.model
model
Definition: anymal-simulation.py:12
pinocchio::computeMechanicalEnergy
Scalar computeMechanicalEnergy(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
Computes the mechanical energy of the system stored in data.mechanical_energy. The result is accessib...
center-of-mass.hpp
joint-configuration.hpp
pinocchio::integrate
void integrate(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v, const Eigen::MatrixBase< ReturnType > &qout)
Integrate a configuration vector for the specified model for a tangent vector during one unit time.
Definition: joint-configuration.hpp:72
autodiff-rnea.v
v
Definition: autodiff-rnea.py:15
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(test_kinetic_energy)
Definition: unittest/energy.cpp:20
pinocchio::ForceTpl
Definition: context/casadi.hpp:25
q
q
setZero
void setZero(std::vector< MatType, Eigen::aligned_allocator< MatType > > &Ms)
a
Vec3f a
pinocchio::computeKineticEnergy
Scalar computeKineticEnergy(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
Computes the kinetic energy of the system. The result is accessible through data.kinetic_energy.
pinocchio::rnea
const DataTpl< Scalar, Options, JointCollectionTpl >::TangentVectorType & rnea(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType1 > &v, const Eigen::MatrixBase< TangentVectorType2 > &a)
The Recursive Newton-Euler algorithm. It computes the inverse dynamics, aka the joint torques accordi...
dcrba.eps
int eps
Definition: dcrba.py:439
pinocchio::cholesky::Mv
MatRes & Mv(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< Mat > &min, const Eigen::MatrixBase< MatRes > &mout)
Performs the multiplication by using the sparsity pattern of the M matrix.
energy.hpp
sample-models.hpp
pinocchio::ModelTpl
Definition: context/generic.hpp:20
crba.hpp
evalMv
Eigen::VectorXd evalMv(const pinocchio::Model &model, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v)
Definition: unittest/energy.cpp:114
pinocchio
Main pinocchio namespace.
Definition: timings.cpp:27
BOOST_CHECK
#define BOOST_CHECK(check)
Definition: overview-urdf.cpp:34
pinocchio::centerOfMass
const DataTpl< Scalar, Options, JointCollectionTpl >::Vector3 & centerOfMass(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const bool computeSubtreeComs=true)
Computes the center of mass position of a given model according to a particular joint configuration....


pinocchio
Author(s):
autogenerated on Sat Jun 22 2024 02:41:46