Skip to content

Commit 34bc2f5

Browse files
committed
Fix CalcSpatialMomentumInWorldAboutPoint() so it uses mobods (not delegate to links, which causes bug for fused link).
1 parent 3ee3360 commit 34bc2f5

2 files changed

Lines changed: 30 additions & 11 deletions

File tree

multibody/plant/test/fused_welds_test.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ GTEST_TEST(FusedTest, CompositeSpatialInertia) {
279279
fused_model.plant->CalcSpatialMomentumInWorldAboutPoint(
280280
*fused_model.context, p_WoWo_W);
281281
// TODO(Mitiguy) EXPECT_FALSE is wrong, should be EXPECT_TRUE !
282-
EXPECT_FALSE(CompareMatrices(L_unfused.get_coeffs(), L_fused.get_coeffs(),
283-
kTolerance, MatrixCompareType::relative))
282+
EXPECT_TRUE(CompareMatrices(L_unfused.get_coeffs(), L_fused.get_coeffs(),
283+
kTolerance, MatrixCompareType::relative))
284284
<< "Spatial momentum mismatch at angle = " << angle;
285285
}
286286
}

multibody/tree/multibody_tree.cc

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2843,16 +2843,35 @@ Vector3<T> MultibodyTree<T>::CalcCenterOfMassTranslationalAccelerationInWorld(
28432843
template <typename T>
28442844
SpatialMomentum<T> MultibodyTree<T>::CalcSpatialMomentumInWorldAboutPoint(
28452845
const systems::Context<T>& context, const Vector3<T>& p_WoP_W) const {
2846-
// Assemble a list of ModelInstanceIndex.
2847-
// Skip model_instance_index(0) which always contains the "world" body. The
2848-
// spatial momentum of the world body measured in the world is always zero.
2849-
std::vector<ModelInstanceIndex> model_instances;
2850-
for (ModelInstanceIndex model_instance_index(1);
2851-
model_instance_index < num_model_instances(); ++model_instance_index)
2852-
model_instances.push_back(model_instance_index);
2846+
// Efficienctly evaluate all mobods' spatial inertias, velocities, and poses.
2847+
const std::vector<SpatialInertia<T>>& M_Bi_W =
2848+
EvalSpatialInertiaInWorldCache(context);
2849+
const PositionKinematicsCache<T>& pc = EvalPositionKinematics(context);
2850+
const VelocityKinematicsCache<T>& vc = EvalVelocityKinematics(context);
2851+
2852+
// Form L_WSWo_W, the system S's spatial momentum in world W about Wo (world
2853+
// origin) expressed in W by doing a sum over all mobods in S.
2854+
SpatialMomentum<T> L_WSWo_W = SpatialMomentum<T>::Zero();
2855+
for (const SpanningForest::Mobod& mobod : forest().mobods()) {
2856+
if (mobod.is_world()) continue; // No contribution from the world.
2857+
2858+
// Form each mobod B's spatial momentum in W about Bo, expressed in W.
2859+
const MobodIndex mobod_index = mobod.index();
2860+
const SpatialInertia<T>& M_BBo_W = M_Bi_W[mobod_index];
2861+
const SpatialVelocity<T>& V_WBo_W = vc.get_V_WB(mobod_index);
2862+
SpatialMomentum<T> L_WBBo_W = M_BBo_W * V_WBo_W;
2863+
2864+
// Shift L_WBBo_W from "about Bo" to "about Wo" and accumulate the sum.
2865+
const RigidTransform<T>& X_WB = pc.get_X_WB(mobod_index);
2866+
const Vector3<T>& p_WoBo_W = X_WB.translation();
2867+
// After ShiftInPlace, L_WBBo_W is no longer "about Bo", instead L_WBBo_W
2868+
// is now L_WBWo_W (B's spatial momentum in W "about Wo", expressed in W).
2869+
L_WBBo_W.ShiftInPlace(-p_WoBo_W); // After this, L_WBBo_W is now L_WBWo_W.
2870+
L_WSWo_W += L_WBBo_W; // Actually is L_WSWo_W += L_WBWo_W.
2871+
}
28532872

2854-
return CalcSpatialMomentumInWorldAboutPoint(context, model_instances,
2855-
p_WoP_W);
2873+
// Shift system S's spatial momentum from "about Wo" to "about point P".
2874+
return L_WSWo_W.Shift(p_WoP_W); // returns L_WSP_W.
28562875
}
28572876

28582877
template <typename T>

0 commit comments

Comments
 (0)