7#include <janus/janus.hpp>
82 const Vec3<Scalar> &position) {
84 .mass = m, .cg = position, .inertia = Mat3<Scalar>::Zero()};
95 const Vec3<Scalar> &cg_pos,
96 const Scalar &Ixx,
const Scalar &Iyy,
98 Mat3<Scalar> I = Mat3<Scalar>::Zero();
120 const Scalar &Ixx,
const Scalar &Iyy,
const Scalar &Izz,
121 const Scalar &Ixy,
const Scalar &Ixz,
const Scalar &Iyz) {
148 const Vec3<Scalar> &cg_pos = Vec3<Scalar>::Zero()) {
149 Scalar I_diag = Scalar(0.4) * m * radius * radius;
150 return diagonal(m, cg_pos, I_diag, I_diag, I_diag);
164 const Vec3<Scalar> &cg_pos = Vec3<Scalar>::Zero()) {
165 Scalar r2 = radius * radius;
166 Scalar L2 = length * length;
167 Scalar Ixx = (Scalar(1) / Scalar(12)) * m * (Scalar(3) * r2 + L2);
168 Scalar Izz = Scalar(0.5) * m * r2;
169 return diagonal(m, cg_pos, Ixx, Ixx, Izz);
184 solid_box(
const Scalar &m,
const Scalar &dx,
const Scalar &dy,
186 const Vec3<Scalar> &cg_pos = Vec3<Scalar>::Zero()) {
187 Scalar k = Scalar(1) / Scalar(12);
188 Scalar Ixx = k * m * (dy * dy + dz * dz);
189 Scalar Iyy = k * m * (dx * dx + dz * dz);
190 Scalar Izz = k * m * (dx * dx + dy * dy);
191 return diagonal(m, cg_pos, Ixx, Iyy, Izz);
203 Mat3<Scalar> I = Mat3<Scalar>::Identity();
208 .mass = m, .cg = Vec3<Scalar>::Zero(), .inertia = I};
217 return diagonal(m, Vec3<Scalar>::Zero(), Ixx, Iyy, Izz);
224 const Scalar &Iyy,
const Scalar &Izz,
225 const Scalar &Ixy,
const Scalar &Ixz,
227 return from_components(m, Vec3<Scalar>::Zero(), Ixx, Iyy, Izz, Ixy, Ixz,
248 Vec3<Scalar> r =
cg - point;
249 Scalar r_dot_r = janus::dot(r, r);
253 J(0, 0) +=
mass * (r_dot_r - r(0) * r(0));
254 J(1, 1) +=
mass * (r_dot_r - r(1) * r(1));
255 J(2, 2) +=
mass * (r_dot_r - r(2) * r(2));
256 J(0, 1) -=
mass * r(0) * r(1);
257 J(1, 0) -=
mass * r(0) * r(1);
258 J(0, 2) -=
mass * r(0) * r(2);
259 J(2, 0) -=
mass * r(0) * r(2);
260 J(1, 2) -=
mass * r(1) * r(2);
261 J(2, 1) -=
mass * r(1) * r(2);
276 Scalar total_mass =
mass + other.
mass;
279 Vec3<Scalar> combined_cg =
285 Mat3<Scalar> combined_inertia = I1_at_cg + I2_at_cg;
288 .mass = total_mass, .cg = combined_cg, .inertia = combined_inertia};
296 return *
this + (Scalar(-1) * other);
304 .mass =
mass * factor, .cg =
cg, .inertia =
inertia * factor};
309 return *
this * (Scalar(1) / factor);
314 *
this = *
this + other;
329template <
typename Scalar>
332 return props * factor;
346template <
typename Scalar>
349 if (components.empty()) {
351 .cg = Vec3<Scalar>::Zero(),
352 .inertia = Mat3<Scalar>::Zero()};
356 for (
size_t i = 1; i < components.size(); ++i) {
357 result = result + components[i];
368template <
typename Scalar>
369MassProperties<Scalar>
371 const Mat3<Scalar> &rotation,
372 const Vec3<Scalar> &translation) {
374 Vec3<Scalar> new_cg = rotation * (props.
cg - translation);
377 Mat3<Scalar> new_inertia = rotation * props.
inertia * rotation.transpose();
380 .mass = props.
mass, .cg = new_cg, .inertia = new_inertia};
395template <
typename Scalar>
397 static_assert(std::is_same_v<Scalar, double>,
398 "is_physically_valid only works with double");
400 if (props.
mass < 0) {
405 Eigen::SelfAdjointEigenSolver<Mat3<double>> solver(props.
inertia);
406 Vec3<double> eigs = solver.eigenvalues();
409 if (eigs(0) < 0 || eigs(1) < 0 || eigs(2) < 0) {
414 if (eigs(0) + eigs(1) < eigs(2) || eigs(0) + eigs(2) < eigs(1) ||
415 eigs(1) + eigs(2) < eigs(0)) {
423template <
typename Scalar>
425 static_assert(std::is_same_v<Scalar, double>,
426 "is_point_mass only works with double");
427 return props.
inertia.norm() < 1e-12;
431template <
typename Scalar>
433 static_assert(std::is_same_v<Scalar, double>,
434 "principal_moments only works with double");
435 Eigen::SelfAdjointEigenSolver<Mat3<double>> solver(props.
inertia);
436 return solver.eigenvalues();
440template <
typename Scalar>
442 static_assert(std::is_same_v<Scalar, double>,
443 "principal_axes only works with double");
444 Eigen::SelfAdjointEigenSolver<Mat3<double>> solver(props.
inertia);
445 return solver.eigenvectors();
Definition MassProperties.hpp:12
MassProperties< Scalar > operator*(const Scalar &factor, const MassProperties< Scalar > &props)
Left-multiplication: factor * props.
Definition MassProperties.hpp:330
MassProperties< Scalar > transform_mass_properties(const MassProperties< Scalar > &props, const Mat3< Scalar > &rotation, const Vec3< Scalar > &translation)
Definition MassProperties.hpp:370
Mat3< Scalar > principal_axes(const MassProperties< Scalar > &props)
Compute principal axes rotation matrix (eigenvectors, numeric only).
Definition MassProperties.hpp:441
bool is_physically_valid(const MassProperties< Scalar > &props)
Definition MassProperties.hpp:396
bool is_point_mass(const MassProperties< Scalar > &props)
Check if effectively a point mass (zero inertia).
Definition MassProperties.hpp:424
MassProperties< Scalar > aggregate_mass_properties(const std::vector< MassProperties< Scalar > > &components)
Definition MassProperties.hpp:347
Vec3< Scalar > principal_moments(const MassProperties< Scalar > &props)
Compute principal moments of inertia (eigenvalues, numeric only).
Definition MassProperties.hpp:432
Definition MassProperties.hpp:65
static MassProperties< Scalar > solid_box(const Scalar &m, const Scalar &dx, const Scalar &dy, const Scalar &dz, const Vec3< Scalar > &cg_pos=Vec3< Scalar >::Zero())
Definition MassProperties.hpp:184
static MassProperties< Scalar > solid_sphere(const Scalar &m, const Scalar &radius, const Vec3< Scalar > &cg_pos=Vec3< Scalar >::Zero())
Definition MassProperties.hpp:147
Vec3< Scalar > cg
CG position in body frame [m].
Definition MassProperties.hpp:67
static MassProperties< Scalar > diagonal(const Scalar &m, const Vec3< Scalar > &cg_pos, const Scalar &Ixx, const Scalar &Iyy, const Scalar &Izz)
Definition MassProperties.hpp:94
static MassProperties< Scalar > point_mass(const Scalar &m, const Vec3< Scalar > &position)
Definition MassProperties.hpp:81
MassProperties< Scalar > operator*(const Scalar &factor) const
Definition MassProperties.hpp:302
Scalar mass
Total mass [kg].
Definition MassProperties.hpp:66
MassProperties< Scalar > operator-(const MassProperties< Scalar > &other) const
Definition MassProperties.hpp:295
MassProperties< Scalar > operator/(const Scalar &factor) const
Divide mass properties by a factor.
Definition MassProperties.hpp:308
MassProperties< Scalar > & operator+=(const MassProperties< Scalar > &other)
In-place addition.
Definition MassProperties.hpp:313
static MassProperties< Scalar > from_components(const Scalar &m, const Vec3< Scalar > &cg_pos, const Scalar &Ixx, const Scalar &Iyy, const Scalar &Izz, const Scalar &Ixy, const Scalar &Ixz, const Scalar &Iyz)
Definition MassProperties.hpp:119
static MassProperties< Scalar > solid_cylinder(const Scalar &m, const Scalar &radius, const Scalar &length, const Vec3< Scalar > &cg_pos=Vec3< Scalar >::Zero())
Definition MassProperties.hpp:163
static MassProperties< Scalar > diagonal(const Scalar &m, const Scalar &Ixx, const Scalar &Iyy, const Scalar &Izz)
Definition MassProperties.hpp:214
Mat3< Scalar > inertia_about_point(const Vec3< Scalar > &point) const
Definition MassProperties.hpp:247
MassProperties< Scalar > operator+(const MassProperties< Scalar > &other) const
Definition MassProperties.hpp:275
Mat3< Scalar > inertia
Inertia tensor about CG, in body-fixed axes [kg·m²].
Definition MassProperties.hpp:69
static MassProperties< Scalar > from_mass(const Scalar &m)
Definition MassProperties.hpp:201
static MassProperties< Scalar > full(const Scalar &m, const Scalar &Ixx, const Scalar &Iyy, const Scalar &Izz, const Scalar &Ixy, const Scalar &Ixz, const Scalar &Iyz)
Definition MassProperties.hpp:223
Vec3< Scalar > cg_offset() const
Definition MassProperties.hpp:325