1 #define BIORBD_API_EXPORTS
2 #include "Muscles/WrappingCylinder.h"
4 #include "Utils/String.h"
5 #include "Utils/RotoTrans.h"
6 #include "RigidBody/Joints.h"
10 m_dia(std::make_shared<biorbd::utils::Scalar>(0)),
11 m_length(std::make_shared<biorbd::utils::Scalar>(0)),
12 m_isCylinderPositiveSign(std::make_shared<bool>(true)),
13 m_RTtoParent(std::make_shared<biorbd::utils::RotoTrans>()),
14 m_p1Wrap(std::make_shared<biorbd::utils::Vector3d>()),
15 m_p2Wrap(std::make_shared<biorbd::utils::Vector3d>()),
16 m_lengthAroundWrap(std::make_shared<biorbd::utils::Scalar>(0))
18 *
m_typeOfNode = biorbd::utils::NODE_TYPE::WRAPPING_CYLINDER;
23 const biorbd::utils::Scalar& diameter,
24 const biorbd::utils::Scalar& length,
25 bool isCylinderPositiveSign) :
27 m_dia(std::make_shared<biorbd::utils::Scalar>(diameter)),
28 m_length(std::make_shared<biorbd::utils::Scalar>(length)),
29 m_isCylinderPositiveSign(std::make_shared<bool>(isCylinderPositiveSign)),
30 m_RTtoParent(std::make_shared<biorbd::utils::RotoTrans>(rt)),
31 m_p1Wrap(std::make_shared<biorbd::utils::Vector3d>()),
32 m_p2Wrap(std::make_shared<biorbd::utils::Vector3d>()),
33 m_lengthAroundWrap(std::make_shared<biorbd::utils::Scalar>(0))
35 *
m_typeOfNode = biorbd::utils::NODE_TYPE::WRAPPING_CYLINDER;
40 const biorbd::utils::Scalar& diameter,
41 const biorbd::utils::Scalar& length,
42 bool isCylinderPositiveSign,
46 m_dia(std::make_shared<biorbd::utils::Scalar>(diameter)),
47 m_length(std::make_shared<biorbd::utils::Scalar>(length)),
48 m_isCylinderPositiveSign(std::make_shared<bool>(isCylinderPositiveSign)),
49 m_RTtoParent(std::make_shared<biorbd::utils::RotoTrans>(rt)),
50 m_p1Wrap(std::make_shared<biorbd::utils::Vector3d>()),
51 m_p2Wrap(std::make_shared<biorbd::utils::Vector3d>()),
52 m_lengthAroundWrap(std::make_shared<biorbd::utils::Scalar>(0))
54 *
m_typeOfNode = biorbd::utils::NODE_TYPE::WRAPPING_CYLINDER;
67 *m_dia = *other.
m_dia;
71 *m_p1Wrap = other.
m_p1Wrap->DeepCopy();
72 *m_p2Wrap = other.
m_p2Wrap->DeepCopy();
82 biorbd::utils::Scalar *length)
94 findTangentToCircle(*p_glob.
m_p1, p1_tan);
95 findTangentToCircle(*p_glob.
m_p2, p2_tan);
99 findVerticalNode(p_glob, tanPoints);
103 if (length !=
nullptr)
104 *length = computeLength(tanPoints);
107 tanPoints.
m_p1->applyRT(rt);
108 tanPoints.
m_p2->applyRT(rt);
111 p1 = *tanPoints.
m_p1;
112 p2 = *tanPoints.
m_p2;
115 m_p1Wrap = tanPoints.
m_p1;
116 m_p2Wrap = tanPoints.
m_p2;
117 if (length !=
nullptr)
118 *m_lengthAroundWrap = *length;
128 biorbd::utils::Scalar *length) {
131 wrapPoints(RT(model,Q), p1_bone, p2_bone, p1, p2, length);
137 biorbd::utils::Scalar *length){
140 if (length !=
nullptr)
141 *length = *m_lengthAroundWrap;
154 *m_RT = model.
globalJCS(*m_parentName) * *m_RTtoParent;
159 const biorbd::utils::Scalar& val)
175 const biorbd::utils::Scalar& val)
188 biorbd::utils::Scalar p_dot = p.block(0,0,2,1).dot(p.block(0,0,2,1));
190 const RigidBodyDynamics::Math::Vector2d& Q0(radius()*radius()/p_dot*p.block(0,0,2,1));
191 RigidBodyDynamics::Math::Matrix2d tp(RigidBodyDynamics::Math::Matrix2d::Zero());
195 const RigidBodyDynamics::Math::Vector2d& T(
196 radius()/p_dot*std::sqrt(p_dot-radius()*radius()) * tp * p.block(0,0,2,1));
200 m.
m_p1->block(0,0,2,1) = Q0 + T;
201 m.
m_p2->block(0,0,2,1) = Q0 - T;
204 selectTangents(m, p_tan);
210 if (m_isCylinderPositiveSign){
211 #ifdef BIORBD_USE_CASADI_MATH
212 p_tan = casadi::MX::if_else(
213 casadi::MX::ge((*p1.
m_p2)(0), (*p1.
m_p1)(0)),
222 #ifdef BIORBD_USE_CASADI_MATH
223 p_tan = casadi::MX::if_else(
224 casadi::MX::lt((*p1.
m_p2)(0), (*p1.
m_p1)(0)),
238 #ifdef BIORBD_USE_CASADI_MATH
239 if (checkIfWraps(pointsInGlobal, pointsToWrap).is_zero()){
241 if (!checkIfWraps(pointsInGlobal, pointsToWrap)){
243 for (
unsigned int i=0; i<3; ++i){
244 (*pointsToWrap.
m_p1)(i) =
static_cast<biorbd::utils::Scalar
>(
static_cast<double>(NAN));
245 (*pointsToWrap.
m_p2)(i) =
static_cast<biorbd::utils::Scalar
>(
static_cast<double>(NAN));
251 (*pointsToWrap.
m_p1)(2) = 0;
252 (*pointsToWrap.
m_p2)(2) = 0;
287 (*pointsToWrap.
m_p1)(2) = biorbd::utils::Scalar(wrapA(0)-globB(0)) /
288 biorbd::utils::Scalar(globA(0)-globB(0)) *
289 ((*pointsInGlobal.
m_p1)(2)-(*pointsInGlobal.
m_p2)(2)) + (*pointsInGlobal.
m_p2)(2);
290 (*pointsToWrap.
m_p2)(2) = biorbd::utils::Scalar(wrapB(0)-globB(0)) /
291 biorbd::utils::Scalar(globA(0)-globB(0)) *
292 ((*pointsInGlobal.
m_p1)(2)-(*pointsInGlobal.
m_p2)(2)) + (*pointsInGlobal.
m_p2)(2);
296 #ifdef BIORBD_USE_CASADI_MATH
300 biorbd::utils::Scalar isWrap = 1;
303 return casadi::MX::if_else(
304 (casadi::MX::lt((*pointsToWrap.
m_p1)(0), (*pointsToWrap.
m_p2)(0)) &&
305 casadi::MX::gt((*pointsInGlobal.
m_p1)(0), (*pointsInGlobal.
m_p2)(0))) ||
306 (casadi::MX::gt((*pointsToWrap.
m_p1)(0), (*pointsToWrap.
m_p2)(0)) &&
307 casadi::MX::lt((*pointsInGlobal.
m_p1)(0), (*pointsInGlobal.
m_p2)(0))),
320 if (m_isCylinderPositiveSign){
321 if ((*pointsInGlobal.
m_p1)(0) > radius() && (*pointsInGlobal.
m_p2)(0) > radius())
326 if ((*pointsInGlobal.
m_p1)(0) < -radius() && (*pointsInGlobal.
m_p2)(0) < -radius())
333 if ( ( (*pointsInGlobal.
m_p1)(1) > 0 && (*pointsInGlobal.
m_p2)(1) > 0) || ( (*pointsInGlobal.
m_p1)(1) < 0 && (*pointsInGlobal.
m_p2)(1) < 0) )
338 if ( fabs( (*pointsInGlobal.
m_p1)(1)) < radius() || fabs( (*pointsInGlobal.
m_p2)(1)) < radius() )
343 if ( ( (*pointsToWrap.
m_p1)(0) < (*pointsToWrap.
m_p2)(0) && (*pointsInGlobal.
m_p1)(0) > (*pointsInGlobal.
m_p2)(0)) ||
344 ( (*pointsToWrap.
m_p1)(0) > (*pointsToWrap.
m_p2)(0) && (*pointsInGlobal.
m_p1)(0) < (*pointsInGlobal.
m_p2)(0)) )
354 biorbd::utils::Scalar arc = std::acos( ( (*p.
m_p1)(0) * (*p.
m_p2)(0) + (*p.
m_p1)(1) * (*p.
m_p2)(1))
360 return std::sqrt(arc*arc + ( (*p.
m_p1)(2) - (*p.
m_p2)(2)) * ( (*p.
m_p1)(2) - (*p.
m_p2)(2)) );