iMSTK
Interactive Medical Simulation Toolkit
RbdPointToArcConstraint.h
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #pragma once
8 
9 #include "imstkRbdConstraint.h"
10 
11 using namespace imstk;
12 
20 {
21 public:
34  std::shared_ptr<RigidBody> obj,
35  const Vec3d arcCenter, const double beginRadian, const double endRadian,
36  const double arcCircleRadius, const Mat3d arcBasis,
37  const Vec3d fixedPoint,
38  const double beta = 0.05) : RbdConstraint(obj, nullptr, Side::A),
39  m_arcCenter(arcCenter), m_beginRadian(beginRadian), m_endRadian(endRadian),
40  m_arcCircleRadius(arcCircleRadius), m_arcBasis(arcBasis),
41  m_fixedPoint(fixedPoint),
42  m_beta(beta)
43  {
44  // Check orthonormal basis
45  }
46 
47  ~RbdPointToArcConstraint() override = default;
48 
49  IMSTK_TYPE_NAME(RbdPointToArcConstraint)
50 
51 public:
52  void compute(double dt) override
53  {
54  // Jacobian of contact (defines linear and angular constraint axes)
55  J = Eigen::Matrix<double, 3, 4>::Zero();
56  if ((m_side == Side::AB || m_side == Side::A) && !m_obj1->m_isStatic)
57  {
58  // Compute the direction and closest point to the arc from the fixedPoint
59  const Vec3d circleDiff = m_fixedPoint - m_arcCenter;
60  const Vec3d dir = circleDiff.normalized();
61 
62  // m_arcBasis Should be orthonormal, this should project onto the axes
63  const Mat3d invArcBasis = m_arcBasis.transpose();
64  const Vec3d p = invArcBasis * circleDiff;
65  const double rad = atan2(-p[2], -p[0]) + PI;
66  // Clamp to range (if closest point on circle is outside on range we want the end)
67  const double clampedRad = std::min(std::max(rad, m_beginRadian), m_endRadian);
68  // Finally compute the closest point to the arc using the new radian
69  const Vec3d closestPt = (cos(clampedRad) * m_arcBasis.col(0) +
70  sin(clampedRad) * m_arcBasis.col(2)) * m_arcCircleRadius +
71  m_arcCenter;
72 
73  Vec3d diff = m_fixedPoint - closestPt;
74  const Vec3d r = closestPt - m_obj1->getPosition();
75  const Vec3d c = r.cross(diff);
76 
77  vu = diff.norm() * m_beta / dt;
78  diff = diff.normalized();
79  J(0, 0) = diff[0]; J(0, 1) = c[0];
80  J(1, 0) = diff[1]; J(1, 1) = c[1];
81  J(2, 0) = diff[2]; J(2, 1) = c[2];
82  }
83  }
84 
85 private:
86  Vec3d m_arcCenter = Vec3d::Zero();
87  Mat3d m_arcBasis = Mat3d::Zero(); // Should be orthonormal
88  double m_arcCircleRadius = 0.0;
89  double m_beginRadian = 0.0;
90  double m_endRadian = 0.0;
91 
92  Vec3d m_fixedPoint = Vec3d::Zero();
93 
94  double m_beta = 0.05;
95 };
Abstract class for rigid body constraints. A RbdConstraint should mainly provide a constraint jacobia...
void compute(double dt) override
Compute constraint jacobian.
Compound Geometry.
RbdPointToArcConstraint(std::shared_ptr< RigidBody > obj, const Vec3d arcCenter, const double beginRadian, const double endRadian, const double arcCircleRadius, const Mat3d arcBasis, const Vec3d fixedPoint, const double beta=0.05)
Constrains an rigid body arc geometry to a point by computing the linear force and angular torque to ...