Skip to content

How to use own data in AnyMocap model

toerholm edited this page Jul 2, 2019 · 17 revisions

What do you need to process your own C3D model?

  1. You need a C3D file of the recorded trial: In most cases it is easy to switch between trials recorded in Vicon, Qualisys, Simi, ... Many of our users have the Plug-In-Gait marker protocol or something similar. Different protocols are also applicable. Additional markers can easily be added to the model. Force data from Force Platforms is necessary to ensure a smooth processing of the trials. It is also possible to use BVH files from XSens, Animazoo, Kinect, ...

  2. Anthropometric data of the recorded subject. Weight and total height of the subject are necessary. Individual segment lengths, e.g. thigh, shank, … is helping the process, but not mandatory.

What is the structure of the MoCap Model example?

Please see Documentation of AnyMocap model in AMMR to learn more about the structure of the mocap models.

In the folder MocapExamples folder three several models this description fits Plug-in-gait_Simple but most of the description is applicable to the Plug-in-gait-MultiTrial_StandingRef also. The Plug-in-gait_Simple folder containsthree subfolders, one for the Input (eg C3D), one for the Setup and one for the Output. There are also 3 main files, one only analyzing the Lower Body, and one analyzing the Full Body and one for the Full Body with ground reaction force prediction. It is an advantage to use only the lower body when looking at knee or hip for example, it same computational time.

Let’s get started, and open the model with the Main file LowerExtremity.Main.any.

To learn more about how to use the different built in studies in this model please see the AnyMocap tutorial it shows how to use the model loading an existing data file. The following part describes how to modify the model to use your own data.

The model has two built in operation sequences RunParameterIdentification and RunAnalysis Study. If you want to analyze a new motion capture trial and have a new C3D file, you need to start with the RunParameterIdentification first!

RunParameterIdentification

In this study, the C3D file will be loaded and used. The Markers of the recording will be used assigned to a body segment. The position of the markers, the joint axis, or joint centers will be determined to find the optimal Motion. The segment lengths will be optimized suing the recorded motion. This study is pure kinematics. The forces are not used, therefore the muscles will not be activated in this procedure. After finding the optimal motion and parameters, the joint angles will be exported into .txt files.

RunAnalysis

In this study, the motion will come from the previously generated .txt files and the forces from the C3D file will be added. The Body Model will be used with muscles. In this study, muscle activations and forces will be calculated and therefore joint reaction forces will be calculated. The process of using Motion and external forces as input is called “inverse dynamics”.

How to setup the model?

There are two aspects, in order to setup a new protocol or gait lab, you need to adjust the forceplates in the environment file and the markersetup in the modelsetup. If you have done that and want to simulate different trials, you need to adapt the trialspecific data.

An easy way to get an overview of which data you have in the C3D file is to use the program Mokka, it also allows you to easily load the C3D file and browser and visualize it's data. Mokka can be found at this link Mokka

Let's start with the Forceplates

Modifications in ForcePlates.any file:

The standard setup is using force plates of the type 4. Please look at C3D.org to read more about force plate types. You can create your own force plates type, but the most common plates are already setup in AnyBody. If you look into your C3D under Forceplate and Type you will see how many and what type you have. If you have a different type than type 4 you have to change a couple things.

If you are in doubt which plates you have then load the model and expand the ModelTree like on image below, in this case 3 plates of type 4 can be seen (if the model fails to load due to the wrong plates types out-comment the plates temporarily). ForcePlateType

There are two different options, you can use the AutoDetection or the basic version. AutoDetection is generally used to detect which foot (left or right) is in contact with the specific force plate automatically. So you should try to use the AutoDetection. Otherwise, if you use the basic version you need to modify this file yourself. Therefore you need to know which segment of the human body is in contact with the specific force plate. So there is no concept of 'automatic detection' when you use this file.

Another important aspect is if the force plates are using a calibration matrix or not. You can see that also in the C3D file under Force_Platform (or similar).

AutoDetection:

  • What type of force plates do you have?
  • How many force plates do you have?
  • Do they have a calibration matrix?
  • What is the vertical direction of your lab coordinate system?

Basic:

  • What type of force plates do you have?

  • How many force plates do you have?

  • Do they have a calibration matrix?

  • What Body segment (eg left foot) is touching what plate?

    Here are some examples how that might look like:

AutoDetection, type 4, 2 plates

ForcePlateAutoDetection Plate1(
    PLATE_NO=1,
    HeightTolerance = 0.07,
    VelThreshold = 2.2,
    FORCEPLATE_TYPE = 4,
    ALLOW_MULTI_LIMB_CONTACT = OFF
  ) = { };
  
  ForcePlateAutoDetection Plate2(
    PLATE_NO=2,
    HeightTolerance = 0.07,
    VelThreshold = 2.2,
    FORCEPLATE_TYPE = 4,
    ALLOW_MULTI_LIMB_CONTACT = OFF
  ) = { };

Modifications in LabSpecific.any file

This files is mostly a file which links to other files which are specific for the lab setup but a few things need to be adjusted in the file itself.

Here we need to adjust the gravity. In some Gait Labs, Y is normal to the ground, however, sometimes it is the Z-direction:

 AnyVector Gravity = {0, -9.81, 0}; // Y direction is normal to the ground

In the following sequence, you can see what values are optimized in the parameters optimization study. The segment lengths are optimized when you see an “On” after the segment name. Sometimes, it helps if you exclude certain parameters here. If the Model is setup to optimize too many parameters (and markers / see below), there is a possibility that the model will not find a solution for the optimization process and it will fail. For instance, if you don’t use any markers on the trunk segment, then ‘TrunkHeightOnOff’ value should be set as ‘Off’.

  // This adds different segment length as design variables to 
  // to the parameter identification study (Main.Studies.ParameterIdentification)
  // This allows the segment length to be optimized in based on the markers/motion
  OptimizeAnthropometricsOnOff OptimizeAntropometricsOnOff (
    PELVIS_WIDTH = ON , 
    HEAD_HEIGHT = OFF, 
    TRUNK_HEIGHT= ON, 
    RIGHT_THIGH_LENGTH= ON, 
    LEFT_THIGH_LENGTH = ON,
    RIGHT_SHANK_LENGTH= ON, 
    LEFT_SHANK_LENGTH = ON,
    RIGHT_FOOT_LENGTH= ON, 
    LEFT_FOOT_LENGTH = ON,
    RIGHT_UPPERARM_LENGTH= INCLUDE_UPPERBODY, 
    LEFT_UPPERARM_LENGTH = INCLUDE_UPPERBODY,
    RIGHT_LOWERARM_LENGTH= INCLUDE_UPPERBODY, 
    LEFT_LOWERARM_LENGTH = INCLUDE_UPPERBODY,
    RIGHT_HAND_LENGTH= OFF, 
    LEFT_HAND_LENGTH = OFF,
    LEFT_RIGHT_SYMMETRY = ON
  ) ={};

Modifications in MarkerProtocol.any file:

Now open the MarkerProtocol.any file to have a look at it (it is linked from the LabSpecific.any file):

The MarkerProtocol file contains the marker topology of the data set. It links free floating markers with the markers on the human. Usually, there is no need to make major changes here. If you want to run your own C3D files with different marker names, you might have to change marker names and marker positions.

// Marker on the Left Posterior Superior Iliac
CreateMarkerDriver LPSI ( 
MarkerName= LPSI,
MarkerPlacement=Trunk.SegmentsLumbar.PelvisSeg,
OptX=OFF, OptY=OFF, OptZ=ON,
UseC3DWeightResiduals=ON
) = {
  sRelOpt = {-0.145,0.02, -0.04};
};

Same marker definition now with comments

#ifdef _LPSI
// Marker on the Left Posterior Superior Iliac
CreateMarkerDriver LPSI ( 

//Change the name here to the name of your Marker Protocol!: 
MarkerName= LPSI,   


//Marker is assigned to Pelvis Segment 
MarkerPlacement=Trunk.SegmentsLumbar.PelvisSeg,

// Is the position of the Marker good, or does it need to be optimised?  
OptX=OFF, OptY=OFF, OptZ=ON,

//Leave this setting to ON if you may have small marker dropouts
UseC3DWeightResiduals = ON

) = {
 //Position of the Marker on the skeleton, relativ to the segment. Please adjust!
 // the location is in the anatomical frame of segment
  sRelOpt = {-0.145,0.02, -0.04};
};
#endif


Please note that if you have changed the hip markers names you will need to also modify these names in the TrialSpecific.any file. (it is described in the section for the TrialSpecific.any file)

Here is another example of a marker:

//// Lower Extremity Markers
#ifdef _RTHI
// Marker on the Right Thigh
CreateMarkerDriver RTHI ( 
MarkerName=  RTHI,
OptX=ON,OptY=ON,OptZ=ON,
MarkerPlacement =Right.Leg.Seg.Thigh,
WeightX=1.0,WeightY=1.0,WeightZ=1.0,
UseC3DWeightResiduals=ON
)= {
  sRelOpt = {0.00, -0.15, 0.1};
};
#endif

You can see in the code above that the Marker with a given name is here assigned to a body segment, e.g. RTHI is assigned to the right thigh segment. The RTHI marker is optimized in X, Y and Z direction (Opt_=”On”). The target marker is placed on the right thigh with an offset of sRelOpt = {x,y,z}. It is most likely that you place the markers in your Gait Lab differently on the skin, therefore you might have to adjust the marker's sRelOpt value. This sRelOpt value is in meter and represents the offset of the marker on the anatomical frame of the segment. The anatomical frame is a well defined reference frame on the segment constructed using bony-landmarks, almost all segments in the body models are equipped with one.

To visualize the anatomical frame you can add the code below anywhere in your model (needs to be within Main brackets)

Main.HumanModel.BodyModel.Right.Leg.Seg.Shank.AnatomicalFrame ={
AnyDrawRefFrame drw ={ScaleXYZ={1,1,1}*0.3; RGB={0,0,1};};
};

It is also possible to locate the anatomical frame in the ModelTree, Right click then select ModelView->RefFrames->Show

The default used sRelOpt values are very close to most other marker protocols, so there is usually no need to change a lot. There is also a weight function in the code that weighs the optimization of this marker. You may be able to increase these weight values for a certain marker if that marker does not have serious soft tissue artifact(STA). Think before you make changes to the existing model if your changes make really sense! You cannot optimize too many marker directions and segment lengths, otherwise the model will not find a solution and will fail in the parameter identification study, because the optimization problem becomes unbounded. An example of a bad model would if you selected all markers on the the foot to be optimized. Then there is no way the model can find a solution because all ankel flexion angles are equally good. You can easily add new markers by copying markers in this section.

Modifications in TrialSpecific.any file:

In this file you have to change the name of your C3D file (remember to also copy the file into the Input folder ):

  // This is the name of the trial c3d file without extension
  TrialFileName = "GaitNormal_1";

Additionally you can also alter the FirstFrame and LastFrame numbers if you want to cut away part of the trial data.

Please note that if you made a change to the name of the anterior hip markers (RASIS, LASIS and RPSI) you also have to change these names in here in this file, this is because the model is using these markers to get a good estimation on the initial pelvis orientation, see below.

  // This class_template calculates the load time position and orientation of 
   // the pelvis based on markers.
   AutoPelvisPos AutoPos(RASIS=RASI, LASIS=LASI, BACK=RPSI) = {};

If these markers are named differently please change them to like this e.g.

  // This class_template calculates the load time position and orientation of 
   // the pelvis based on markers.
   AutoPelvisPos AutoPos(RASIS=MY_EQUIVALENT_RASI, LASIS=MY_EQUIVALENT_LASI, BACK=MY_EQUIVALENT_RPSI) = {};

The model needs an initial guess of the starting position. You can change starting positions (angles) in the different joints. Note the initial guess just need to be good enough to get the first kinematic step solved, the initial position has no impact on results.

Alternatively it is possible to out-comment the AutoPelvisPos line and provide directly the position of the pelvis, but this then needs to be done manually (see out-commented lines below).

   Main.HumanModel.Mannequin.Posture = {
  //^ The following settings define the initial posture of the
  //^ model (e.g. at load time)
    
  // This can be ommitted if AutoPelvisPos above is used. 
   // PelvisPosX = -0.08;
   // PelvisPosY = 0.89;
   // PelvisPosZ = -0.33;
   //  
   // PelvisRotX = 0.0;
   // PelvisRotY = 0.0;
   // PelvisRotZ = 0.0;
       
    PelvisThoraxExtension = 0;
    PelvisThoraxLateralBending = 0;
    PelvisThoraxRotation = 0;

    NeckExtension = 0;
    NeckLateralBending = 0;
    NeckRotation = 0;
  
    Right = {

      HipFlexion = 20;
      HipAbduction = 4;
      HipExternalRotation = -15;
      KneeFlexion = 8;
      AnklePlantarFlexion = -10;
      SubTalarEversion = 0;
 
      GlenohumeralFlexion = 0;
      GlenohumeralAbduction = 0;
      GlenohumeralExternalRotation = 0;
      ElbowFlexion = 0;
      ElbowPronation = 0;
      WristFlexion = 0;
      WristAbduction = 0;
    
  };
    Left = {
    
      HipFlexion = -23;
      HipAbduction = 0.6660672;
      HipExternalRotation = 0;
      KneeFlexion = 14;
      AnklePlantarFlexion = -15;
      SubTalarEversion = 0;
    
      GlenohumeralFlexion = 0;
      GlenohumeralAbduction = 0;
      GlenohumeralExternalRotation = 0;
      ElbowFlexion = 0;
      ElbowPronation = 0;
      WristFlexion = 0;
      WristAbduction = 0;
    
  };

Modifications in SubjectSpecific.any file:

Now open the SubjectSpecific.any file it contains the subject specific data

It will make the optimization converge faster if you have anthropometric data from your subject. You need to enter here height and weight of the subject. These two values will also be used for strength scaling of the muscles in the model. If you have individual segment lengths, please include them as well. This will help the initial guess.

   Main.ModelSetup.SubjectSpecificData = 
{

  Main.HumanModel.Anthropometrics = 
  {
     BodyMass = 66;
     BodyHeight = 1.75;
     
     // These antrhopometric data will be used as initial guess for 
     // the optimization alogorithm the optimization algoritm will
     // allow changes to the segment lengths 
     SegmentDimensions =
     {
       PelvisWidth = DesignVar(0.16); ///< Distance between hip joints
       HeadHeight = DesignVar(0.13); ///< Height in neutral position from  C1HatNode to top of head
       TrunkHeight = DesignVar(0.60);
     
       Right = 
       {
          UpperArmLength = DesignVar(0.30);
          LowerArmLength = DesignVar(0.23);
          HandLength = DesignVar(0.182);
          HandBreadth = DesignVar(0.085);
          
          ThighLength = DesignVar(0.41); 
          ShankLength = DesignVar(0.40);
          FootLength = DesignVar(0.22);
          
       };
     
       Left = 
       {
          UpperArmLength = DesignVar(0.30);
          LowerArmLength = DesignVar(0.23);
          HandLength = DesignVar(0.182);
          HandBreadth = DesignVar(0.085);
          
          ThighLength = DesignVar(0.41); 
          ShankLength = DesignVar(0.40);
          FootLength = DesignVar(0.22);    
       };
     };
   }; //Main.HumanModel.Anthropometrics

};

Modifications in ExtraDrivers.any file:

The ExtraDrivers.any file contains additional drivers which can be added to the model these drivers helps driving the motion together with the markers in the case there are not sufficient kinematic information recorded. For example if there are no markers on the upper body, you can switch on trunk drivers to drive the upper body with special drivers and not with motion capture.

Possible Errors

Missing markers

Following error may occur during loading:

    Constructing model tree...
    ERROR(SCR.PRS9) : C:/U..s/a..Y/D..p/P..a/FDA/F..2/A..k/A..n/F..l/G..y/M..l/Marker.any  :
        Defined At  : C:/U..s/a..Y/D..p/P..a/FDA/F..2/A..k/A..n/F..l/G..y/M..l/Marker.any  :
                      'RTHI'  :  Unresolved object
    Model loading skipped

This error message means that you don’t have this particular marker in your C3D file. It might be a typo after typing in a new marker, or you really don’t have that marker and you need to out-comment it in the Marker.any file.

 //  CreateMarkerDriver RTHI ( 
//MarkerName=  RTHI,
//OptX=ON,OptY=ON,OptZ=ON,
//MarkerPlacement =Right.Leg.Seg.Thigh,
//UseC3DWeightResiduals=ON
//)= {
//  sRelOpt = {0.00, -0.15, 0.1};
//};

Please be aware that removing markers means that you should add new markers or you might get a model that has not enough constraints to run.

Missing calibration matrix definition

Following error may occur during loading:

    Constructing model tree...
    ERROR(SCR.PRS9) :  C:/U..s/a..Y/D..p/P..a/FDA/F..2/A..k/A..n/F..l/G..y/M..l/ForcePlate.any  :
                      'Cal'  :  Unresolved object
    Model loading skipped

This error message means that you don’t have a calibration matrix in your C3D file and you need to outcomment it in your environment file:

    ={
    //  Cal=Main.ModelSetup.C3DFileData.Groups.FORCE_PLATFORM.CAL_MATRIX.Data[0];
    };

Model is kinematically unconstrained

Following warning may occur during loading and then following error message during running the model:

    Model Warning: Study 'Main.Study' contains too few kinematic constraints to be kinematically determinate.
    WARNING(OBJ.MCH.KIN1) : C:/U..s/a..Y/D..p/R..5/A..c/A..n/E..s/S..l/MoCapModel.Main.any  :
                    Study : Model is kinematically indeterminate :
                    Position analysis failed :  440 independent constraints and 441 unknowns
                    - attemps to continue (attempt no. 5)
    ERROR(OBJ.MCH.KIN1) :   C:/U..s/a..Y/D..p/R..5/A..c/A..n/E..s/S..l/MoCapModel.Main.any  :
    Study  :  Model is kinematically indeterminate :  Position analysis failed

This means you don’t have enough drivers for your model. It might be that you don’t have markers on you upper body. In that case you need to introduce drivers that fix your upper body model separately. There are more explanations on the Wiki or the Forum at www.anyscript.org.

Kinematic analysis fails with "indefinite positions"

This is the same reason and cure as in a kinematically unconstrained model see above. This can happen e.g. in a model with only one marker on entire upper-body, such a model will be undetermined for pelvis-thorax rotations and head motion and extra drivers is needed.

Kinematic analysis fails

Even when there is the right number of markers and drivers in the model it can happen that the kinematic analysis fails during the optimization process. If it fails at step 0 then it is usually due a bad guess on the initial position, that means the position of the body at load time is too far from the markers. This is solved by changing the initial position in TrialSpecificData.any.

The kinematic can also fail later during the motion. That can be due to a marker dropping, and thus distorting the motion of a limb. Solutions include enabling the UseC3DWeightResidual to be ON. The failing can also come from a bad initial guess of the segment length. For example a too short limb may be stretched by the marker’s motion and may lead to a kinematic error in the joints. To cure this you can make the corresponding segments a bit longer in the TrialSpecificData.any file.

What is the correct force plate type from the C3D files?

When you load the MoCap model in AMS, you can check the following values:

   Main.ModelSetup.C3DFileData.Groups.FORCE_PLATFORM.TYPE.Data

When we see this value in the MoCap model, the values are as follows:

   Data = {4, 4, 4}

So it means that in the C3D file there are three force plates of which type is 4.

How to run MotionAndParameterOptimizationModel process using MoCap model if there are some missing markers on the upper body?

There are some extra drivers pre-defined in the "ExtraDrivers.any" file. They can be switched on in the trialspecific file.

But of course you should know that because you are missing some kinematic information of upper body segments, the analysis result would not be better than when you have full kinematic information of the whole body.

When i run the parameter optimization it fails

It is important that the optimization problem is bounded. Examples of things which can go wrong are:

  • No markers on Thorax and Head but trunk height and head height is still being optimized, this will fail since there is no way for the optimizer to determine a good height with no markers available. To fix it go to the LabSpecific.any file and switch off optimization on TrunkHeight and HeadHeight

OptimizeAnthropometricsOnOff OptimizeAntropometricsOnOff ( PELVIS_WIDTH = ON , HEAD_HEIGHT = OFF, TRUNK_HEIGHT= OFF,

  • All makers on the foot are free to be optimized in all directions: This will fails because it can not be determined what should be the flexion and inversion angles, all marker positions are equally "good". To fix this lock some of the marker positions to be not optimized. This is done in the MarkerProtocol.any file by setting OptX=OFF, OptY=OFF, OptZ=OFF so e.g.

CreateMarkerDriver RHEE ( MarkerName= RHEE , MarkerPlacement=Right.Leg.Seg.Foot, PlaceMarkerAt = HeelNode, OptX=OFF, OptY=OFF , OptZ=OFF, WeightX=1.0,WeightY=1.0,WeightZ=1.0, UseC3DWeightResiduals=ON ) = { sRelOpt = {-0.025, 0.01, -0.0}; };

How to change my model when the lab coordinate system is different from that of the default MoCap model?

In general, VICON system uses 'Z' axis as its vertical direction of the lab coordinate system.

You just need to change the gravity direction of the 'AnyBodyStudy InverseDynamicStudy' class object.

   Gravity = {0, 0, -9.81};
Clone this wiki locally
You can’t perform that action at this time.