17 #ifndef GZ_MATH_MASSMATRIX3_HH_
18 #define GZ_MATH_MASSMATRIX3_HH_
26 #include <gz/math/config.hh>
37 inline namespace GZ_MATH_VERSION_NAMESPACE {
58 : mass(_mass), Ixxyyzz(_ixxyyzz), Ixyxzyz(_ixyxzyz)
74 return this->IsValid();
93 const T &_ixx,
const T &_iyy,
const T &_izz,
94 const T &_ixy,
const T &_ixz,
const T &_iyz)
96 this->Ixxyyzz.Set(_ixx, _iyy, _izz);
97 this->Ixyxzyz.Set(_ixy, _ixz, _iyz);
98 return this->IsValid();
105 return this->Ixxyyzz;
112 return this->Ixyxzyz;
120 this->Ixxyyzz = _ixxyyzz;
121 return this->IsValid();
129 this->Ixyxzyz = _ixyxzyz;
130 return this->IsValid();
137 return this->Ixxyyzz[0];
144 return this->Ixxyyzz[1];
151 return this->Ixxyyzz[2];
158 return this->Ixyxzyz[0];
165 return this->Ixyxzyz[1];
172 return this->Ixyxzyz[2];
181 return this->IsValid();
190 return this->IsValid();
199 return this->IsValid();
208 return this->IsValid();
217 return this->IsValid();
226 return this->IsValid();
234 this->Ixxyyzz[0], this->Ixyxzyz[0], this->Ixyxzyz[1],
235 this->Ixyxzyz[0], this->Ixxyyzz[1], this->Ixyxzyz[2],
236 this->Ixyxzyz[1], this->Ixyxzyz[2], this->Ixxyyzz[2]);
246 this->Ixxyyzz.Set(_moi(0, 0), _moi(1, 1), _moi(2, 2));
248 0.5*(_moi(0, 1) + _moi(1, 0)),
249 0.5*(_moi(0, 2) + _moi(2, 0)),
250 0.5*(_moi(1, 2) + _moi(2, 1)));
251 return this->IsValid();
266 return equal<T>(this->mass, _m.
Mass()) &&
276 return !(*
this == _m);
299 GZ_MASSMATRIX3_DEFAULT_TOLERANCE<T>)
const
301 const T epsilon = this->Epsilon(_tolerance);
305 return (this->mass >= 0) &&
306 (this->Ixx() + epsilon >= 0) &&
307 (this->Ixx() * this->Iyy() -
std::pow(this->Ixy(), 2) +
309 (this->Moi().Determinant() + epsilon >= 0);
332 GZ_MASSMATRIX3_DEFAULT_TOLERANCE<T>)
const
334 const T epsilon = this->Epsilon(_tolerance);
338 return (this->mass > 0) &&
339 (this->Ixx() + epsilon > 0) &&
340 (this->Ixx() * this->Iyy() -
std::pow(this->Ixy(), 2) +
342 (this->Moi().Determinant() + epsilon > 0);
353 GZ_MASSMATRIX3_DEFAULT_TOLERANCE<T>)
const
355 return Epsilon(this->DiagonalMoments(), _tolerance);
381 GZ_MASSMATRIX3_DEFAULT_TOLERANCE<T>)
398 T maxPossibleMoI = 0.5 * std::abs(_moments.
Sum());
419 GZ_MASSMATRIX3_DEFAULT_TOLERANCE<T>)
const
421 return this->IsNearPositive(_tolerance) &&
422 ValidMoments(this->PrincipalMoments(), _tolerance);
446 const T _tolerance = GZ_MASSMATRIX3_DEFAULT_TOLERANCE<T>)
448 T epsilon = Epsilon(_moments, _tolerance);
450 return _moments[0] + epsilon >= 0 &&
451 _moments[1] + epsilon >= 0 &&
452 _moments[2] + epsilon >= 0 &&
453 _moments[0] + _moments[1] + epsilon >= _moments[2] &&
454 _moments[1] + _moments[2] + epsilon >= _moments[0] &&
455 _moments[2] + _moments[0] + epsilon >= _moments[1];
472 T tol = _tol * this->Ixxyyzz.Max();
476 return this->Ixxyyzz;
487 T c = Id[0]*Id[1] -
std::pow(Ip[0], 2)
495 - 2*Ip[0]*Ip[1]*Ip[2];
510 T q = 2*
std::pow(b, 3) - 9*b*c - 27*d;
514 T delta = acos(clamp<T>(0.5 * q /
std::pow(p, 1.5), -1, 1));
517 T moment0 = (b + 2*sqrt(p) * cos(delta / 3.0)) / 3.0;
518 T moment1 = (b + 2*sqrt(p) * cos((delta + 2*
GZ_PI)/3.0)) / 3.0;
519 T moment2 = (b + 2*sqrt(p) * cos((delta - 2*
GZ_PI)/3.0)) / 3.0;
520 sort3(moment0, moment1, moment2);
537 Vector3<T> moments = this->PrincipalMoments(_tol);
539 T tol = _tol * this->Ixxyyzz.Max();
540 if (moments.
Equal(this->Ixxyyzz, tol) ||
541 (math::equal<T>(moments[0], moments[1], std::abs(tol)) &&
542 math::equal<T>(moments[0], moments[2], std::abs(tol))))
566 Vector2<T> f1(this->Ixyxzyz[0], -this->Ixyxzyz[1]);
567 Vector2<T> f2(this->Ixxyyzz[1] - this->Ixxyyzz[2],
568 -2*this->Ixyxzyz[2]);
572 Vector2<T> momentsDiff(moments[0] - moments[1],
573 moments[1] - moments[2]);
576 int unequalMoment = -1;
577 if (equal<T>(momentsDiff[0], 0, std::abs(tol)))
579 else if (equal<T>(momentsDiff[1], 0, std::abs(tol)))
582 if (unequalMoment >= 0)
587 T momentsDiff3 = moments[1] - moments[unequalMoment];
591 T s = (this->Ixxyyzz[0] - moments[unequalMoment]) / momentsDiff3;
597 T phi2 = acos(clamp<T>(ClampedSqrt(s), -1, 1));
606 math::Angle phi12(0.5*(Angle2(g2, tol) - Angle2(f2, tol)));
634 Vector2<T> g1a(0, 0.5*momentsDiff3 * sin(2*phi2));
637 math::Angle phi11a(Angle2(g1a, tol) - Angle2(f1, tol));
642 Vector2<T> g1b(0, 0.5*momentsDiff3 * sin(-2*phi2));
645 math::Angle phi11b(Angle2(g1b, tol) - Angle2(f1, tol));
674 if (unequalMoment == 0)
683 +(this->Ixxyyzz[0] - moments[2])
684 *(this->Ixxyyzz[0] + moments[2] - moments[0] - moments[1]))
685 / ((moments[1] - moments[2]) * (moments[2] - moments[0]));
688 if (v < std::abs(tol))
697 w = (this->Ixxyyzz[0] - moments[2] + (moments[2] - moments[1])*v)
698 / ((moments[0] - moments[1]) * v);
703 T phi2 = acos(clamp<T>(ClampedSqrt(v), -1, 1));
705 T phi3 = acos(clamp<T>(ClampedSqrt(w), -1, 1));
710 0.5* (moments[0]-moments[1])*ClampedSqrt(v)*sin(2*phi3),
711 0.5*((moments[0]-moments[1])*w + moments[1]-moments[2])*sin(2*phi2));
713 (moments[0]-moments[1])*(1 + (v-2)*w) + (moments[1]-moments[2])*v,
714 (moments[0]-moments[1])*sin(phi2)*sin(2*phi3));
729 if (f1small && f2small)
740 math::Angle phi12(0.5*(Angle2(g2, tol) - Angle2(f2, tol)));
747 math::Angle phi11(Angle2(g1, tol) - Angle2(f1, tol));
755 math::Angle phi11(Angle2(g1, tol) - Angle2(f1, tol));
758 math::Angle phi12(0.5*(Angle2(g2, tol) - Angle2(f2, tol)));
768 math::Angle phi11a(Angle2(g1a, tol) - Angle2(f1, tol));
769 math::Angle phi12a(0.5*(Angle2(g2a, tol) - Angle2(f2, tol)));
778 signsPhi23.
Set(-1, 1);
785 math::Angle phi11b(Angle2(g1b, tol) - Angle2(f1, tol));
786 math::Angle phi12b(0.5*(Angle2(g2b, tol) - Angle2(f2, tol)));
795 signsPhi23.
Set(1, -1);
802 math::Angle phi11c(Angle2(g1c, tol) - Angle2(f1, tol));
803 math::Angle phi12c(0.5*(Angle2(g2c, tol) - Angle2(f2, tol)));
811 signsPhi23.
Set(-1, -1);
816 phi2 *= signsPhi23[0];
817 phi3 *= signsPhi23[1];
835 const T _tol = 1e-6)
const
837 if (!this->IsPositive(0))
843 Vector3<T> moments = this->PrincipalMoments(_tol);
844 if (!ValidMoments(moments))
855 _size.
X(sqrt(6*(moments.
Y() + moments.
Z() - moments.
X()) / this->mass));
856 _size.
Y(sqrt(6*(moments.
Z() + moments.
X() - moments.
Y()) / this->mass));
857 _size.
Z(sqrt(6*(moments.
X() + moments.
Y() - moments.
Z()) / this->mass));
859 _rot = this->PrincipalAxesOffset(_tol);
881 T volume = _size.
X() * _size.
Y() * _size.
Z();
882 return this->SetFromBox(_mat.
Density() * volume, _size, _rot);
900 this->SetMass(_mass);
901 return this->SetFromBox(_size, _rot);
914 if (this->Mass() <= 0 || _size.
Min() <= 0 ||
925 L(0, 0) = this->mass / 12.0 * (y2 + z2);
926 L(1, 1) = this->mass / 12.0 * (z2 + x2);
927 L(2, 2) = this->mass / 12.0 * (x2 + y2);
948 if (_mat.
Density() <= 0 || _length <= 0 || _radius <= 0 ||
953 T volume =
GZ_PI * _radius * _radius * _length / 3.0;
954 return this->SetFromConeZ(_mat.
Density() * volume,
955 _length, _radius, _rot);
973 if (_mass <= 0 || _length <= 0 || _radius <= 0 ||
978 this->SetMass(_mass);
979 return this->SetFromConeZ(_length, _radius, _rot);
994 if (this->Mass() <= 0 || _length <= 0 || _radius <= 0 ||
1003 L(0, 0) = 3.0 * this->mass * (4.0 * radius2 +
1006 L(2, 2) = 3.0 * this->mass * radius2 / 10.0;
1026 if (_mat.
Density() <= 0 || _length <= 0 || _radius <= 0 ||
1031 T volume =
GZ_PI * _radius * _radius * _length;
1032 return this->SetFromCylinderZ(_mat.
Density() * volume,
1033 _length, _radius, _rot);
1050 if (_mass <= 0 || _length <= 0 || _radius <= 0 ||
1055 this->SetMass(_mass);
1056 return this->SetFromCylinderZ(_length, _radius, _rot);
1071 if (this->Mass() <= 0 || _length <= 0 || _radius <= 0 ||
1080 L(0, 0) = this->mass / 12.0 * (3*radius2 +
std::pow(_length, 2));
1082 L(2, 2) = this->mass / 2.0 * radius2;
1096 if (_mat.
Density() <= 0 || _radius <= 0)
1102 return this->SetFromSphere(_mat.
Density() * volume, _radius);
1112 if (_mass <= 0 || _radius <= 0)
1116 this->SetMass(_mass);
1117 return this->SetFromSphere(_radius);
1127 if (this->Mass() <= 0 || _radius <= 0)
1135 L(0, 0) = 0.4 * this->mass * radius2;
1136 L(1, 1) = 0.4 * this->mass * radius2;
1137 L(2, 2) = 0.4 * this->mass * radius2;
1138 return this->SetMoi(L);
1144 private:
static inline T ClampedSqrt(
const T &_x)
1156 private:
static T Angle2(
const Vector2<T> &_v,
const T _eps = 1e-6)
1158 if (_v.SquaredLength() <
std::pow(_eps, 2))
1160 return atan2(_v[1], _v[0]);
1169 private: Vector3<T> Ixxyyzz;
1174 private: Vector3<T> Ixyxzyz;