You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Conception/drake-master/multibody/math/spatial_acceleration.h

358 lines
19 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#pragma once
#ifndef DRAKE_SPATIAL_ALGEBRA_HEADER
#error Please include "drake/multibody/math/spatial_algebra.h", not this file.
#endif
#include <limits>
#include "drake/common/default_scalars.h"
#include "drake/common/drake_assert.h"
#include "drake/common/drake_copyable.h"
#include "drake/common/eigen_types.h"
#include "drake/math/convert_time_derivative.h"
#include "drake/multibody/math/spatial_vector.h"
#include "drake/multibody/math/spatial_velocity.h"
namespace drake {
namespace multibody {
/// This class represents a _spatial acceleration_ A and has 6 elements with
/// an angular (rotational) acceleration α (3-element vector) on top of a
/// translational (linear) acceleration 𝐚 (3-element vector). Spatial
/// acceleration represents the rotational and translational acceleration of a
/// frame B with respect to a _measured-in_ frame M. This class assumes that
/// both the angular acceleration α and translational acceleration 𝐚 are
/// expressed in the same _expressed-in_ frame E. This class only stores 6
/// elements (namely α and 𝐚) and does not store the underlying frames B, M, E.
/// The user is responsible for explicitly tracking the underlying frames with
/// @ref multibody_quantities "monogram notation". For example, A_MB_E denotes
/// frame B's spatial acceleration measured in frame M, expressed in frame E and
/// contains alpha_MB_E (B's angular acceleration measured in M, expressed in E)
/// and a_MBo_E (Bo's translational acceleration measured in M, expressed in E),
/// where Bo is frame B's origin point.
/// For an @ref multibody_frames_and_bodies "offset frame" Bp, the monogram
/// notation A_MBp_E denotes frame Bp's spatial acceleration measured in M,
/// expressed in E. Details on spatial vectors and monogram notation are in
/// sections @ref multibody_spatial_vectors and @ref multibody_quantities.
///
/// The typeset for A_MB is @f$\,{^MA^B}@f$ and its definition is
/// @f$^MA^B = \frac{^Md}{dt}\,{^MV^B}\,@f$, where @f${^MV^B}@f$ is frame B's
/// spatial velocity in frame M and @f$\frac{^Md}{dt}@f$ denotes the time
/// derivative taken in frame M. To differentiate a vector, we need to
/// specify in what frame the time derivative is taken, see [Mitiguy 2022, §7.2]
/// for an in-depth discussion. Time derivatives in different frames are related
/// by the "Transport Theorem", which in Drake is implemented in
/// drake::math::ConvertTimeDerivativeToOtherFrame().
/// In source code (monogram) notation, we write A_MB = DtM(V_MB), where
/// DtM() denotes the time derivative in frame M. Details on vector
/// differentiation is in section @ref Dt_multibody_quantities.
///
/// [Mitiguy 2022] Mitiguy, P., 2022. Advanced Dynamics & Motion Simulation.
///
/// @tparam_default_scalar
template <typename T>
class SpatialAcceleration : public SpatialVector<SpatialAcceleration, T> {
// We need the fully qualified class name below for the clang compiler to
// work. Without qualifiers the code is legal according to the C++11 standard
// but the clang compiler still gets confused. See:
// http://stackoverflow.com/questions/17687459/clang-not-accepting-use-of-template-template-parameter-when-using-crtp
typedef SpatialVector<::drake::multibody::SpatialAcceleration, T> Base;
public:
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(SpatialAcceleration)
/// Default constructor. In Release builds, all 6 elements of a newly
/// constructed spatial acceleration are uninitialized (for speed). In Debug
/// builds, the 6 elements are set to NaN so that invalid operations on an
/// uninitialized spatial acceleration fail fast (fast bug detection).
SpatialAcceleration() : Base() {}
/// Constructs a spatial acceleration A from an angular acceleration α (alpha)
/// and a translational acceleration 𝐚.
SpatialAcceleration(const Eigen::Ref<const Vector3<T>>& alpha,
const Eigen::Ref<const Vector3<T>>& a) : Base(alpha, a) {}
/// Constructs a spatial acceleration A from an Eigen expression that
/// represents a 6-element vector, i.e., a 3-element angular acceleration α
/// and a 3-element translational acceleration 𝐚. This constructor will assert
/// the size of A is six (6) either at compile-time for fixed sized Eigen
/// expressions or at run-time for dynamic sized Eigen expressions.
template <typename Derived>
explicit SpatialAcceleration(const Eigen::MatrixBase<Derived>& A) : Base(A) {}
/// In-place shift of a %SpatialAcceleration from a frame B to a frame C,
/// where both B and C are fixed to the same frame or rigid body. On entry,
/// `this` is A_MB_E (frame B's spatial acceleration measured in a frame M and
/// expressed in a frame E). On return `this` is modified to A_MC_E (frame C's
/// spatial acceleration measured in frame M and expressed in frame E).
/// @param[in] offset which is the position vector p_BoCo_E from Bo (frame B's
/// origin) to Co (frame C's origin), expressed in frame E. p_BoCo_E must have
/// the same expressed-in frame E as `this` spatial acceleration.
/// @param[in] angular_velocity_of_this_frame which is ω_MB_E, frame B's
/// angular velocity measured in frame W and expressed in frame E.
/// @retval A_MC_E reference to `this` spatial acceleration which has been
/// modified to be frame C's spatial acceleration measured in frame M and
/// expressed in frame E. The components of A_MC_E are calculated as: <pre>
/// α_MC_E = α_MB_E (angular acceleration of `this` is unchanged).
/// a_MCo_E = a_MBo_E + α_MB_E x p_BoCo_E + ω_MB_E x (ω_MB_E x p_BoCo_E)
/// </pre>
/// @see Shift() to shift spatial acceleration without modifying `this`.
/// Use ComposeWithMovingFrameAcceleration() if frame C is moving on frame B.
///
/// <h3> Derivation </h3>
///
/// <h4> Rotational acceleration component </h4>
///
/// Frame B and frame C are fixed (e.g., welded) to the same rigid object.
/// Hence frames B and C always rotate together at the same rate and: <pre>
/// ω_MC_E = ω_MB_E
/// α_MC_E = α_MB_E
/// </pre>
///
/// <h4> Translational acceleration component </h4>
///
/// Since frames B and C are fixed to the same rigid object, the translational
/// velocity of Co (frame C's origin) measured in frame M can be calculated as
/// <pre>
/// v_MCo = v_MBo + ω_MB x p_BoCo
/// </pre>
/// Point Co's translational acceleration in frame M is: <pre>
/// a_MCo = DtM(v_MCo) (definition of acceleration).
/// = DtM(v_MBo + ω_MB x p_BoCo) (substitution)
/// = DtM(v_MBo) + DtM(ω_MB) x p_BoCo + ω_MB x DtM(p_BoCo)
/// = a_MBo + α_MB x p_BoCo + ω_MB x DtM(p_BoCo)
/// </pre>
/// The "Transport Theorem" converts the time-derivative of the last term from
/// DtM() to DtB() -- see math::ConvertTimeDerivativeToOtherFrame(), as <pre>
/// DtM(p_BoCo) = DtB(p_BoCo) + ω_MB x p_BoCo
/// = 0 + ω_MB x p_BoCo
/// </pre>
SpatialAcceleration<T>& ShiftInPlace(
const Vector3<T>& offset,
const Vector3<T>& angular_velocity_of_this_frame) {
const Vector3<T>& p_BoCo_E = offset;
const Vector3<T>& w_MB_E = angular_velocity_of_this_frame;
// Frame B's angular acceleration measured in frame M, expressed in frame M.
const Vector3<T>& alpha_MB_E = this->rotational();
// Calculate point Co's translational acceleration measured in M.
Vector3<T>& a_MCo_E = this->translational();
a_MCo_E += (alpha_MB_E.cross(p_BoCo_E)
+ w_MB_E.cross(w_MB_E.cross(p_BoCo_E)));
return *this;
}
/// Shifts a %SpatialAcceleration from a frame B to a frame C, where both
/// B and C are fixed to the same frame or rigid body.
/// @param[in] offset which is the position vector p_BoCo_E from Bo (frame B's
/// origin) to Co (frame C's origin), expressed in frame E. p_BoCo_E must have
/// the same expressed-in frame E as `this` spatial acceleration, where `this`
/// is A_MB_E (frame B's spatial acceleration measured in M, expressed in E).
/// @param[in] angular_velocity_of_this_frame which is ω_MB_E, frame B's
/// angular velocity measured in frame M and expressed in frame E.
/// @retval A_MC_E which is frame C's spatial acceleration measured in
/// frame M, expressed in frame E.
/// @note Shift() differs from ShiftInPlace() in that Shift() does not modify
/// `this` whereas ShiftInPlace() does modify `this`.
/// @see ShiftInPlace() for more information and how A_MC_E is calculated.
/// Use ComposeWithMovingFrameAcceleration() if frame C is moving on frame B.
SpatialAcceleration<T> Shift(
const Vector3<T>& offset,
const Vector3<T>& angular_velocity_of_this_frame) const {
return SpatialAcceleration<T>(*this).ShiftInPlace(
offset, angular_velocity_of_this_frame);
}
/// (Advanced) Given `this` spatial acceleration A_MB of a frame B measured
/// in a frame M, shifts %SpatialAcceleration from frame B to a frame C (i.e.,
/// A_MB to A_MC), where both B and C are fixed to the same frame or rigid
/// body and where ω_MB = 0 (frame B's angular velocity in frame M is zero).
/// @param[in] offset which is the position vector p_BoCo_E from Bo (frame B's
/// origin) to Co (frame C's origin), expressed in frame E. p_BoCo_E must have
/// the same expressed-in frame E as `this` spatial acceleration, where `this`
/// is A_MB_E (frame B's spatial acceleration measured in M, expressed in E).
/// @retval A_MC_E which is frame C's spatial acceleration measured in
/// frame M, expressed in frame E.
/// @see ShiftInPlace() for more information and how A_MC_E is calculated.
/// @note ShiftWithZeroAngularVelocity() speeds the Shift() computation when
/// ω_MB = 0, even if α_MB ≠ 0 (α_MB is stored in `this`).
SpatialAcceleration<T> ShiftWithZeroAngularVelocity(
const Vector3<T>& offset) const {
const Vector3<T>& p_BoCo_E = offset;
const Vector3<T>& alpha_MB_E = this->rotational();
const Vector3<T>& a_MBo_E = this->translational();
return SpatialAcceleration<T>(alpha_MB_E,
a_MBo_E + alpha_MB_E.cross(p_BoCo_E));
}
/// Compose `this` spatial acceleration (measured in some frame M) with the
/// spatial acceleration of another frame to form the 𝐨𝐭𝐡𝐞𝐫 frame's spatial
/// acceleration in frame M. Herein, `this` is the spatial acceleration of a
/// frame (designated B) in frame M and the 𝐨𝐭𝐡𝐞𝐫 frame is designated C.
/// @param[in] position_of_moving_frame which is the position vector p_BoCo_E
/// (from frame B's origin Bo to frame C's origin Co), expressed in frame E.
/// p_BoCo_E must have the same expressed-in frame E as `this`, where `this`
/// is A_MB_E (frame B's spatial acceleration measured in M, expressed in E).
/// @param[in] angular_velocity_of_this_frame which is ω_MB_E, frame B's
/// angular velocity measured in frame W and expressed in frame E.
/// @param[in] velocity_of_moving_frame which is V_BC_E, frame C's spatial
/// velocity measured in frame B, expressed in frame E.
/// @param[in] acceleration_of_moving_frame which is A_BC_E, frame C's
/// spatial acceleration measured in frame B, expressed in frame E.
/// @retval A_MC_E frame C's spatial acceleration measured in frame M,
/// expressed in frame E.
/// @see SpatialVelocity::ComposeWithMovingFrameVelocity().
/// Use Shift() if frames B and C are both fixed to the same frame or body,
/// i.e., velocity_of_moving_frame = 0 and acceleration_of_moving_frame = 0.
/// @note The returned spatial acceleration A_MC_E contains an angular
/// acceleration α_MC_E and translational acceleration a_MCo_E that are
/// calculated as: <pre>
/// α_MC_E = α_MB_E + α_BC_E + ω_MB_E x ω_BC_E
/// a_MCo_E = a_BCo_E + α_MB_E x p_BoCo_E + ω_MB_E x (ω_MB_E x p_BoCo_E)
/// + 2 ω_MB_E x v_BCo_E + a_BCo_E
/// </pre>
/// If frame C is rigidly fixed to frame B, A_BC_E = 0 and V_BC_E = 0 and
/// this method produces a Shift() operation (albeit inefficiently).
/// The previous equations show composing spatial acceleration is not simply
/// adding A_MB + A_BC and these equations differ significantly from their
/// spatial velocity counterparts. For example, angular velocities simply add
/// as <pre>
/// ω_MC = ω_MB + ω_BC, but 3D angular acceleration is more complicated as
/// α_MC = α_MB + α_BC + ω_MB x ω_BC
/// </pre>
///
/// <h3> Derivation </h3>
///
/// <h4> Rotational acceleration component </h4>
///
/// ω_MC (frame C's angular velocity in frame M) can be calculated with the
/// angular velocity addition theorem as <pre>
/// ω_MC = ω_MB + ω_BC
/// </pre>
/// α_MC (frame C's angular acceleration measured in frame M) is defined as
/// the time-derivative in frame M of ω_MC, and can be calculated using the
/// "Transport Theorem" (Golden rule for vector differentation) which converts
/// the time-derivative of a vector in frame M to frame B, e.g., as
/// DtM(ω_BC) = DtB(ω_BC) + ω_MB x ω_BC, as <pre>
/// α_MC = DtM(ω_MC) = DtM(ω_MB) + DtM(ω_BC)
/// = α_MB + DtB(ω_BC) + ω_MB x ω_BC
/// = α_MB + α_BC + ω_MB x ω_BC (End of proof).
/// </pre>
///
/// <h4> Translational acceleration component </h4>
///
/// v_MCo (frame C's translational velocity in frame M) is calculated in
/// SpatialVelocity::ComposeWithMovingFrameVelocity) as <pre>
/// v_MCo = v_MBo + ω_MB x p_BoCo + v_BCo
/// </pre>
/// a_MCo (frame C's translational acceleration measured in frame M) is
/// defined as the time-derivative in frame M of v_MCo, calculated as <pre>
/// a_MCo = DtM(v_MCo) Definition.
/// = DtM(v_MBo + ω_MB x p_BoCo + v_BCo) Substitution.
/// = DtM(v_MBo) + DtM(ω_MB) x p_BoCo + ω_MB x DtM(p_BoCo) + DtM(v_BCo)
/// = a_MBo + α_MB x p_BoCo + ω_MB x DtM(p_BoCo) + DtM(v_BCo)
/// </pre>
/// The last two terms are modified using the "Transport Theorem" (Golden rule
/// for vector differentation) which converts time-derivatives of vectors in
/// frame M to frame B via DtM(vec) = DtB(vec) + ω_MB x vec. <pre>
/// DtM(p_BoCo) = DtB(p_BoCo) + ω_MB x p_BoCo
/// = v_BCo + ω_MB x p_BoCo
/// DtM(v_BCo) = DtB(v_BCo) + ω_MB x v_BCo
/// = a_BCo + ω_MB x v_BCo
/// </pre>
/// Combining the last few equations proves the formula for a_MCo as: <pre>
/// a_MCo = a_MBo + α_MB x p_BoCo + ω_MB x (ω_MB x p_BoCo)
/// + 2 ω_MB x v_BCo + a_BCo (End of proof).
/// </pre>
/// Some terms in the previous equation have names, e.g., <pre>
/// centripetal acceleration ω_MB x (ω_MB x p_BoCo)
/// Coriolis acceleration 2 ω_MB x v_BCo
/// Coincident point acceleration, i.e., acceleration of the point of frame
/// B coincident with Co a_MBo + α_MB x p_BoCo + ω_MB x (ω_MB x p_BoCo)
/// </pre>
/// Note: The coincident point acceleration can be calculated with a Shift().
///
/// Note: The three cross products appearing in the previous calculation of
/// a_MCo can be reduced to one, possibly improving efficiency via <pre>
/// ω_MB x (ω_MB x p_BoCo) + 2 ω_MB x v_BCo = ω_MB x (v_MCo - v_MBo + v_BCo)
/// </pre>
/// To show this, we rearrange and substitute our expression for v_MCo. <pre>
/// v_MCo = v_MBo + ω_MB x p_BoCo + v_BCo which rearranges to
/// ω_MB x p_BoCo = v_MCo - v_MBo - v_BCo. Substitution produces
/// ω_MB x (ω_MB x p_BoCo) = ω_MB x (v_MCo - v_MBo - v_BCo) Hence,
/// ω_MB x (ω_MB x p_BoCo) + 2 ω_MB x v_BCo = ω_MB x (v_MCo - v_MBo + v_BCo)
/// </pre>
SpatialAcceleration<T> ComposeWithMovingFrameAcceleration(
const Vector3<T>& position_of_moving_frame,
const Vector3<T>& angular_velocity_of_this_frame,
const SpatialVelocity<T>& velocity_of_moving_frame,
const SpatialAcceleration<T>& acceleration_of_moving_frame) const {
// This operation can be written in a compact form using the rigid shift
// operator Φᵀ(p_BoCo) (documented in SpatialVelocity::Shift()) and
// Ac_MC(ω_MB, V_BC) which contains the centrifugal and Coriolis terms:
// A_MC = Φᵀ(p_BoCo) A_MB + Ac_MC(ω_MB, V_BC) + A_BC
// Ac_MC(ω_MB, V_BC) = | ω_MB x ω_BC |
// | ω_MB x (ω_MB x p_BoCo) + 2 ω_MB x v_BCo |
// ^^^^^^^^^^^ ^^^^^^^^
// centrifugal Coriolis
const Vector3<T>& p_PB_E = position_of_moving_frame;
const Vector3<T>& w_WP_E = angular_velocity_of_this_frame;
const SpatialVelocity<T>& V_PB_E = velocity_of_moving_frame;
const SpatialAcceleration<T>& A_PB_E = acceleration_of_moving_frame;
const Vector3<T>& w_PB_E = V_PB_E.rotational();
const Vector3<T>& v_PB_E = V_PB_E.translational();
// Use Shift() to calculate the coincident point acceleration, i.e.,
// acceleration of the point of frame B coincident with Co as
// a_MBo + α_MB x p_BoCo + ω_MB x (ω_MB x p_BoCo).
SpatialAcceleration<T> A_WB_E = this->Shift(p_PB_E, w_WP_E);
// Adds additional term in angular acceleration calculation, i.e.,
// α_MC = α_MB + α_BC + ω_MB x ω_BC.
const Vector3<T>& alpha_PB_E = A_PB_E.rotational();
A_WB_E.rotational() += (alpha_PB_E + w_WP_E.cross(w_PB_E));
// Adds Coriolis and translational acceleration of B in P.
// a_MCo = ... a_BCo + 2 ω_MB x v_BCo
const Vector3<T>& a_PB_E = A_PB_E.translational();
A_WB_E.translational() += (a_PB_E + 2.0 * w_WP_E.cross(v_PB_E));
return A_WB_E;
}
};
/// Adds two spatial accelerations by simply adding their 6 underlying elements.
/// @param[in] A1_E spatial acceleration expressed in the same frame E as A2_E.
/// @param[in] A2_E spatial acceleration expressed in the same frame E as A1_E.
/// @note The general utility of this operator+() function is questionable and
/// it should only be used if you are sure it makes sense.
/// @see Shift(), ShiftInPlace(), and ComposeWithMovingFrameAcceleration().
/// @relates SpatialAcceleration
template <typename T>
inline SpatialAcceleration<T> operator+(const SpatialAcceleration<T>& A1_E,
const SpatialAcceleration<T>& A2_E) {
// Although this operator+() function simply calls an associated
// SpatialVector operator+=() function, it is needed for documentation.
return SpatialAcceleration<T>(A1_E) += A2_E;
}
/// Subtracts spatial accelerations by simply subtracting their 6 underlying
/// elements.
/// @param[in] A1_E spatial acceleration expressed in the same frame E as A2_E.
/// @param[in] A2_E spatial acceleration expressed in the same frame E as A1_E.
/// @note The general utility of this operator-() function is questionable and
/// it should only be used if you are sure it makes sense.
/// @see Shift(), ShiftInPlace(), and ComposeWithMovingFrameAcceleration().
/// @relates SpatialAcceleration
template <typename T>
inline SpatialAcceleration<T> operator-(const SpatialAcceleration<T>& A1_E,
const SpatialAcceleration<T>& A2_E) {
// Although this operator-() function simply calls an associated
// SpatialVector operator-=() function, it is needed for documentation.
return SpatialAcceleration<T>(A1_E) -= A2_E;
}
} // namespace multibody
} // namespace drake
DRAKE_DECLARE_CLASS_TEMPLATE_INSTANTIATIONS_ON_DEFAULT_SCALARS(
class ::drake::multibody::SpatialAcceleration)