Skip to content

Commit 8f3a3a3

Browse files
committed
Nuke useless FrameBase class; adds frame body pose cache.
Convert BodyNode functions to use the new cache.
1 parent 1ec9904 commit 8f3a3a3

14 files changed

+382
-185
lines changed

multibody/tree/BUILD.bazel

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ drake_cc_library(
5959
"acceleration_kinematics_cache.cc",
6060
"articulated_body_force_cache.cc",
6161
"articulated_body_inertia_cache.cc",
62+
"frame_body_pose_cache.cc",
6263
"position_kinematics_cache.cc",
6364
"velocity_kinematics_cache.cc",
6465
],
6566
hdrs = [
6667
"acceleration_kinematics_cache.h",
6768
"articulated_body_force_cache.h",
6869
"articulated_body_inertia_cache.h",
70+
"frame_body_pose_cache.h",
6971
"position_kinematics_cache.h",
7072
"velocity_kinematics_cache.h",
7173
],
@@ -89,7 +91,6 @@ drake_cc_library(
8991
"fixed_offset_frame.cc",
9092
"force_element.cc",
9193
"frame.cc",
92-
"frame_base.cc",
9394
"joint.cc",
9495
"joint_actuator.cc",
9596
"linear_bushing_roll_pitch_yaw.cc",
@@ -133,7 +134,6 @@ drake_cc_library(
133134
"fixed_offset_frame.h",
134135
"force_element.h",
135136
"frame.h",
136-
"frame_base.h",
137137
"joint.h",
138138
"joint_actuator.h",
139139
"linear_bushing_roll_pitch_yaw.h",

multibody/tree/body_node.h

+36-31
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ class BodyNode : public MultibodyElement<T> {
187187
// in the tree.)
188188
void CalcPositionKinematicsCache_BaseToTip(
189189
const systems::Context<T>& context,
190+
const FrameBodyPoseCache<T>& frame_body_pose_cache,
190191
PositionKinematicsCache<T>* pc) const {
191192
// This method must not be called for the "world" body node.
192193
DRAKE_ASSERT(topology_.rigid_body != world_index());
@@ -203,7 +204,7 @@ class BodyNode : public MultibodyElement<T> {
203204
// mobilizer. q(W:P) denotes all generalized positions in the kinematics
204205
// path between World and the parent body P. It assumes we are in a
205206
// base-to-tip recursion and therefore `X_WP` has already been updated.
206-
CalcAcrossMobilizerBodyPoses_BaseToTip(context, pc);
207+
CalcAcrossMobilizerBodyPoses_BaseToTip(frame_body_pose_cache, pc);
207208

208209
// TODO(amcastro-tri):
209210
// Update Body specific kinematics. These include:
@@ -381,6 +382,7 @@ class BodyNode : public MultibodyElement<T> {
381382
// MultibodyTree::CalcAccelerationKinematicsCache().
382383
void CalcSpatialAcceleration_BaseToTip(
383384
const systems::Context<T>& context,
385+
const FrameBodyPoseCache<T>& frame_body_poses_cache,
384386
const PositionKinematicsCache<T>& pc,
385387
const VelocityKinematicsCache<T>* vc,
386388
const VectorX<T>& mbt_vdot,
@@ -456,12 +458,11 @@ class BodyNode : public MultibodyElement<T> {
456458
// =========================================================================
457459
// Computation of A_PB = DtP(V_PB), Eq. (4).
458460

459-
// TODO(amcastro-tri): consider caching these. Also used in velocity
460-
// kinematics.
461-
const math::RotationMatrix<T> R_PF =
462-
frame_F.CalcRotationMatrixInBodyFrame(context);
463-
const math::RigidTransform<T> X_MB =
464-
frame_M.CalcPoseInBodyFrame(context).inverse();
461+
const math::RigidTransform<T>& X_PF =
462+
frame_F.get_X_BF(frame_body_poses_cache);
463+
const math::RotationMatrix<T>& R_PF = X_PF.rotation();
464+
const math::RigidTransform<T>& X_MB =
465+
frame_M.get_X_FB(frame_body_poses_cache);
465466

466467
// Form the rotation matrix relating the world frame W and parent body P.
467468
// Available since we are called within a base-to-tip recursion.
@@ -595,6 +596,7 @@ class BodyNode : public MultibodyElement<T> {
595596
// MultibodyTree::CalcInverseDynamics().
596597
void CalcInverseDynamics_TipToBase(
597598
const systems::Context<T>& context,
599+
const FrameBodyPoseCache<T>& frame_body_pose_cache,
598600
const PositionKinematicsCache<T>& pc,
599601
const std::vector<SpatialInertia<T>>& M_B_W_cache,
600602
const std::vector<SpatialForce<T>>* Fb_Bo_W_cache,
@@ -675,7 +677,8 @@ class BodyNode : public MultibodyElement<T> {
675677
// Compute shift vector from Bo to Mo expressed in the world frame W.
676678
const Frame<T>& frame_M = outboard_frame();
677679
DRAKE_DEMAND(frame_M.body().index() == body_B.index());
678-
const math::RigidTransform<T> X_BM = frame_M.CalcPoseInBodyFrame(context);
680+
const math::RigidTransform<T>& X_BM =
681+
frame_M.get_X_BF(frame_body_pose_cache); // F==M
679682
const Vector3<T>& p_BoMo_B = X_BM.translation();
680683
const math::RigidTransform<T>& X_WB = get_X_WB(pc);
681684
const math::RotationMatrix<T>& R_WB = X_WB.rotation();
@@ -700,8 +703,8 @@ class BodyNode : public MultibodyElement<T> {
700703
// p_CoMc_W:
701704
const Frame<T>& frame_Mc = child_node->outboard_frame();
702705
const math::RotationMatrix<T>& R_WC = child_node->get_X_WB(pc).rotation();
703-
const math::RigidTransform<T> X_CMc =
704-
frame_Mc.CalcPoseInBodyFrame(context);
706+
const math::RigidTransform<T>& X_CMc =
707+
frame_Mc.get_X_BF(frame_body_pose_cache); // B==C, F==Mc
705708
const Vector3<T>& p_CoMc_W = R_WC * X_CMc.translation();
706709

707710
// Shift position vector from child C outboard mobilizer frame Mc to body
@@ -775,6 +778,7 @@ class BodyNode : public MultibodyElement<T> {
775778
// with `context` by MultibodyTree::CalcPositionKinematicsCache().
776779
void CalcAcrossNodeJacobianWrtVExpressedInWorld(
777780
const systems::Context<T>& context,
781+
const FrameBodyPoseCache<T>& frame_body_pose_cache,
778782
const PositionKinematicsCache<T>& pc,
779783
EigenPtr<MatrixX<T>> H_PB_W) const {
780784
// Checks on the input arguments.
@@ -788,10 +792,11 @@ class BodyNode : public MultibodyElement<T> {
788792
// Outboard frame M of this node's mobilizer.
789793
const Frame<T>& frame_M = outboard_frame();
790794

791-
const math::RotationMatrix<T> R_PF =
792-
frame_F.CalcRotationMatrixInBodyFrame(context);
793-
const math::RigidTransform<T> X_MB =
794-
frame_M.CalcPoseInBodyFrame(context).inverse();
795+
const math::RigidTransform<T>& X_PF =
796+
frame_F.get_X_BF(frame_body_pose_cache); // B==P
797+
const math::RotationMatrix<T>& R_PF = X_PF.rotation();
798+
const math::RigidTransform<T>& X_MB =
799+
frame_M.get_X_FB(frame_body_pose_cache); // F==M
795800

796801
// Form the rotation matrix relating the world frame W and parent body P.
797802
const math::RotationMatrix<T>& R_WP = get_R_WP(pc);
@@ -1296,10 +1301,12 @@ class BodyNode : public MultibodyElement<T> {
12961301
// @pre pc and vc previously computed to be in sync with `context.
12971302
//
12981303
// @throws when `Ab_WB` is nullptr.
1299-
void CalcSpatialAccelerationBias(const systems::Context<T>& context,
1300-
const PositionKinematicsCache<T>& pc,
1301-
const VelocityKinematicsCache<T>& vc,
1302-
SpatialAcceleration<T>* Ab_WB) const {
1304+
void CalcSpatialAccelerationBias(
1305+
const systems::Context<T>& context,
1306+
const FrameBodyPoseCache<T>& frame_body_pose_cache,
1307+
const PositionKinematicsCache<T>& pc,
1308+
const VelocityKinematicsCache<T>& vc,
1309+
SpatialAcceleration<T>* Ab_WB) const {
13031310
DRAKE_THROW_UNLESS(Ab_WB != nullptr);
13041311
// As a guideline for developers, please refer to @ref
13051312
// abi_computing_accelerations for a detailed description and derivation of
@@ -1311,10 +1318,11 @@ class BodyNode : public MultibodyElement<T> {
13111318
const Frame<T>& frame_M = outboard_frame();
13121319

13131320
// Compute R_PF and X_MB.
1314-
const math::RotationMatrix<T> R_PF =
1315-
frame_F.CalcRotationMatrixInBodyFrame(context);
1316-
const math::RigidTransform<T> X_MB =
1317-
frame_M.CalcPoseInBodyFrame(context).inverse();
1321+
const math::RigidTransform<T>& X_PF =
1322+
frame_F.get_X_BF(frame_body_pose_cache); // B==P
1323+
const math::RotationMatrix<T>& R_PF = X_PF.rotation();
1324+
const math::RigidTransform<T>& X_MB =
1325+
frame_M.get_X_FB(frame_body_pose_cache); // F==M
13181326

13191327
// Parent position in the world is available from the position kinematics.
13201328
const math::RotationMatrix<T>& R_WP = get_R_WP(pc);
@@ -1733,7 +1741,7 @@ class BodyNode : public MultibodyElement<T> {
17331741
// between the world and the parent body P. It assumes we are in a base-to-tip
17341742
// recursion and therefore `X_WP` has already been updated.
17351743
void CalcAcrossMobilizerBodyPoses_BaseToTip(
1736-
const systems::Context<T>& context,
1744+
const FrameBodyPoseCache<T>& frame_body_pose_cache,
17371745
PositionKinematicsCache<T>* pc) const {
17381746
// RigidBody for this node.
17391747
const RigidBody<T>& body_B = body();
@@ -1753,8 +1761,10 @@ class BodyNode : public MultibodyElement<T> {
17531761
// - X_FM(q_B)
17541762
// - X_WP(q(W:B)), where q(W:B) includes all positions in the kinematics
17551763
// path from body B to the world W.
1756-
const math::RigidTransform<T> X_MB =
1757-
frame_M.CalcPoseInBodyFrame(context).inverse();
1764+
const math::RigidTransform<T>& X_MB =
1765+
frame_M.get_X_FB(frame_body_pose_cache); // F==M
1766+
const math::RigidTransform<T>& X_PF =
1767+
frame_F.get_X_BF(frame_body_pose_cache); // B==P
17581768
const math::RigidTransform<T>& X_FM =
17591769
get_X_FM(*pc); // mobilizer.Eval_X_FM(ctx)
17601770
const math::RigidTransform<T>& X_WP =
@@ -1771,12 +1781,7 @@ class BodyNode : public MultibodyElement<T> {
17711781
// In that case X_FB = X_FM as suggested by setting X_MB = Identity.
17721782
const math::RigidTransform<T> X_FB = X_FM * X_MB;
17731783

1774-
// Given the pose X_FB of body frame B measured in the mobilizer inboard
1775-
// frame F, we can ask frame F (who's parent body is P) for the pose of body
1776-
// B measured in the frame of the parent body P.
1777-
// In the particular case F = B, this method directly returns X_FB.
1778-
X_PB = frame_F.CalcOffsetPoseInBody(context, X_FB);
1779-
1784+
X_PB = X_PF * X_FB;
17801785
X_WB = X_WP * X_PB;
17811786

17821787
// Compute shift vector p_PoBo_W from the parent origin to the body origin.

multibody/tree/frame.h

+85-19
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
#include <memory>
44
#include <optional>
55
#include <string>
6+
#include <vector>
67

78
#include "drake/common/autodiff.h"
89
#include "drake/common/nice_type_name.h"
9-
#include "drake/multibody/math/spatial_algebra.h"
10-
#include "drake/multibody/tree/frame_base.h"
10+
#include "drake/multibody/tree/frame_body_pose_cache.h"
11+
#include "drake/multibody/tree/multibody_element.h"
1112
#include "drake/multibody/tree/multibody_tree_indexes.h"
1213
#include "drake/multibody/tree/multibody_tree_topology.h"
1314
#include "drake/multibody/tree/scoped_name.h"
@@ -23,39 +24,41 @@ std::string DeprecateWhenEmptyName(std::string name, std::string_view type);
2324
template<typename T> class RigidBody;
2425

2526
/// %Frame is an abstract class representing a _material frame_ (also called a
26-
/// _physical frame_), meaning that the %Frame's origin is a material point of
27-
/// a Body.
27+
/// _physical frame_) of its underlying RigidBody. The %Frame's origin is a
28+
/// material point of its RigidBody, and its axes have fixed directions
29+
/// in that body. A %Frame's pose (position and orientation) with respect to its
30+
/// RigidBodyFrame may be parameterized, but is fixed (not time or state
31+
/// dependent) once parameters have been set.
2832
///
29-
/// An important characteristic of a %Frame is that forces or torques applied
30-
/// to a %Frame are applied to the %Frame's underlying Body. Force-producing
33+
/// An important characteristic of a %Frame is that forces or torques applied to
34+
/// a %Frame are applied to the %Frame's underlying RigidBody. Force-producing
3135
/// elements like joints, actuators, and constraints usually employ two %Frames,
3236
/// with one %Frame connected to one body and the other connected to a different
33-
/// Body. Every %Frame object can report the RigidBody to which it is attached.
34-
/// Despite its name, %Frame is not the most general frame in Drake
35-
/// (see FrameBase for more information).
37+
/// body. Every %Frame F can report the RigidBody B to which it is attached and
38+
/// its pose X_BF with respect to B's RigidBodyFrame.
3639
///
3740
/// A %Frame's pose in World (or relative to other frames) is always calculated
38-
/// starting with its pose relative to its underlying %Body's BodyFrame.
41+
/// starting with its pose relative to its underlying RigidBodyFrame.
3942
/// Subclasses derived from %Frame differ in how kinematic calculations are
4043
/// performed. For example, the angular velocity of a FixedOffsetFrame or
41-
/// BodyFrame is identical to the angular velocity of its underlying body,
44+
/// RigidBodyFrame is identical to the angular velocity of its underlying body,
4245
/// whereas the translational velocity of a FixedOffsetFrame differs from that
43-
/// of a BodyFrame. If a %Frame is associated with a soft body, kinematic
44-
/// calculations can depend on the soft body's deformation state variables.
46+
/// of a RigidBodyFrame.
4547
///
46-
/// A %Frame object does _not_ store a Context (where Context means state that
47-
/// contains the %Frame's current orientation, position, motion, etc.).
48-
/// Instead, %Frame provides methods for calculating these %Frame-properties
49-
/// from a Context passed to %Frame methods.
48+
/// %Frame provides methods for obtaining its current orientation, position,
49+
/// motion, etc. from a Context passed to those methods.
5050
///
5151
/// @tparam_default_scalar
5252
template <typename T>
53-
class Frame : public FrameBase<T> {
53+
class Frame : public MultibodyElement<T> {
5454
public:
5555
DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN(Frame);
5656

5757
~Frame() override;
5858

59+
/// Returns this %Frame's unique index.
60+
FrameIndex index() const { return this->template index_impl<FrameIndex>(); }
61+
5962
/// Returns a const reference to the body associated to this %Frame.
6063
const RigidBody<T>& body() const {
6164
return body_;
@@ -80,6 +83,19 @@ class Frame : public FrameBase<T> {
8083
/// will be empty (the scope name and the element name).
8184
ScopedName scoped_name() const;
8285

86+
/// Returns a reference to the body-relative pose X_BF giving the pose of this
87+
/// Frame with respect to its body's RigidBodyFrame. This may depend on
88+
/// parameters in the Context but not on time or state. The first time this is
89+
/// called after a parameter change will precalculate offset poses for all
90+
/// %Frames into the Context's cache; subsequent calls on any %Frame are very
91+
/// fast.
92+
const math::RigidTransform<T>& EvalPoseInBodyFrame(
93+
const systems::Context<T>& context) const {
94+
const internal::FrameBodyPoseCache<T>& frame_body_poses =
95+
this->GetParentTreeSystem().EvalFrameBodyPoses(context);
96+
return get_X_BF(frame_body_poses);
97+
}
98+
8399
/// Returns the pose `X_BF` of `this` frame F in the body frame B associated
84100
/// with this frame.
85101
/// In particular, if `this` **is** the body frame B, this method directly
@@ -495,14 +511,62 @@ class Frame : public FrameBase<T> {
495511
return DoCloneToScalar(tree_clone);
496512
}
497513

514+
/// @name Internal use only
515+
/// These functions work directly with the frame body pose cache entry.
516+
//@{
517+
/// (Internal use only) A %Frame's pose-in-parent X_PF can be parameterized,
518+
/// the parent's pose may also be parameterized, and so on. Thus the
519+
/// calculation of this frame's pose in its body (X_BF) can be expensive.
520+
/// There is a cache entry that holds the calculated X_BF, evaluated
521+
/// whenever parameters change. This allows us to grab X_BF as a const
522+
/// reference rather than having to extract and reformat parameters, and
523+
/// compose with parent and ancestor poses at runtime.
524+
///
525+
/// At the time parameters are allocated we assign a slot in the body pose
526+
/// cache entry to each %Frame and record its index using this function. (The
527+
/// index for a RigidBodyFrame will refer to an identity transform.) Note that
528+
/// the body pose index is not necessarily the same as the %Frame index
529+
/// because all RigidBodyFrames can share an entry. (Of course if you know you
530+
/// are working with a RigidBodyFrame you don't need to ask about its body
531+
/// pose!)
532+
void set_body_pose_index_in_cache(int body_pose_index) {
533+
body_pose_index_in_cache_ = body_pose_index;
534+
}
535+
536+
/// (Internal use only) Retrieve this %Frame's body pose index in the cache.
537+
int get_body_pose_index_in_cache() const {
538+
return body_pose_index_in_cache_;
539+
}
540+
541+
/// (Internal use only) Given an already up-to-date frame body pose cache,
542+
/// extract X_BF for this %Frame from it.
543+
/// @note Be sure you have called MultibodyTreeSystem::EvalFrameBodyPoses()
544+
/// since the last parameter change; we can't check here.
545+
/// @retval X_BF pose of this frame in its body's frame
546+
const math::RigidTransform<T>& get_X_BF(
547+
const internal::FrameBodyPoseCache<T>& frame_body_poses) const {
548+
return frame_body_poses.get_X_BF(body_pose_index_in_cache_);
549+
}
550+
551+
/// (Internal use only) Given an already up-to-date frame body pose cache,
552+
/// extract X_FB (=X_BF⁻¹) for this %Frame from it.
553+
/// @note Be sure you have called MultibodyTreeSystem::EvalFrameBodyPoses()
554+
/// since the last parameter change; we can't check here.
555+
/// @retval X_FB inverse of this frame's pose in its body's frame
556+
const math::RigidTransform<T>& get_X_FB(
557+
const internal::FrameBodyPoseCache<T>& frame_body_poses) const {
558+
return frame_body_poses.get_X_FB(body_pose_index_in_cache_);
559+
}
560+
//@}
561+
498562
protected:
499563
/// Only derived classes can use this constructor. It creates a %Frame
500564
/// object attached to `body` and puts the frame in the body's model
501565
/// instance.
502566
explicit Frame(
503567
const std::string& name, const RigidBody<T>& body,
504568
std::optional<ModelInstanceIndex> model_instance = {})
505-
: FrameBase<T>(model_instance.value_or(body.model_instance())),
569+
: MultibodyElement<T>(model_instance.value_or(body.model_instance())),
506570
name_(internal::DeprecateWhenEmptyName(name, "Frame")),
507571
body_(body) {}
508572

@@ -586,6 +650,8 @@ class Frame : public FrameBase<T> {
586650

587651
// The internal bookkeeping topology struct used by MultibodyTree.
588652
internal::FrameTopology topology_;
653+
654+
int body_pose_index_in_cache_{-1};
589655
};
590656

591657
} // namespace multibody

multibody/tree/frame_base.cc

-15
This file was deleted.

0 commit comments

Comments
 (0)