Switch to side-by-side view

--- a
+++ b/Tools/AnyMocap/CreateMarkerDriverClass.any
@@ -0,0 +1,427 @@
+#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
+
+