GMFoot MoCap and RBF Scaling

Hi Pavel, sorry its taken so long to get back to you, I am currently balancing an MSc and PhD simultaneously.

I’ve changed a few things so that the ScaleFunction is a combination of all the transformations/morphs like so:

RBFLandmarks.any…

AnyFunTransform3DLin ScaleFunction = {
  PreTransforms = {
  &.ScaleCalcaneus,
  &.ScaleTalus,
  &.ScaleNavicular,
  &.ScaleInt_Med_Lat_Cunneiforms,
  &.ScaleCuboid,
  &.ScaleMetatarsal1,
  &.ScaleMetatarsal2,
  &.ScaleMetatarsal345,
  &.ScaleDistalPhalange1,
  &.ScaleProximalPhalange1,
  &.ScaleDist_Mid_Prox_Phalanges2345 
  };
  ScaleMat = {{1,0,0},{0,1,0},{0,0,1}};
  Offset = {0,0,0};
};

With each morph constructed like so:

//Start of Calcaneus Scaling

AnyFunTransform3DLin ScaleCalcaneus = {
  PreTransforms = {&.RBFCalcaneus,&.RevCalcaneus};
  ScaleMat = {{1,0,0},{0,1,0},{0,0,1}};
  Offset = {0,0,0};
};

AnyFunTransform3DLin2 FwCalcaneus = {
  Points0 = .CalcaneusMorphingLandmarks.SourceCalcaneusPointCloud; //Original MorphingPointCloud matrix.      
  Points1 = .CalcaneusMorphingLandmarks.TargetCalcaneusPointCloud; //Target MorphingPointCloud matrix.        
  Mode  = VTK_LANDMARK_AFFINE;
};

AnyFunTransform3DRBF RBFCalcaneus = {
  PreTransforms = {&.FwCalcaneus};
  RBFDef.Type = RBF_ThinPlate;
  Points0 = .CalcaneusMorphingLandmarks.SourceCalcaneusPointCloud; //Original MorphingPointCloud matrix.      
  Points1 = .CalcaneusMorphingLandmarks.TargetCalcaneusPointCloud; //Target MorphingPointCloud matrix.        
  BoundingBoxOnOff = On;
  BoundingBox.ScaleXYZ = {1,1,1}*2;
  BoundingBox.DivisionFactorXYZ = {1, 1, 1}*2;
};

AnyFunTransform3DLin2 RevCalcaneus = {
  Points1 = .CalcaneusMorphingLandmarks.SourceCalcaneusPointCloud;       
  Points0 = .CalcaneusMorphingLandmarks.TargetCalcaneusPointCloud;         
  Mode = VTK_LANDMARK_RIGIDBODY;
};

//STL Transformation
     AnyFunTransform3DSTL STLCalcaneus ={       
        PreTransforms = {&.RBFCalcaneus};
        RBFDef.Type = RBF_ThinPlate;
        AnyFixedRefFrame Input = {
          AnySurfSTL Source = {
            FileName = "CalcaneusGM.stl";
            ScaleXYZ = {1, 1, 1};
            //AnyFunTransform3D &pre = ....TSeg2ScaleFrame;
          };
          AnySurfSTL Target = {
            FileName = "MBFOOT5_calcaneus.stl";
            ScaleXYZ = {1, 1, 1}*0.001; 
          };
        };
        SurfaceObjects0 = {&Input.Source};
        SurfaceObjects1 = {&Input.Target};
        //Max NumPoints = Number of Source Surface Verticies
        NumPoints = 5000;
        BoundingBoxOnOff = On;
        BoundingBox.ScaleXYZ = {1,1,1}*2;
        BoundingBox.DivisionFactorXYZ = {1, 1, 1}*2;
        //UseClosestPointMatchingOnOff= On;
      };

AnyFolder CalcaneusMorphingLandmarks= {
  
  AnyFolder &SegRef = .....BodyModel.Right.Leg.Seg;
//  AnyFolder &SegRef = .....BodyModel.Right.Leg.Seg.Calcaneus;
  
  //Matrix of the point cloud in foot ref frame.
 AnyMatrix SourceCalcaneusPointCloud = 
    FunCEx("CalcaneusGM_picked_points_43.pp", Main.FootPrintFolderPath +"/Scaling");
  
  AnyInt Size = 43;
  AnyFunEx FunCEx = 
  {
    AnyMatrix Return = {iarr(1,.Size)*0,iarr(1,.Size)*0,iarr(1,.Size)*0}';
    AnyFunExMonoPy ReadMLFile =
    {
      ModuleFile = "ReadMeshlabIn.py";
      ArgList = 
      {
        AnyStringVar filename = "";
        AnyStringVar path = "";
      };
    };
  };
  AnyMatrix TargetCalcaneusPointCloudMillimeter =  
  
  FunCEx("MBFOOT5_calcaneus_picked_points_43.pp", Main.FootPrintFolderPath +"/Scaling");
  
  AnyMatrix TargetCalcaneusPointCloud =  TargetCalcaneusPointCloudMillimeter*0.001;  
  
  
};//CalcaneusMorphingLandmarks

//End of Calcaneus Scaling

//Start of Talus Scaling

AnyFunTransform3DLin ScaleTalus = {
  PreTransforms = {&.RBFTalus,&.RevTalus};
  ScaleMat = {{1,0,0},{0,1,0},{0,0,1}};
  Offset = {0,0,0};
};

AnyFunTransform3DLin2 FwTalus = {
  Points0 = .TalusMorphingLandmarks.SourceTalusPointCloud; //Original MorphingPointCloud matrix.      
  Points1 = .TalusMorphingLandmarks.TargetTalusPointCloud; //Target MorphingPointCloud matrix.        
  Mode  = VTK_LANDMARK_AFFINE;
};

AnyFunTransform3DRBF RBFTalus = {
  PreTransforms = {&.FwTalus};
  RBFDef.Type = RBF_ThinPlate;
  Points0 = .TalusMorphingLandmarks.SourceTalusPointCloud; //Original MorphingPointCloud matrix.      
  Points1 = .TalusMorphingLandmarks.TargetTalusPointCloud; //Target MorphingPointCloud matrix.        
  BoundingBoxOnOff = On;
  BoundingBox.ScaleXYZ = {1,1,1}*2;
  BoundingBox.DivisionFactorXYZ = {1, 1, 1}*2;
};

AnyFunTransform3DLin2 RevTalus = {
  Points1 = .TalusMorphingLandmarks.SourceTalusPointCloud;       
  Points0 = .TalusMorphingLandmarks.TargetTalusPointCloud;         
  Mode = VTK_LANDMARK_RIGIDBODY;
};

//STL Transformation
     AnyFunTransform3DSTL STLTalus ={       
        PreTransforms = {&.RBFTalus};
        RBFDef.Type = RBF_ThinPlate;
        AnyFixedRefFrame Input = {
          AnySurfSTL Source = {
            FileName = "TalusGM.stl";
            ScaleXYZ = {1, 1, 1};
            //AnyFunTransform3D &pre = ....TSeg2ScaleFrame;
          };
          AnySurfSTL Target = {
            FileName = "MBFOOT5_talus.stl";
            ScaleXYZ = {1, 1, 1}*0.001; 
          };
        };
        SurfaceObjects0 = {&Input.Source};
        SurfaceObjects1 = {&Input.Target};
        //Max NumPoints = Number of Source Surface Verticies
        NumPoints = 5000;
        BoundingBoxOnOff = On;
        BoundingBox.ScaleXYZ = {1,1,1}*2;
        BoundingBox.DivisionFactorXYZ = {1, 1, 1}*2;
        //UseClosestPointMatchingOnOff= On;
      };

AnyFolder TalusMorphingLandmarks= {
  
  AnyFolder &SegRef = .....BodyModel.Right.Leg.Seg;
  
  
  //Matrix of the point cloud in foot ref frame.
 AnyMatrix SourceTalusPointCloud = 
    FunCEx("TalusGM_picked_points_31.pp", Main.FootPrintFolderPath +"/Scaling");
  
  AnyInt Size = 31;
  AnyFunEx FunCEx = 
  {
    AnyMatrix Return = {iarr(1,.Size)*0,iarr(1,.Size)*0,iarr(1,.Size)*0}';
    AnyFunExMonoPy ReadMLFile =
    {
      ModuleFile = "ReadMeshlabIn.py";
      ArgList = 
      {
        AnyStringVar filename = "";
        AnyStringVar path = "";
      };
    };
  };
  AnyMatrix TargetTalusPointCloudMillimeter =  
  
  FunCEx("MBFOOT5_talus_picked_points_31.pp", Main.FootPrintFolderPath +"/Scaling");
  
  AnyMatrix TargetTalusPointCloud =  TargetTalusPointCloudMillimeter*0.001; 
  
  
};//TalusMorphingLandmarks

//End of Talus Scaling

When I combine more than one …MorphingLandmarks (like the calcaneus and talus example above) the scaling behaves poorly and when I combine all the …MorphingLandmarks, the foot disappears, but the model loads dumping out:


Evaluating model...
Number of requested landmarks (5000) exceeds number of source surface vertices (2525). Using the latter one.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.Talus.TaloNavicularJoint: Non-orthogonal axes were adjusted.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.Navicular.TaloNavicularJoint: Non-orthogonal axes were adjusted.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.Navicular.CenterNode: Non-orthogonal axes were adjusted.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.Navicular.MedCuneiNaviJoint: Non-orthogonal axes were adjusted.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.Navicular.LatCuneiNaviJoint: Non-orthogonal axes were adjusted.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.MedialCuneiform.CuneiNaviJoint: Non-orthogonal axes were adjusted.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.MedialCuneiform.CenterNode: Non-orthogonal axes were adjusted.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.LateralCuneiform.CuneiNaviJoint: Non-orthogonal axes were adjusted.
WARNING for Main.Studies.KinematicStudyForParameterIdentification.HumanModel.BodyModel.Right.Leg.Seg.LateralCuneiform.CenterNode: Non-orthogonal axes were adjusted.
Number of requested landmarks (5000) exceeds number of source surface vertices (2274). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (1181). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (889). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (444). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (415). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (920). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (313). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (1205). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (318). Using the latter one.
Number of requested landmarks (5000) exceeds number of source surface vertices (286). Using the latter one.
Loaded successfully.
Elapsed Time : 150.939000

Any ideas on a solution to this would be very warmly welcomed.
Kind Regards,
Zach

Hi Zach,

There is something definitely wrong with the ScaleFunction. The PreTransforms is a pipeline of transformations, rather than a combined law. It means that you apply them sequentially and the results will be strange in your case. When I said a combined scaling function - i meant that you need to construct a combined transformation, where all surfaces/landmarks are inputs.
Just think of the foot as a single object, where landmarks are selected per each bone. The combined transformation should look something like that (just an idea, not an actual code):


// source landmarks
AnyMatrix SCalcaneusLandmarks = {{...},..{...}};
AnyMatrix STalusLandmarks = {{...},..{...}};
...

AnyFunTransform3DLin2 AffineTransform = {
 Points0 = arrcat(.SCalcaneusLanmarks, STalusLandmarks, ...);
 Points1 = arrcat(.TCalcaneusLanmarks, TTalusLandmarks, ...);
 Mode = VTK_LANDMARK_AFFINE;
};

etc.

Please try.

Kind regards,
Pavel

Hi Pavel,
So i’ve combined the picked point matrix form each individual bone into one picked point file - so combing each bone matrix, like the example you gave. Plus i’ve including an STL transformation. I also tried doing the bones separately with some success (see script below).

Interestingly though, when I export the surfaces of the Calc and Talus and compare these from the two methods i’ve tried they are different despite having the same landmark matrix, same STL file and the same functions applied to them?

Individual bone Method looks like:

MainFile.any


...
Main = {
  
 
 //** ModelSetup will let you edit the general Marker setup and the Foot Folder location** 
  #include "Model/ModelSetup.any" 
 //** Trials will let you edit names and Start-End times of the trials** 
  #include "Model/TrialSpecificData3.any"
  
  #define CUSTOM_SCALING_Foot
  #define CUSTOM_SCALING_Talus
  #define CUSTOM_SCALING_Calcaneus
 
  
  #if MotionAndParameterOptimizationModel
  #include "Model/Kinematics.any"
  #endif 
  
  #if InverseDynamicModel
  #include "Model/InverseDynamics.any"
  #endif

HumanModel.any

 
...
  //#include "<ANYBODY_PATH_BODY>Scaling\ScalingUniform.any"
  //#include "<ANYBODY_PATH_BODY>Scaling\ScalingLengthMass.any" 
  //#include "<ANYBODY_PATH_BODY>Scaling\FootScaling\ScalingLengthMassFat.any" 
  //#include "<ANYBODY_PATH_BODY>\Scaling\FootScaling/ScalingLengthMassFatRBF.any"
     #include "ScalingLengthMassFatRBF.any"
  
 
  Scaling = {
    //This is the file which set the segments lenghts
    #include "AnyManRBF.any" 
    
        GeometricalScaling.Right.Foot = {#include "../Scaling/RBFLandmarks.any"};
        GeometricalScaling.Right.Talus = {#include "../Scaling/TalusRBF.any"};
	GeometricalScaling.Right.Calcaneus = {#include "../Scaling/CalcaneusRBF.any"};


    //MorphingLandmarks = {AnyFolder &SegRef = Main.Studies.HumanModel.BodyModel.Right.Leg.Seg;};
    //#include "<ANYBODY_PATH_BODY>Scaling\FootScaling\MorphingLandmarks.any"
  };
  #include "FootType.any"
};

ScalingLengthMassFatRBF.any


...

AnyFolder Foot  = {
          AnyVar LengthScale = ...AnthroSegmentLengths.Right.FootLength / ...StandardParameters.Right.Foot.Length; 
          AnyVar WidthScale = ...AnthroSegmentLengths.Right.FootWidth / ...StandardParameters.Right.Foot.Width;
          AnyVar HeightScale = ...AnthroSegmentLengths.Right.FootHeight / ...StandardParameters.Right.Foot.Height;
          AnyVar ms = ...MassScaling.Right.Foot.MassScale;
          AnyVar ls = LengthScale;
          AnyVar ws = WidthScale;
          AnyVar hs = HeightScale; 
          
	  #ifndef CUSTOM_SCALING_Foot
          AnyFunTransform3DLin ScaleFunction = {
           //ScaleMat = {{(.ms/.ls)^0.5, 0, 0},{0, .ls, 0},{0, 0, .ws}};
           ScaleMat = {{.hs, 0, 0},{0, .ls, 0},{0, 0, .ws}};
           Offset = {0, 0, 0};
          };
             
          #else
          #endif
};
//        AnyFolder &Talus = Foot;
        AnyFolder Talus = {
	  
	  #ifndef CUSTOM_SCALING_Talus
          AnyFunTransform3DLin ScaleFunction = {
           ScaleMat = {{(.ms/.ls)^0.5, 0, 0},{0, .ls, 0},{0, 0, .ws}};
          // ScaleMat = {{.hs, 0, 0},{0, .ls, 0},{0, 0, .ws}};
          // ScaleMat = {{1,0,0},{0,1,0},{0,0,1}};
            Offset = {0, 0, 0};
          };
		  
		  #else
          #endif
};

 //     AnyFolder &Calcaneus = Foot;
         AnyFolder Calcaneus = {
          
		#ifndef CUSTOM_SCALING_Calcaneus
          AnyFunTransform3DLin ScaleFunction = {
           //ScaleMat = {{(.ms/.ls)^0.5, 0, 0},{0, .ls, 0},{0, 0, .ws}};
           //ScaleMat = {{.hs, 0, 0},{0, .ls, 0},{0, 0, .ws}};
           ScaleMat = {{1,0,0},{0,1,0},{0,0,1}};
            Offset = {0, 0, 0};
          };
		  
		  #else
          #endif
}; 

CalcaneusRBF.any

AnyFunTransform3DLin ScaleFunction = {
  PreTransforms = {&.STLCalcaneus,&.RevCalcaneus};
  ScaleMat = {{1,0,0},{0,1,0},{0,0,1}};
  Offset = {0,0,0};
};

AnyFunTransform3DLin2 FwCalcaneus = {
  Points0 = .CalcaneusMorphingLandmarks.SourceCalcaneusPointCloud; //Original MorphingPointCloud matrix.      
  Points1 = .CalcaneusMorphingLandmarks.TargetCalcaneusPointCloud; //Target MorphingPointCloud matrix.        
  Mode  = VTK_LANDMARK_AFFINE;
};

AnyFunTransform3DRBF RBFCalcaneus = {
  PreTransforms = {&.FwCalcaneus};
  RBFDef.Type = RBF_Triharmonic;
  Points0 = .CalcaneusMorphingLandmarks.SourceCalcaneusPointCloud; //Original MorphingPointCloud matrix.      
  Points1 = .CalcaneusMorphingLandmarks.TargetCalcaneusPointCloud; //Target MorphingPointCloud matrix.        
  BoundingBoxOnOff = On;
  BoundingBox.ScaleXYZ = {1,1,1}*2;
  BoundingBox.DivisionFactorXYZ = {1, 1, 1}*2;
};

AnyFunTransform3DLin2 RevCalcaneus = {
  Points1 = .CalcaneusMorphingLandmarks.SourceCalcaneusPointCloud;       
  Points0 = .CalcaneusMorphingLandmarks.TargetCalcaneusPointCloud;         
  Mode = VTK_LANDMARK_RIGIDBODY;
};

//STL Transformation
     AnyFunTransform3DSTL STLCalcaneus ={       
        PreTransforms = {&.RBFCalcaneus};
        RBFDef.Type = RBF_ThinPlate;
        AnyFixedRefFrame Input = {
          AnySurfSTL Source = {
            FileName = "CalcaneusGM.stl";
            ScaleXYZ = {1, 1, 1};
            //AnyFunTransform3D &pre = ....TSeg2ScaleFrame;
          };
          AnySurfSTL Target = {
            FileName = "MBFOOT5_calcaneus.stl";
            ScaleXYZ = {1, 1, 1}*0.001; 
          };
        };
        SurfaceObjects0 = {&Input.Source};
        SurfaceObjects1 = {&Input.Target};
        //Max NumPoints = Number of Source Surface Verticies
        NumPoints = 5000;
        BoundingBoxOnOff = On;
        BoundingBox.ScaleXYZ = {1,1,1}*2;
        BoundingBox.DivisionFactorXYZ = {1, 1, 1}*2;
        //UseClosestPointMatchingOnOff= On;
      };

AnyFolder CalcaneusMorphingLandmarks= {
  
  AnyFolder &SegRef = .....BodyModel.Right.Leg.Seg;
  
  //Matrix of the point cloud in foot ref frame.
 AnyMatrix SourceCalcaneusPointCloud = 
    FunCEx("CalcaneusGM_picked_points_43.pp", Main.FootPrintFolderPath +"/Scaling");
  
  AnyInt Size = 43;
  AnyFunEx FunCEx = 
  {
    AnyMatrix Return = {iarr(1,.Size)*0,iarr(1,.Size)*0,iarr(1,.Size)*0}';
    AnyFunExMonoPy ReadMLFile =
    {
      ModuleFile = "ReadMeshlabIn.py";
      ArgList = 
      {
        AnyStringVar filename = "";
        AnyStringVar path = "";
      };
    };
  };
  AnyMatrix TargetCalcaneusPointCloudMillimeter =  
  
  FunCEx("MBFOOT5_calcaneus_picked_points_43.pp", Main.FootPrintFolderPath +"/Scaling");
  
  AnyMatrix TargetCalcaneusPointCloud =  TargetCalcaneusPointCloudMillimeter*0.001; 
  
  
};//CalcaneusMorphingLandmarks

//End of Calcaneus Scaling

Zach,

Unfortunately my code interpreting skills are not advanced enough to imagine two models that you are modelling, especially that I cannot see the second one.

Do you mind uploading those models?

P.

Hi Pavel, sorry for not explaining it properly.

Please find attached the folders per model the input is the same for each model. I think this is all you need to get it working, but if you need more files please let me know.

Thank you very much for your time.
Zach

Hi Pavel, I believe the issue was with my RBFDef.Type not being consistent in the CombinedMatrix version for both the AnyFunTransform3DRBF RBF and AnyFunTransform3DSTL STL.

On that note, why does the RBF Triharmonic work better than the RBF ThinPlate in this case?

One more question, what is the correct ScaleMat in:

ScaleLengthMassFatRBF.any

#ifndef CUSTOM_SCALING_Foot
          AnyFunTransform3DLin ScaleFunction = {
           ScaleMat = {{(.ms/.ls)^0.5, 0, 0},{0, .ls, 0},{0, 0, .ws}};
          // ScaleMat = {{.hs, 0, 0},{0, .ls, 0},{0, 0, .ws}};
           Offset = {0, 0, 0};
          };

I am also not able to complete the inital position, despite the marker positions looking quite good, would you have any thoughts on this? Would i have to manually adjust the blue markers in the GM model to fit my own model?
Thanks,
Zach

Hi Zach,

Should i understand your message as that you found the problem? :slight_smile:

Triharmonic and ThinPlate use different RBF functions (r^3 vs r^2*log®) to construct interpolation. In my experience Triharmonic behaves a little smoother - possibly due to the simpler form of the function. It is possible to investigate the behaviour by deforming a regular grid and seeing how it moves points. I will leave it up to you.

Kind regards,
Pavel

Thanks Pavel, I remember seeing the RBF Gridlines in one of the tutorials, so i will have a look there again.

I think i solved the scaling problem. The other question I had was on the ScalMat and Initial position with possibility to move the GM Model mocap markers?

Also,
To check the quality of the morphed mesh I have calculated the hausdorff distance between the morphed mesh (exported after morphing) and the target mesh (My MBFoot). In your experience, what would be an acceptable RMS value?

Thanks,
Zach

Hi Zach,

I am not sure I understood your first question.

Regarding RMS error: you should think what this error represents - in our case it can be viewed as a some sort of averaged error over the whole surface. Meaning that you will have this kind of error in the moment arms of the muscles. So please think what an acceptable moment arm error is in your case.

Kind regards,
Pavel

Thanks Pavel that makes a lot of sense, thanks for the RMS clarification, perhaps a bit of thinking to do on ‘acceptable’.

To my other question.

Is there a correct ScaleMat in:
In the ScaleLengthMassFatRBF.any file.

Code:

 
..
AnyFolder Foot  = {
          AnyVar LengthScale = ...AnthroSegmentLengths.Right.FootLength / ...StandardParameters.Right.Foot.Length; 
          AnyVar WidthScale = ...AnthroSegmentLengths.Right.FootWidth / ...StandardParameters.Right.Foot.Width;
          AnyVar HeightScale = ...AnthroSegmentLengths.Right.FootHeight / ...StandardParameters.Right.Foot.Height;
          AnyVar ms = ...MassScaling.Right.Foot.MassScale;
          AnyVar ls = LengthScale;
          AnyVar ws = WidthScale;
          AnyVar hs = HeightScale; 

#ifndef CUSTOM_SCALING_Foot
          AnyFunTransform3DLin ScaleFunction = {
           ScaleMat = {{(.ms/.ls)^0.5, 0, 0},{0, .ls, 0},{0, 0, .ws}};
          // ScaleMat = {{.hs, 0, 0},{0, .ls, 0},{0, 0, .ws}};
           Offset = {0, 0, 0};
          };

I think the ScaleMat refers back to the foot height length and width in Trial Specific Data:


..
 AnyFolder Anthropometrics={
    AnyVar BodyMass=76;  //the mass is automatically distributed to the segments
    AnyVar BodyHeight=1.68;  //height
    
    AnyVar ThighLength = 0.4098364 + 0.02;
    AnyVar ShankLength = 0.4073689 + 0.02;
    AnyVar FootLength = 0.2353423; //Back of heel (tuber calcanei) to second toe tip.
    AnyVar FootWidth = 0.07649351; //MPjnt1 center to MPjnt5 center.
    AnyVar FootHeight = 0.07116012; //vertical from base of heel (medial process) to ankle joint.
    AnyVar PelvisWidth=0.16; //distance between hip joints

So when I run the initial conditions it fails and I think it might be because of the rotation of the foot which i think is influenced by the ScaleMat, but I am not sure.

I’m thinking I can either change the ScaleMat or move the blue markers in the mo cap model?

I hope this makes more sense.

Thanks,
Zach

Hi Zach,

ScaleMat will only be used when you do not have subject-specific scaling of the foot. So not sure why you want it. The #ifndef statement will exclude it in case of the subject-specific scaling.

Kind regards,
Pavel

Hi Pavel, it’s been some time since I posted on this thread and I would just like to thank you for your help to date.

I’m not sure if this should be a new thread, but I am keeping it in the same thread so it is easier to find.

I have a question related to the RBF scaling and integration of an active appearance model.

I have an active appearance model of the foot and from this I have .pts files and .cnn files for points in connectivity of quite a few bones in the foot - the shape model itself is quite revealing, but am interested in how I can utilise outputs from the shape model in the AMS

I have exported the AMMR GM foot STL files as my mean shape and built the shape model that way. Although the reference frames between the shape model and AMMR GM are different. I was wondering:

  1. Is it possible to switch the low resolution GM stls for the high resolution stl’s i have made from winding the .pts and .cnn files from the appearance model?

  2. If it is possible to batch process the Inverse dynamic modelling in the AMS of all these patient specific scaled tibia to navicular bones with just a few control points given there was a global registration to the AnyBody GM STL’s so all vertices and faces in the shape model correspond.

I hope this makes sense and any thoughts would be greatly recieved.

Many Thanks,
Zach

Hi Zach,

Yes, this is all possible. Practically you just need to organize your data and scaling files, so that you can switch between them through a define with the subject ID.

And for the scaling - you need to set up a template scaling, where you will have to make your own source bones from the statistical shape model. So here is a workflow how i see it:
a) separate bones from the GM stl in Meshlab or elsewhere
b) make new STL from the statistical shape model, which would match a) - it can be achieved by optimizing the input parameters with the objective function being a similarity measure between objects, for example. This will enable using corresponding vertices as landmarks in RBF scaling.
c) setting up a combined scaling function to take into account all individual scaling functions.
d) set up batch-processing so that input files will be automatically switched together with the subject id. For example, the filenames could contain subject-id embedded.

Hope this helps.

Kind regards,
Pavel