@@ -241,6 +241,7 @@ namespace pinocchio
241241 typedef Eigen::Matrix<T, 3 , 3 , U> Matrix3;
242242 typedef Eigen::Matrix<T, 4 , 4 , U> Matrix4;
243243 typedef Eigen::Matrix<T, 6 , 6 , U> Matrix6;
244+ typedef Eigen::Matrix<T, 10 , 10 , U> Matrix10;
244245 typedef Matrix6 ActionMatrix_t;
245246 typedef Vector3 Angular_t;
246247 typedef Vector3 Linear_t;
@@ -271,6 +272,7 @@ namespace pinocchio
271272
272273 typedef typename Symmetric3::AlphaSkewSquare AlphaSkewSquare;
273274 typedef typename Eigen::Matrix<Scalar, 10 , 1 , Options> Vector10;
275+ typedef typename Eigen::Matrix<Scalar, 10 , 10 , Options> Matrix10;
274276
275277 // Constructors
276278 InertiaTpl ()
@@ -565,6 +567,220 @@ namespace pinocchio
565567 mass, lever, Symmetric3 (params.template segment <6 >(4 )) + AlphaSkewSquare (mass, lever));
566568 }
567569
570+ /* *
571+ * Converts the inertia to a pseudo inertia matrix.
572+ *
573+ * @return A 4x4 pseudo inertia matrix.
574+ */
575+ Matrix4 toPseudoInertia () const
576+ {
577+ Vector10 dynamic_params = toDynamicParameters ();
578+ Scalar m = dynamic_params[0 ];
579+ Vector3 h = dynamic_params.template segment <3 >(1 );
580+ Matrix3 I_bar;
581+ I_bar << dynamic_params[4 ], dynamic_params[5 ], dynamic_params[7 ], dynamic_params[5 ],
582+ dynamic_params[6 ], dynamic_params[8 ], dynamic_params[7 ], dynamic_params[8 ],
583+ dynamic_params[9 ];
584+
585+ Matrix3 Sigma = 0.5 * I_bar.trace () * Matrix3::Identity () - I_bar;
586+ Matrix4 pseudo_inertia = Matrix4::Zero ();
587+ pseudo_inertia.template block <3 , 3 >(0 , 0 ) = Sigma;
588+ pseudo_inertia.template block <3 , 1 >(0 , 3 ) = h;
589+ pseudo_inertia.template block <1 , 3 >(3 , 0 ) = h.transpose ();
590+ pseudo_inertia (3 , 3 ) = m;
591+
592+ return pseudo_inertia;
593+ }
594+
595+ /* *
596+ * Builds an inertia matrix from a 4x4 pseudo inertia matrix.
597+ *
598+ * @param[in] pseudo_inertia A 4x4 pseudo inertia matrix.
599+ *
600+ * @return An InertiaTpl object constructed from the provided pseudo inertia matrix.
601+ */
602+ static InertiaTpl FromPseudoInertia (const Matrix4 & pseudo_inertia)
603+ {
604+ Scalar m = pseudo_inertia (3 , 3 );
605+ Vector3 h = pseudo_inertia.template block <3 , 1 >(0 , 3 );
606+ Matrix3 Sigma = pseudo_inertia.template block <3 , 3 >(0 , 0 );
607+ Matrix3 I_bar = Sigma.trace () * Matrix3::Identity () - Sigma;
608+
609+ Vector10 dynamic_params;
610+ dynamic_params[0 ] = m; /* */
611+ dynamic_params.template segment <3 >(1 ) = h;
612+ dynamic_params[4 ] = I_bar (0 , 0 );
613+ dynamic_params[5 ] = I_bar (0 , 1 );
614+ dynamic_params[6 ] = I_bar (1 , 1 );
615+ dynamic_params[7 ] = I_bar (0 , 2 );
616+ dynamic_params[8 ] = I_bar (1 , 2 );
617+ dynamic_params[9 ] = I_bar (2 , 2 );
618+
619+ return FromDynamicParameters (dynamic_params);
620+ }
621+
622+ /* *
623+ * Converts logarithmic Cholesky parameters directly to dynamic parameters.
624+ *
625+ * @param[in] log_cholesky A 10-dimensional vector containing logarithmic Cholesky parameters.
626+ * The parameters are given as
627+ * \f$ \eta = [\alpha, d_1, d_2, d_3, s_{12}, s_{23}, s_{13}, t_1, t_2, t_3] \f$
628+ *
629+ * @return A 10-dimensional vector containing mass, first moments, and inertia tensor
630+ * components. The parameters are given as \f$ \theta = [m, mc_x, mc_y, mc_z, I_{xx}, I_{xy},
631+ * I_{yy}, I_{xz}, I_{yz}, I_{zz}] \f$
632+ */
633+ template <typename Vector10Like>
634+ static Vector10 LogcholToDynamicParameters (const Eigen::MatrixBase<Vector10Like> & log_cholesky)
635+ {
636+ PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Vector10Like, log_cholesky, 10 , 1 );
637+ using Scalar = typename Vector10Like::Scalar;
638+ Vector10 dynamic_params;
639+
640+ const Scalar alpha = log_cholesky[0 ];
641+ const Scalar d1 = log_cholesky[1 ];
642+ const Scalar d2 = log_cholesky[2 ];
643+ const Scalar d3 = log_cholesky[3 ];
644+ const Scalar s12 = log_cholesky[4 ];
645+ const Scalar s23 = log_cholesky[5 ];
646+ const Scalar s13 = log_cholesky[6 ];
647+ const Scalar t1 = log_cholesky[7 ];
648+ const Scalar t2 = log_cholesky[8 ];
649+ const Scalar t3 = log_cholesky[9 ];
650+
651+ const Scalar exp_d1 = math::exp (d1);
652+ const Scalar exp_d2 = math::exp (d2);
653+ const Scalar exp_d3 = math::exp (d3);
654+
655+ dynamic_params[0 ] = 1 ;
656+ dynamic_params[1 ] = t1;
657+ dynamic_params[2 ] = t2;
658+ dynamic_params[3 ] = t3;
659+ dynamic_params[4 ] = s23 * s23 + t2 * t2 + t3 * t3 + exp_d2 * exp_d2 + exp_d3 * exp_d3;
660+ dynamic_params[5 ] = -s12 * exp_d2 - s13 * s23 - t1 * t2;
661+ dynamic_params[6 ] =
662+ s12 * s12 + s13 * s13 + t1 * t1 + t3 * t3 + exp_d1 * exp_d1 + exp_d3 * exp_d3;
663+ dynamic_params[7 ] = -s13 * exp_d3 - t1 * t3;
664+ dynamic_params[8 ] = -s23 * exp_d3 - t2 * t3;
665+ dynamic_params[9 ] =
666+ s12 * s12 + s13 * s13 + s23 * s23 + t1 * t1 + t2 * t2 + exp_d1 * exp_d1 + exp_d2 * exp_d2;
667+
668+ const Scalar exp_2_alpha = math::exp (2 * alpha);
669+ dynamic_params *= exp_2_alpha;
670+
671+ return dynamic_params;
672+ }
673+
674+ /* *
675+ * Builds an Inertia from log Cholesky parameters.
676+ *
677+ * @param[in] log_cholesky A 10-dimensional vector containing logarithmic Cholesky parameters.
678+ * The parameters are given as
679+ * \f$ \eta = [\alpha, d_1, d_2, d_3, s_{12}, s_{23}, s_{13}, t_1, t_2, t_3] \f$
680+ *
681+ * @return An Inertia object constructed from the provided log Cholesky parameters.
682+ */
683+ template <typename Vector10Like>
684+ static InertiaTpl
685+ FromLogCholeskyParameters (const Eigen::MatrixBase<Vector10Like> & log_cholesky)
686+ {
687+ PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Vector10Like, log_cholesky, 10 , 1 );
688+ Vector10 dynamic_params = LogcholToDynamicParameters (log_cholesky);
689+ return FromDynamicParameters (dynamic_params);
690+ }
691+
692+ /* *
693+ * Calculates the Jacobian of the dynamic parameters with respect to the log-Cholesky
694+ * parameters.
695+ *
696+ * @param[in] log_cholesky A 10-dimensional vector containing the log-Cholesky parameters.
697+ *
698+ * @return A 10x10 matrix containing the Jacobian of dynamic parameters with respect to
699+ * log-Cholesky parameters.
700+ */
701+ static Matrix10 calculateLogCholeskyJacobian (const Vector10 & log_cholesky)
702+ {
703+ Matrix10 jacobian = Matrix10::Zero ();
704+ const Scalar alpha = log_cholesky[0 ];
705+ const Scalar d1 = log_cholesky[1 ];
706+ const Scalar d2 = log_cholesky[2 ];
707+ const Scalar d3 = log_cholesky[3 ];
708+ const Scalar s12 = log_cholesky[4 ];
709+ const Scalar s23 = log_cholesky[5 ];
710+ const Scalar s13 = log_cholesky[6 ];
711+ const Scalar t1 = log_cholesky[7 ];
712+ const Scalar t2 = log_cholesky[8 ];
713+ const Scalar t3 = log_cholesky[9 ];
714+
715+ const Scalar exp_2alpha = math::exp (2 * alpha);
716+ const Scalar exp_2d1 = math::exp (2 * d1);
717+ const Scalar exp_2d2 = math::exp (2 * d2);
718+ const Scalar exp_2d3 = math::exp (2 * d3);
719+ const Scalar exp_d1 = math::exp (d1);
720+ const Scalar exp_d2 = math::exp (d2);
721+ const Scalar exp_d3 = math::exp (d3);
722+
723+ jacobian (0 , 0 ) = 2 * exp_2alpha;
724+
725+ jacobian (1 , 0 ) = 2 * t1 * exp_2alpha;
726+ jacobian (1 , 7 ) = exp_2alpha;
727+
728+ jacobian (2 , 0 ) = 2 * t2 * exp_2alpha;
729+ jacobian (2 , 8 ) = exp_2alpha;
730+
731+ jacobian (3 , 0 ) = 2 * t3 * exp_2alpha;
732+ jacobian (3 , 9 ) = exp_2alpha;
733+
734+ jacobian (4 , 0 ) = 2 * (s23 * s23 + t2 * t2 + t3 * t3 + exp_2d2 + exp_2d3) * exp_2alpha;
735+ jacobian (4 , 2 ) = 2 * exp_2alpha * exp_2d2;
736+ jacobian (4 , 3 ) = 2 * exp_2alpha * exp_2d3;
737+ jacobian (4 , 5 ) = 2 * s23 * exp_2alpha;
738+ jacobian (4 , 8 ) = 2 * t2 * exp_2alpha;
739+ jacobian (4 , 9 ) = 2 * t3 * exp_2alpha;
740+
741+ jacobian (5 , 0 ) = -2 * (s12 * exp_d2 + s13 * s23 + t1 * t2) * exp_2alpha;
742+ jacobian (5 , 2 ) = -s12 * exp_2alpha * exp_d2;
743+ jacobian (5 , 4 ) = -exp_2alpha * exp_d2;
744+ jacobian (5 , 5 ) = -s13 * exp_2alpha;
745+ jacobian (5 , 6 ) = -s23 * exp_2alpha;
746+ jacobian (5 , 7 ) = -t2 * exp_2alpha;
747+ jacobian (5 , 8 ) = -t1 * exp_2alpha;
748+
749+ jacobian (6 , 0 ) =
750+ 2 * (s12 * s12 + s13 * s13 + t1 * t1 + t3 * t3 + exp_2d1 + exp_2d3) * exp_2alpha;
751+ jacobian (6 , 1 ) = 2 * exp_2alpha * exp_2d1;
752+ jacobian (6 , 3 ) = 2 * exp_2alpha * exp_2d3;
753+ jacobian (6 , 4 ) = 2 * s12 * exp_2alpha;
754+ jacobian (6 , 6 ) = 2 * s13 * exp_2alpha;
755+ jacobian (6 , 7 ) = 2 * t1 * exp_2alpha;
756+ jacobian (6 , 9 ) = 2 * t3 * exp_2alpha;
757+
758+ jacobian (7 , 0 ) = -2 * (s13 * exp_d3 + t1 * t3) * exp_2alpha;
759+ jacobian (7 , 3 ) = -s13 * exp_2alpha * exp_d3;
760+ jacobian (7 , 6 ) = -exp_2alpha * exp_d3;
761+ jacobian (7 , 7 ) = -t3 * exp_2alpha;
762+ jacobian (7 , 9 ) = -t1 * exp_2alpha;
763+
764+ jacobian (8 , 0 ) = -2 * (s23 * exp_d3 + t2 * t3) * exp_2alpha;
765+ jacobian (8 , 3 ) = -s23 * exp_2alpha * exp_d3;
766+ jacobian (8 , 5 ) = -exp_2alpha * exp_d3;
767+ jacobian (8 , 8 ) = -t3 * exp_2alpha;
768+ jacobian (8 , 9 ) = -t2 * exp_2alpha;
769+
770+ jacobian (9 , 0 ) = 2
771+ * (s12 * s12 + s13 * s13 + s23 * s23 + t1 * t1 + t2 * t2 + exp_2d1 + exp_2d2)
772+ * exp_2alpha;
773+ jacobian (9 , 1 ) = 2 * exp_2alpha * exp_2d1;
774+ jacobian (9 , 2 ) = 2 * exp_2alpha * exp_2d2;
775+ jacobian (9 , 4 ) = 2 * s12 * exp_2alpha;
776+ jacobian (9 , 5 ) = 2 * s23 * exp_2alpha;
777+ jacobian (9 , 6 ) = 2 * s13 * exp_2alpha;
778+ jacobian (9 , 7 ) = 2 * t1 * exp_2alpha;
779+ jacobian (9 , 8 ) = 2 * t2 * exp_2alpha;
780+
781+ return jacobian;
782+ }
783+
568784 // Arithmetic operators
569785 InertiaTpl & __equl__ (const InertiaTpl & clone)
570786 {
0 commit comments