--- 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 + +