Skip to content

Commit fecf8f8

Browse files
lvjonokjcarpent
authored andcommitted
feat: init implementation
1 parent 52d1e7a commit fecf8f8

File tree

8 files changed

+169
-0
lines changed

8 files changed

+169
-0
lines changed

bindings/python/algorithm/expose-regressor.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ namespace pinocchio
2727
return frameBodyRegressor(model, data, frameId);
2828
}
2929

30+
boost::python::tuple computeMomentumRegressor_proxy(
31+
const context::Model & model,
32+
context::Data & data,
33+
const context::VectorXs & q,
34+
const context::VectorXs & v)
35+
{
36+
computeMomentumRegressor(model, data, q, v);
37+
38+
return boost::python::make_tuple(data.momentumRegressor, data.dpartial_lagrangian_q);
39+
}
40+
3041
void exposeRegressor()
3142
{
3243
typedef context::Scalar Scalar;
@@ -123,6 +134,18 @@ namespace pinocchio
123134
"\tdata: data related to the model\n"
124135
"\tq: the joint configuration vector (size model.nq)\n",
125136
bp::return_value_policy<bp::return_by_value>());
137+
138+
bp::def(
139+
"computeMomentumRegressor", &computeMomentumRegressor_proxy,
140+
bp::args("model", "data", "q", "v"),
141+
"Compute the momentum regressor and the partial derivative of the Lagrangian with respect "
142+
"to the configuration, store the result in context::Data and return it.\n\n"
143+
"Parameters:\n"
144+
"\tmodel: model of the kinematic tree\n"
145+
"\tdata: data related to the model\n"
146+
"\tq: the joint configuration vector (size model.nq)\n"
147+
"\tv: the joint velocity vector (size model.nv)\n",
148+
bp::return_value_policy<bp::return_by_value>());
126149
}
127150

128151
} // namespace python

include/pinocchio/algorithm/regressor.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,23 @@ namespace pinocchio
379379
const ModelTpl<Scalar, Options, JointCollectionTpl> & model,
380380
DataTpl<Scalar, Options, JointCollectionTpl> & data,
381381
const Eigen::MatrixBase<ConfigVectorType> & q);
382+
383+
// TODO: Add documentation
384+
template<
385+
typename Scalar,
386+
int Options,
387+
template<typename, int>
388+
class JointCollectionTpl,
389+
typename ConfigVectorType,
390+
typename TangentVectorType>
391+
std::pair<
392+
typename DataTpl<Scalar, Options, JointCollectionTpl>::MatrixXs,
393+
typename DataTpl<Scalar, Options, JointCollectionTpl>::MatrixXs>
394+
computeMomentumRegressor(
395+
const ModelTpl<Scalar, Options, JointCollectionTpl> & model,
396+
DataTpl<Scalar, Options, JointCollectionTpl> & data,
397+
const Eigen::MatrixBase<ConfigVectorType> & q,
398+
const Eigen::MatrixBase<TangentVectorType> & v);
382399
} // namespace pinocchio
383400

384401
/* --- Details -------------------------------------------------------------------- */

include/pinocchio/algorithm/regressor.hxx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "pinocchio/algorithm/check.hpp"
99
#include "pinocchio/algorithm/kinematics.hpp"
10+
#include "pinocchio/algorithm/kinematics-derivatives.hpp"
1011
#include "pinocchio/spatial/skew.hpp"
1112
#include "pinocchio/spatial/symmetric3.hpp"
1213

@@ -557,6 +558,76 @@ namespace pinocchio
557558

558559
return data.potentialEnergyRegressor;
559560
}
561+
562+
template<
563+
typename Scalar,
564+
int Options,
565+
template<typename, int>
566+
class JointCollectionTpl,
567+
typename ConfigVectorType,
568+
typename TangentVectorType>
569+
std::pair<
570+
typename DataTpl<Scalar, Options, JointCollectionTpl>::MatrixXs,
571+
typename DataTpl<Scalar, Options, JointCollectionTpl>::MatrixXs>
572+
computeMomentumRegressor(
573+
const ModelTpl<Scalar, Options, JointCollectionTpl> & model,
574+
DataTpl<Scalar, Options, JointCollectionTpl> & data,
575+
const Eigen::MatrixBase<ConfigVectorType> & q,
576+
const Eigen::MatrixBase<TangentVectorType> & v)
577+
{
578+
typedef context::Data::Matrix6x Matrix6x;
579+
typedef context::Data::MatrixXs MatrixXs;
580+
581+
// symbolic jacobian of the spatial kinetic energy
582+
auto spatialKineticEnergyJacobian =
583+
[](const Eigen::Vector3d & v, const Eigen::Vector3d & w) -> Eigen::Matrix<double, 6, 10> {
584+
Eigen::Matrix<double, 10, 6> jacobian;
585+
jacobian << v[0], v[1], v[2], 0, 0, 0, 0, w[2], -w[1], 0, -v[2], v[1], -w[2], 0, w[0], v[2],
586+
0, -v[0], w[1], -w[0], 0, -v[1], v[0], 0, 0, 0, 0, w[0], 0, 0, 0, 0, 0, w[1], w[0], 0, 0, 0,
587+
0, 0, w[1], 0, 0, 0, 0, w[2], 0, w[0], 0, 0, 0, 0, w[2], w[1], 0, 0, 0, 0, 0, w[2];
588+
589+
return jacobian.transpose();
590+
};
591+
592+
// zero the regressors
593+
data.momentumRegressor.setZero();
594+
data.dpartial_lagrangian_q.setZero();
595+
596+
auto zero_v = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Zero(model.nv);
597+
598+
// first compute the momentum regressor with gravity terms included
599+
computeJointTorqueRegressor(model, data, q, zero_v, v);
600+
MatrixXs momentum_with_gravity = data.jointTorqueRegressor.eval();
601+
602+
// compute the gravity component of the regressor
603+
computeJointTorqueRegressor(model, data, q, zero_v, zero_v);
604+
MatrixXs gravity_regressor = data.jointTorqueRegressor.eval();
605+
606+
data.momentumRegressor = momentum_with_gravity - gravity_regressor;
607+
608+
for (JointIndex joint_id = 1; joint_id < (JointIndex)model.njoints; ++joint_id)
609+
{
610+
611+
Motion v_i = getVelocity(model, data, joint_id, LOCAL);
612+
613+
Matrix6x partial_dq(Matrix6x::Zero(6, model.nv));
614+
Matrix6x dvb_dv(Matrix6x::Zero(6, model.nv));
615+
616+
getJointVelocityDerivatives(model, data, joint_id, LOCAL, partial_dq, dvb_dv);
617+
618+
// auto dvb_dv = velocity_derivatives.second;
619+
auto phik_dv = spatialKineticEnergyJacobian(v_i.linear(), v_i.angular());
620+
621+
auto phik_dv_joint = dvb_dv.transpose() * phik_dv;
622+
data.dpartial_lagrangian_q.middleCols((joint_id - 1) * 10, 10) = phik_dv_joint;
623+
}
624+
625+
// Subtract the static regressor to get the final result
626+
data.dpartial_lagrangian_q -= gravity_regressor;
627+
628+
return std::make_pair(data.momentumRegressor.eval(), data.dpartial_lagrangian_q.eval());
629+
}
630+
560631
} // namespace pinocchio
561632

562633
#endif // ifndef __pinocchio_algorithm_regressor_hxx__

include/pinocchio/bindings/python/multibody/data.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ namespace pinocchio
256256
.ADD_DATA_PROPERTY(jointTorqueRegressor, "Joint torque regressor.")
257257
.ADD_DATA_PROPERTY(kineticEnergyRegressor, "Kinetic energy regressor.")
258258
.ADD_DATA_PROPERTY(potentialEnergyRegressor, "Potential energy regressor.")
259+
.ADD_DATA_PROPERTY(momentumRegressor, "Momentum regressor.")
260+
.ADD_DATA_PROPERTY(
261+
dpartial_lagrangian_q, "Partial Lagrangian with respect to the joint configuration.")
259262

260263
#ifndef PINOCCHIO_PYTHON_SKIP_COMPARISON_OPERATIONS
261264
.def(bp::self == bp::self)

include/pinocchio/multibody/data.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,12 @@ namespace pinocchio
505505
/// \brief Matrix related to potential energy regressor
506506
RowVectorXs potentialEnergyRegressor;
507507

508+
/// \brief Matrix related to momentum regressor
509+
MatrixXs momentumRegressor;
510+
511+
/// \brief Matrix related to partial Lagrangian with respect to the joint configuration
512+
MatrixXs dpartial_lagrangian_q;
513+
508514
PINOCCHIO_ALIGNED_STD_VECTOR(Matrix6x) KA;
509515
PINOCCHIO_ALIGNED_STD_VECTOR(MatrixXs) LA;
510516
PINOCCHIO_ALIGNED_STD_VECTOR(VectorXs) lA;

include/pinocchio/multibody/data.hxx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ namespace pinocchio
115115
, jointTorqueRegressor(MatrixXs::Zero(model.nv, 10 * (model.njoints - 1)))
116116
, kineticEnergyRegressor(RowVectorXs::Zero(10 * (model.njoints - 1)))
117117
, potentialEnergyRegressor(RowVectorXs::Zero(10 * (model.njoints - 1)))
118+
, momentumRegressor(MatrixXs::Zero(model.nv, 10 * (model.njoints - 1)))
119+
, dpartial_lagrangian_q(MatrixXs::Zero(model.nv, 10 * (model.njoints - 1)))
118120
, KA((std::size_t)model.njoints, Matrix6x::Zero(6, 0))
119121
, LA((std::size_t)model.njoints, MatrixXs::Zero(0, 0))
120122
, lA((std::size_t)model.njoints, VectorXs::Zero(0))

src/algorithm/regressor.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,16 @@ namespace pinocchio
117117
context::VectorXs>(
118118
const context::Model &, context::Data &, const Eigen::MatrixBase<context::VectorXs> &);
119119

120+
template PINOCCHIO_EXPLICIT_INSTANTIATION_DEFINITION_DLLAPI
121+
std::pair<context::Data::MatrixXs, context::Data::MatrixXs>
122+
computeMomentumRegressor<
123+
context::Scalar,
124+
context::Options,
125+
JointCollectionDefaultTpl,
126+
context::VectorXs,
127+
context::VectorXs>(
128+
const context::Model &,
129+
context::Data &,
130+
const Eigen::MatrixBase<context::VectorXs> &,
131+
const Eigen::MatrixBase<context::VectorXs> &);
120132
} // namespace pinocchio

unittest/regressor.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,39 @@ BOOST_AUTO_TEST_CASE(test_potential_energy_regressor)
428428
BOOST_CHECK_CLOSE(potential_energy_regressor, target_energy, 1e-12);
429429
}
430430

431+
BOOST_AUTO_TEST_CASE(test_momentum_regressor)
432+
{
433+
using namespace Eigen;
434+
using namespace pinocchio;
435+
436+
pinocchio::Model model;
437+
buildModels::humanoidRandom(model);
438+
439+
model.lowerPositionLimit.head<7>().fill(-1.);
440+
model.upperPositionLimit.head<7>().fill(1.);
441+
442+
pinocchio::Data data(model);
443+
pinocchio::Data data_ref(model);
444+
445+
const VectorXd q = randomConfiguration(model);
446+
const VectorXd v = Eigen::VectorXd::Random(model.nv);
447+
const VectorXd dv = Eigen::VectorXd::Random(model.nv);
448+
449+
computeAllTerms(model, data_ref, q, v);
450+
451+
// fill in the mass inertia matrix
452+
data_ref.M.triangularView<Eigen::StrictlyLower>() =
453+
data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
454+
const VectorXd target_momentum = data_ref.M * v;
455+
456+
computeMomentumRegressor(model, data, q, v);
457+
std::cout << "executed momentum regressor" << std::endl;
458+
Eigen::VectorXd params(10 * (model.njoints - 1));
459+
for (JointIndex i = 1; i < (Model::JointIndex)model.njoints; ++i)
460+
params.segment<10>(Eigen::DenseIndex((i - 1) * 10)) = model.inertias[i].toDynamicParameters();
461+
462+
const VectorXd momentum_regressor = data.momentumRegressor * params;
463+
BOOST_CHECK(momentum_regressor.isApprox(target_momentum));
464+
}
465+
431466
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)