[38ba34]: / Tools / AnyMocap / CreateMarkerDriverClass.any

Download this file

428 lines (358 with data), 15.0 kB

#ifndef _ANYMOCAP_CREATE_MARKER_DRIVER_CLASS_ANY_
#define _ANYMOCAP_CREATE_MARKER_DRIVER_CLASS_ANY_
/*
---
group: MoCap
topic: Markers
descr: Creates MoCap markers and links them to the C3D file data.
---

See below for more details

*/

// This template is used by all the MoCap models to link the model to the C3D file data.
// It creates a marker driver on the specified segment on the model and creates the
// necessary drivers to link the marker position to the C3D file data. 
// 
// The class template has special options to add optimizations of the marker positions 
// and to add filters to the marker positions.
// 
// :::{rubric} For example
// :::
// 
// :::{code-block} AnyScript
// CreateMarkerDriver RPSI (
//   MarkerPlacement=Trunk.Segments.PelvisSeg,
//   PlaceMarkerAt=Right.PSIS,
//   OptX=OFF, OptY=OFF, OptZ=ON,
//   UseC3DWeightResiduals=ON
// ) = {
//     sRelOpt = {-0.025,0,0.0};
// };
// :::
// 
#class_template CreateMarkerDriver (
  MarkerName=_NOT_DEFINED_,
  MarkerPlacement,
  WeightX=1, WeightY=1, WeightZ=1,
  OptX=0, OptY=0, OptZ=0,
  ScaleMarkerPosOnOff = 1,
  FilterCutOffFrequency = 0,
  FilterOrder = 2,
  UseC3DWeightResiduals = 0,
  PARAMETER_OPT_STUDY = Main.Studies.ParameterIdentification,
  C3D_OBJECT = Main.ModelSetup.C3DFileData,
  BODY_MODEL_FOLDER = Main.HumanModel.BodyModel,
  PlaceMarkerAt = MoCapMarkerFrameAMMR24,
  USE_BVH_INPUT = 0,
  BVH_OBJECT = Main.ModelSetup.BVHFileData,
  MarkerPlacementBVH = REQUIRED_FOR_BVH_INPUT,
  DRAW_SCALE = 1,
  SKIP_MARKER_EXIST_CHECK = 0,
)
{

//Class template arguments:
//---------------------------
// CreateMarkerDriver#MarkerPlacement
//    (Required) The segment on which the marker is place, relative to the Body model.
// CreateMarkerDriver#PlaceMarkerAt
//    Specifies which coordinate system on the segment the marker is place.
//    This is used when placing markers relative to bony landmarks. (Defaults to `AnatomicalFrame`)
// CreateMarkerDriver#WeightX
//     The weight of soft driver for the marker in X direction
// CreateMarkerDriver#WeightY
//     The weight of soft driver for the marker in Y direction
// CreateMarkerDriver#WeightZ
//     The weight of soft driver for the marker in Z direction
// CreateMarkerDriver#OptX
//     Switch to determine if the markers positions can be optimized in the X direction
// CreateMarkerDriver#OptY
//     Switch to determine if the markers positions can be optimized in the Y direction
// CreateMarkerDriver#OptZ
//     Switch to determine if the markers positions can be optimized in the Z direction
// CreateMarkerDriver#ScaleMarkerPosOnOff
//     Switch to indicate if the marker position should be scaled with the segment
//     which it is attached. If the marker is located relative the segments original
//     this should be ON. If the marker is located relative to a bony landmark it
//     may make sense to turn this off.
// CreateMarkerDriver#FilterCutOffFrequency
//     If set to something different that zero, it will use a special low pass filter
//     on this marker, instead of using the default filter applied by the AnyInputC3D
//     object.
// CreateMarkerDriver#FilterOrder
//     Filter order to use if FilterCutOffFrequency > 0
// CreateMarkerDriver#MarkerName
//    The name of marker in the C3D file. It defaults to the name of the class template.
// CreateMarkerDriver#UseC3DWeightResiduals
//     Switch to specify if the Marker residual value in the C3D file should be
//     used when creating weights for the marker. This is can be used to automatically
//     set the weight of the marker to zero when the marker drops out.
// CreateMarkerDriver#PARAMETER_OPT_STUDY
//     Can be used to specify which optimization study marker design values should be
//     added. It is useful in advanced cases where multiple marker optimization studies
//     are used.
// CreateMarkerDriver#C3D_OBJECT
//     Specifies from which C3D object to link the markers. This only for advanced cases
//     using multiple C3D files for input.
// CreateMarkerDriver#BODY_MODEL_FOLDER
//     Specifies the folder where the body model is located. This is only for advanced
//     cases where the body model is not located in the default location.
// CreateMarkerDriver#USE_BVH_INPUT
//     Switch to specify if the marker should be linked to a BVH file instead of a C3D file.
// CreateMarkerDriver#BVH_OBJECT
//     Specifies from which BVH object to link the markers. This only for advanced cases
//     using multiple BVH files for input.
// CreateMarkerDriver#MarkerPlacementBVH
//     Specifies the segment on which the marker is place, relative to the Body model.
//     This is only used when using BVH input.
// CreateMarkerDriver#DRAW_SCALE
//     Specifies the scale of the marker in the model view. This is only used for
//     visualization purposes.
// CreateMarkerDriver#SKIP_MARKER_EXIST_CHECK
//     Disable the check if the marker exists in the C3D file. This switch must be 
//     enabled if you model is structured so markers are created
//     before the AnyInputC3D file have been defined. (Defaults to 0)

                                
//  #if  MarkerName != _NOT_DEFINED_
//  AnyInt Deprecated_MarkerName_argument = warn(0, strformat("\n"+
//       "------------------------------------------------------------------------------------------------------\n"+
//       "    The "MarkerName" argument to CreateDriver is deprecated. Just give the class template the same   \n"+
//       "    name as the marker. \n"+
//       "-------------------------------------------------------------------------------------------------------\n")
//    );
//  
//  #endif

#if  USE_BVH_INPUT
#if MarkerName != _NOT_DEFINED_
#if MarkerName != __NAME__
  AnyMessage NotSupported_MarkerName_argument = {
    TriggerPreProcess = On;
    Type = MSG_ErrorFatal;
    Message = strformat("\n"+
         "------------------------------------------------------------------------------------------------------\n"+
         "    The "MarkerName" can't be specified for the BVH based models. \n"+
         "    Just remove the MarkerName argument to the class template. \n"+
         "-------------------------------------------------------------------------------------------------------\n");
  };
#endif
#endif
#endif


#if  USE_BVH_INPUT == 0
#if SKIP_MARKER_EXIST_CHECK == 0
AnyMessage TestMarkerExist ={
#if MarkerName == _NOT_DEFINED_
  AnyString MarkerLabel = #__NAME__;
  #else
  AnyString MarkerLabel = #MarkerName;
#endif 
  // Note: if you get a ERROR: " 'PointLabels'  :  Identifier cannot be resolved "
  //       This is because you create a marker earlier than the C3D file objects
  //       is created. For example by creating the marker directly in the "TrialSpecificData.any" file
  //       In that case set the class-template argument 'SKIP_MARKER_EXIST_CHECK=1', as a workaround.
  TriggerPreProcess = not(sum(eqfun(Main.ModelSetup.C3DFileData.PointLabels, MarkerLabel)));
  Type=MSG_Error;
  Message = "Marker: " + strquote(MarkerLabel) + " does not exist in the c3d file";
};
#endif
#endif
                                      
                                      
  #var AnyVar ConstMarkerWeightX = WeightX;  
  #var AnyVar ConstMarkerWeightY = WeightY;
  #var AnyVar ConstMarkerWeightZ = WeightZ;
  
  #if (UseC3DWeightResiduals == 1) & (USE_BVH_INPUT == 0)
    AnyFunSquareWaveThreshold MarkerWeightsFun = 
    {
      #var dT = {C3D_OBJECT.WeightTransitionTime};
      #if MarkerName == _NOT_DEFINED_
      T = C3D_OBJECT.Points.Markers.__NAME__.PosInterpol.T;
      #var Data = C3D_OBJECT.Points.Markers.__NAME__.Residual;
      #else
      T = C3D_OBJECT.Points.Markers.MarkerName.PosInterpol.T;
      #var Data = C3D_OBJECT.Points.Markers.MarkerName.Residual;
      #endif
      OutputValues = 
            {{0, .ConstMarkerWeightX },
             {0, .ConstMarkerWeightY },
             {0, .ConstMarkerWeightZ}};
      #var Threshold = 0.0;
      #var TType = {TransitionStart, TransitionEnd};
    };
  #else
    AnyFunConst MarkerWeightsFun =
    { 
      Value = {.ConstMarkerWeightX , .ConstMarkerWeightY , .ConstMarkerWeightZ };
    };
  #endif
  
  #var AnyObjectPtrVar MarkerWeightsPtr = &MarkerWeightsFun;
    


  // CreateMarkerDriver
  /// Position of the marker within its local reference frame
  #var AnyVec3 sRelOpt; 
  
  #if USE_BVH_INPUT
  // CreateMarkerDriver
  /// Position of the marker on the BVH stick figure model. This is only
  /// used when using BVH input.
  #var AnyVec3 sRelOnBVH = {0,0,0};
  #endif

  #var AnyVec3 sRelOptDelta = {0, 0, 0};
  
  #if OptX ==0 & OptY == 0 & OptZ == 0
        AnyVec3 sRelOptEdit = DesignVar(sRelOptDelta); //make it a design var ! because it will not be otherwise
  #else
        AnyVec3 sRelOptEdit = sRelOptDelta; 
  #endif



  
  
  Main.ModelSetup.Macros={ 
     AnyStringVar Set##__NAME__ = ("classoperation "+  CompleteNameOf(...sRelOptEdit) + " " + strquote("Set Value") +  strformat ("\n")+ "classoperation Main " + strquote("Update Values") + strformat ("\n"));
  };

  
  Main.ModelSetup.ParameterIdentification = {
      AnyDesVar __NAME__##_X = {   Val = ....sRelOptEdit[0];    
        #var Min=-100;
        #var Max=100;      
      };
      
      AnyDesVar __NAME__##_Y = {
        Val = ....sRelOptEdit[1];   
        #var Min=-100;
        #var Max=100;      
      };
      
      AnyDesVar __NAME__##_Z = {
        Val = ....sRelOptEdit[2];   
        #var Min=-100;
        #var Max=100;      
      };
  };
  
 

  AnyFolder &MarkerPlacementSegment = BODY_MODEL_FOLDER.MarkerPlacement;
  MarkerPlacementSegment = {
    AnyRefNode __NAME__##_Marker  ={
      #if ScaleMarkerPosOnOff == 1
        AnyVec3 MarkerOffset = (.GeomScale(..sRelOpt) + ..sRelOptEdit )*.ScalingNode.ARel' ;
        sRel = .PlaceMarkerAt.sRel + MarkerOffset;
        ARel= .ScalingNode.ARel;
      #else
        sRel = .PlaceMarkerAt.sRel + (..sRelOpt + ..sRelOptEdit )*.PlaceMarkerAt.ARel';
        ARel= .PlaceMarkerAt.ARel;
      #endif
      
//      This was an attempt to allow PlaceMarkerAt to be anywhere and not only
//      a RefNode on the segments.
//      AnyFunTransform3DLinRef Transform2SegmentFrame = {
//            AnyVec3 test1 = ..PlaceMarkerAt.sRel;
//            AnyMat33 test2 = ..PlaceMarkerAt.ARel;
//            Ref = &..PlaceMarkerAt;
//      };
//      sRel = Transform2SegmentFrame({0.0,0,0}) + MarkerOffset;
      
      
      AnyFolder Arrows = {  
          // This folder is left for backwards compotability
          #var AnyVar size = DRAW_SCALE*0.05;
      };
      AnyDrawVector Arrow_X =   {
        AnyInt is_optimized = eqfun(OptX,1);
        Vec = {size,0, 0};            
        #include "DrawVector.any"
        #var Text="X";
      };
      AnyDrawVector Arrow_Y =  {
        AnyInt is_optimized = eqfun(OptY,1);
        Vec = {0,size, 0};
        #include "DrawVector.any"
        #var Text="Y";
      };
      AnyDrawVector Arrow_Z =  {
        AnyInt is_optimized = eqfun(OptZ,1);
        Vec = {0,0,size};
        #include "DrawVector.any"
        #var Text="Z";
      };
    }; //MarkerName 
  };// InsertionNode
  
      
      AnyKinDriverMarker Driver = {
        AnyDrawKinMeasure Draw = {
          #if UseC3DWeightResiduals
          #var Visible = On;// iffun(bool(sum(.WeightPos)), On, Off);
          #else
          #var Visible = On;
          #endif
          #var Opacity = iffun(bool(sum(.WeightPos)), 1.0, 0.2)  * bool(sum(.WeightPos));
          #var Label = Off;
          #var Size = DRAW_SCALE*0.01;
          #if USE_BVH_INPUT
          #var Line = DesignVar(Off);
          #else
          #var Line = On;
          #endif
        };
        #if UseC3DWeightResiduals
        AnyDrawKinMeasure DrawDroppedOutMarker = {
          #var Visible = On; //iffun(bool(sum(.WeightPos)), Off, On);
          #var Label = Off;
          #var Size = DRAW_SCALE*0.01;
          #var Opacity = 0.5 * not(bool(sum(.WeightPos)));
          RGB1 = {0.4, 0.4, 0.4};
          RGB3 = {0.4, 0.4, 0.4};
        };
        #endif
        Linear.Ref=0;
        
        
        AnyRefFrame &MarkerRef = BODY_MODEL_FOLDER.MarkerPlacement.__NAME__##_Marker;
        
        #if USE_BVH_INPUT
          AnyFolder &MarkerDataRef = BVH_OBJECT.Markers.__NAME__;
        #else
          #if MarkerName == _NOT_DEFINED_
          AnyFolder &MarkerDataRef = C3D_OBJECT.Points.Markers.__NAME__;
          #else
          AnyFolder &MarkerDataRef = C3D_OBJECT.Points.Markers.MarkerName;
          #endif
        #endif
        
        #if FilterCutOffFrequency > 0
   	  /// A lowpass butterworth filter
   	    AnyFunButterworthFilter LowPassFilter = 
   	    {
   	     	#var FilterForwardBackwardOnOff = On;
   	     	#var AutomaticInitialConditionOnOff = On;
   	     	N = FilterOrder;
              W = {1/(C3D_OBJECT.Header.VideoFrameRate*0.5)*FilterCutOffFrequency };
   	      Type = LowPass;
   	    };
  	  
          /// Interpolation function of the lowpass filtered data
          AnyFunInterpol FilteredPosInterpol = 
          {
            #var Type = Bspline;
            BsplineOrder =4;

            T = .MarkerDataRef.PosInterpol.T;
            Data = .LowPassFilter(.MarkerDataRef.Pos');
          };
          
        #else        
        
        AnyParamFun &InterpolRef = MarkerDataRef.PosInterpol;

        #endif
        
        WeightFun={.MarkerWeightsPtr};
      };

  PARAMETER_OPT_STUDY ={

    #if OptX ==1
      AnyDesVar &__NAME__##_X =  Main.ModelSetup.ParameterIdentification.__NAME__##_X;
    #endif
    
    #if OptY ==1
      AnyDesVar &__NAME__##_Y =  Main.ModelSetup.ParameterIdentification.__NAME__##_Y;
    #endif
    
    #if OptZ ==1
      AnyDesVar &__NAME__##_Z =  Main.ModelSetup.ParameterIdentification.__NAME__##_Z;
    #endif        
    
  };
  
#if USE_BVH_INPUT

   BVH_OBJECT.Markers = {
      AnyVirtualMarkerBVH __NAME__ = {
        RefFramePtr = &MarkerPlacementBVH.__NAME__;
      };
   };

  
  //AnyFolder &MarkerInsertionNodeBVH = MarkerPlacementBVH;  
  MarkerPlacementBVH = 
  {
    AnyRefNode __NAME__ = {
      //sRel = ..sRelOnBVH;
      #if MarkerName == _NOT_DEFINED_
      sRel = Main.ModelSetup.MocapDrivers.__NAME__.sRelOnBVH ;
      #else
      sRel = Main.ModelSetup.MocapDrivers.MarkerName.sRelOnBVH ;
      #endif
      AnyDrawNode drw_node = 
      {
        #var RGB = {0, 1, 0};
        #var ScaleXYZ = 0.015*{1, 1, 1};     
        Visible = BVH_OBJECT.ModelDrawOnOff;
      };
    };
  };//
  
  //Main.ModelSetup.BVHFileData.Markers.MarkerName.

  

#endif
  
  
  
  
}; // End of InsertSegmentClass




#endif