Skip to content

Commit

Permalink
Merge pull request #1153 from GiulioRomualdi/locked_inertia
Browse files Browse the repository at this point in the history
Implement KinDynComputations::getCentroidalRobotLockedInertia and KinDynComputations::getRobotLockedInertia
  • Loading branch information
traversaro committed Feb 7, 2024
2 parents 4a981e1 + f25fa8d commit ff40744
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [10.3.0] - 2024-02-07

### Added

- Added getCentroidalRobotLockedInertia and getRobotLockedInertia to KinDynComputations class (https://github.com/robotology/idyntree/pull/1153).

## [10.2.1] - 2024-02-01

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

cmake_minimum_required(VERSION 3.16)

project(iDynTree VERSION 10.2.1
project(iDynTree VERSION 10.3.0
LANGUAGES C CXX)

# Disable in source build, unless Eclipse is used
Expand Down
18 changes: 18 additions & 0 deletions src/high-level/include/iDynTree/KinDynComputations.h
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,15 @@ class KinDynComputations {
*/
bool getAverageVelocityJacobian(iDynTree::MatrixView<double> avgVelocityJacobian);

/**
* Get the robot locked inertia matrix.
* The quantity is expressed in (B[A]), (A) or (B) depending on the FrameVelocityConvention used.
*
* @return the locked inertia matrix of the robot.
*
*/
SpatialInertia getRobotLockedInertia();

/**
* Get the centroidal average velocity of the robot.
*
Expand Down Expand Up @@ -960,6 +969,15 @@ class KinDynComputations {
*/
bool getCentroidalAverageVelocityJacobian(iDynTree::MatrixView<double> centroidalAvgVelocityJacobian);

/**
* Get the robot locked centroidal inertia matrix.
* The quantity is expressed in (G[A]) or (G[B]) depending on the FrameVelocityConvention used.
*
* @return the locked inertia centroidal matrix of the robot.
*
*/
SpatialInertia getCentroidalRobotLockedInertia();

/**
* Get the linear and angular momentum of the robot.
* The quantity is expressed in (B[A]), (A) or (B) depending on the FrameVelocityConvention used.
Expand Down
54 changes: 54 additions & 0 deletions src/high-level/src/KinDynComputations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2199,6 +2199,29 @@ bool KinDynComputations::getAverageVelocityJacobian(MatrixView<double> avgVeloci
return true;
}

SpatialInertia KinDynComputations::getRobotLockedInertia()
{
this->computeRawMassMatrixAndTotalMomentum();
const SpatialInertia & base_lockedInertia = pimpl->getRobotLockedInertia();

if (pimpl->m_frameVelRepr == BODY_FIXED_REPRESENTATION)
{
// the computeRawMassMatrixAndTotalMomentum generates the lockedInertia in body frame.
// So in this case there is no need to conversion
return base_lockedInertia;
}
else if (pimpl->m_frameVelRepr == MIXED_REPRESENTATION)
{
iDynTree::Transform B_A_H_B(pimpl->m_pos.worldBasePos().getRotation(), Position::Zero());

// the following is not a classical multiplication. Indeed it transform the spatial inertia in a different frame.
return B_A_H_B * base_lockedInertia;
}

assert(pimpl->m_frameVelRepr == INERTIAL_FIXED_REPRESENTATION);
return pimpl->m_pos.worldBasePos()*base_lockedInertia;
}

void KinDynComputations::KinDynComputationsPrivateAttributes::processOnLeftSideBodyFixedCentroidalAvgVelocityJacobian(
MatrixView<double> jac, const FrameVelocityRepresentation & leftSideRepresentation)
{
Expand Down Expand Up @@ -2262,6 +2285,37 @@ Twist KinDynComputations::getCentroidalAverageVelocity()
return newOutputFrame_X_oldOutputFrame*base_averageVelocity;
}

SpatialInertia KinDynComputations::getCentroidalRobotLockedInertia()
{
this->computeRawMassMatrixAndTotalMomentum();


const SpatialInertia & base_lockedInertia = pimpl->getRobotLockedInertia();

// Get the center of mass in the base frame
const Position vectorFromComToBaseWithRotationOfBase = Position::inverse(pimpl->getRobotLockedInertia().getCenterOfMass());

Transform newOutputFrame_X_oldOutputFrame;
if (pimpl->m_frameVelRepr == BODY_FIXED_REPRESENTATION)
{
// oldOutputFrame is B
// newOutputFrame is G[B]

newOutputFrame_X_oldOutputFrame = Transform(Rotation::Identity(),vectorFromComToBaseWithRotationOfBase);
}
else
{
assert(pimpl->m_frameVelRepr == INERTIAL_FIXED_REPRESENTATION ||
pimpl->m_frameVelRepr == MIXED_REPRESENTATION);
// oldOutputFrame is B
// newOutputFrame is G[A]
const Rotation & A_R_B = pimpl->m_pos.worldBasePos().getRotation();
newOutputFrame_X_oldOutputFrame = Transform(pimpl->m_pos.worldBasePos().getRotation(),A_R_B*(vectorFromComToBaseWithRotationOfBase));
}

return newOutputFrame_X_oldOutputFrame*base_lockedInertia;
}

bool KinDynComputations::getCentroidalAverageVelocity(Span<double> vel)
{
constexpr int expected_spatial_velocity_size = 6;
Expand Down
29 changes: 26 additions & 3 deletions src/high-level/tests/KinDynComputationsUnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,19 @@ void testRelativeTransform(iDynTree::KinDynComputations & dynComp)

void testAverageVelocityAndTotalMomentumJacobian(iDynTree::KinDynComputations & dynComp)
{
iDynTree::Twist avgVel;
iDynTree::SpatialMomentum mom, centroidalMom;
iDynTree::Vector6 avgVelCheck, momCheck, centroidalMomCheck;
iDynTree::Twist avgVel, centroidalAvgVel;
iDynTree::SpatialMomentum mom, centroidalMom, computedMom, computedCentroidalMom;
iDynTree::Vector6 avgVelCheck, centroidalAvgVelCheck, momCheck, centroidalMomCheck;
iDynTree::VectorDynSize nu(dynComp.getNrOfDegreesOfFreedom()+6);
iDynTree::SpatialInertia lockedInertia, centroidalLockedInertia;
dynComp.getModelVel(nu);

MomentumFreeFloatingJacobian momJac(dynComp.getRobotModel());
MomentumFreeFloatingJacobian centroidalMomJac(dynComp.getRobotModel());
FrameFreeFloatingJacobian avgVelJac(dynComp.getRobotModel());
FrameFreeFloatingJacobian centroidalAvgVelJac(dynComp.getRobotModel());

// momentum quantities

avgVel = dynComp.getAverageVelocity();
bool ok = dynComp.getAverageVelocityJacobian(avgVelJac);
Expand All @@ -133,17 +137,36 @@ void testAverageVelocityAndTotalMomentumJacobian(iDynTree::KinDynComputations &

ASSERT_IS_TRUE(ok);

lockedInertia = dynComp.getRobotLockedInertia();
computedMom = lockedInertia * avgVel;

// centroidal quantities

centroidalAvgVel = dynComp.getCentroidalAverageVelocity();
ok = dynComp.getCentroidalAverageVelocityJacobian(centroidalAvgVelJac);

ASSERT_IS_TRUE(ok);

centroidalMom = dynComp.getCentroidalTotalMomentum();
ok = dynComp.getCentroidalTotalMomentumJacobian(centroidalMomJac);
ASSERT_IS_TRUE(ok);

centroidalLockedInertia = dynComp.getCentroidalRobotLockedInertia();
computedCentroidalMom = centroidalLockedInertia * centroidalAvgVel;

toEigen(momCheck) = toEigen(momJac)*toEigen(nu);
toEigen(centroidalMomCheck) = toEigen(centroidalMomJac)*toEigen(nu);
toEigen(avgVelCheck) = toEigen(avgVelJac)*toEigen(nu);
toEigen(centroidalAvgVelCheck) = toEigen(centroidalAvgVelJac)*toEigen(nu);

ASSERT_EQUAL_VECTOR(momCheck,mom.asVector());
ASSERT_EQUAL_VECTOR(centroidalMomCheck,centroidalMom.asVector());

ASSERT_EQUAL_VECTOR(avgVelCheck,avgVel.asVector());
ASSERT_EQUAL_VECTOR(centroidalAvgVelCheck, centroidalAvgVel.asVector());

ASSERT_EQUAL_VECTOR(mom.asVector(), computedMom);
ASSERT_EQUAL_VECTOR(centroidalMom.asVector(), computedCentroidalMom);
}

inline Eigen::VectorXd toEigen(const Vector6 & baseAcc, const VectorDynSize & jntAccs)
Expand Down

0 comments on commit ff40744

Please sign in to comment.