[770c98]: / Tools / ModelUtilities / SegmentCoM / CreateCoMRefNode.any

Download this file

93 lines (85 with data), 4.2 kB

/*
---
group: Utilities
topic: Center of mass
descr: |
  Class template to create a reference node at the center of mass of a segment
  with its axis aligned with the principal axes of inertia. 
---

To use the class template import the file:
#include "<ANYBODY_PATH_MODELUTILS>/SegmentCoM/CreateCoMRefNode.any"

*/


// Creates a reference node at the center of mass of the segment. The orientation of the reference
// node is determined from the principal axes of inertia, which are determined from the Jmatrix of
// the segment. This class template must be used inside the scope of AnySeg.
//
// This class template calculates the Jmatrix about the center of mass and its eigenvectors and eigenvalues   
// to determine the principal axes of inertia. In cases with symmetric shape, for example a sphere, 
// cylinder, etc., some of the eigenvalue terms are duplicated. Therefore, the principal axes may not 
// be uniquely defined in these cases.
//
// In the example below a reference node is created inside a segment.
//
// :::{rubric} Example
// :::
//
// :::{code-block} AnyScriptDoc
// AnySeg MySegment = {
//   CreateCoMRefNode CoMNode () = {
//     viewRefFrame.Visible = On;
//   };
// };
//:::
//
#class_template CreateCoMRefNode (__CLASS__ = AnyRefNode,
  SUPPRESS_SYMMETRY_NOTICE = "Off"){
  // Arguments
  // -----------
  //  CreateCoMRefNode#SUPPRESS_SYMMETRY_NOTICE
  //   Switch to suppress the notice detecting duplicate eigenvalues of the Jmatrix about the center of mass, 
  //   indicating that two or three axes of the center of mass node may not be uniquely defined.

  /// Jmatrix about the center of mass
  AnyMat33 JMatrixCoM = .Jmatrix + .Mass*skewmat3d(.sCoM)*skewmat3d(.sCoM);
  /// Matrix with eigenvectors and eigenvalues from the Jmatrix about center of mass
  AnyMatrix JMatrixEV = LAPACK_syevd(JMatrixCoM,"V","V");
  /// Eigenvectors of the Jmatrix about the center of mass
  AnyFloat EigenVectors = {JMatrixEV[0],JMatrixEV[1],JMatrixEV[2]};
  /// Eigenvalues of the Jmatrix about the center of mass
  AnyFloat EigenValues = JMatrixEV[3];
  
  #if SUPPRESS_SYMMETRY_NOTICE == "Off"
  /// Check if first and second eigenvalues are same
  AnyInt test0_1 = iffun(ltfun(abs(EigenValues[0]-EigenValues[1]),SymmetryTolerance),1,0);
  /// Check if second and third eigenvalues are same
  AnyInt test1_2 = iffun(ltfun(abs(EigenValues[1]-EigenValues[2]),SymmetryTolerance),1,0);
  /// Check if first and third eigenvalues are same
  AnyInt test0_2 = iffun(ltfun(abs(EigenValues[0]-EigenValues[2]),SymmetryTolerance),1,0);
  /// Sum of the three tests.
  AnyInt sumcheck = test0_1+test1_2+test0_2;
  /// Notice when 2 Eigenvalues are same
  AnyInt AxisNotice_2 = notice(sumcheck-1, strformat("2 of 3 eigenvalues are the same. 2 axes of the Center of Mass node may not be uniquely defined due to symmetric moment of inertia about 2 axes.\n\t\t\tYou can suppress this notice by setting SUPPRESS_SYMMETRY_NOTICE = " + strquote("On")));
  /// Notice when 3 Eigenvalues are same
  AnyInt AxisNotice_3 = notice(sumcheck-3, strformat("3 of 3 eigenvalues are the same. The axes of the Center of Mass node may not be uniquely defined due to symmetric moment of inertia about 3 axes. \n\t\t\tYou can suppress this notice by setting SUPPRESS_SYMMETRY_NOTICE = " + strquote("On")));
  #endif
  
  //CreateCoMRefNode
  /// Tolerance for checking duplicate eigenvalues
  #var AnyFloat SymmetryTolerance = 1e-10;
  
  // sRel
  /// Relative position of the reference node in the segmental frame. This defaults to
  /// segment sCoM.
  #var sRel = .sCoM;
  // ARel 
  /// Relative orientation of the reference node in the segmental frame. This defaults to
  /// be aligned with the principal axes of inertia.
  #var ARel = {EigenVectors[0],EigenVectors[1],cross(EigenVectors[0],EigenVectors[1])}';
  viewRefFrame = {
    // viewRefFrame.Visible
    /// Switch to view the reference node.
    #var Visible = Off;
    // viewRefFrame.ScaleXYZ
    /// Size of the drawing of the reference node.
    #var ScaleXYZ = 0.5*{1,1,1};
    // viewRefFrame.RGB
    /// Color of the drawing of the reference node.
    #var RGB = {0.8,0.2,0.2};
  };
};