hip kinematic data

Hi,

After optimization step in GaitLowerExtremity example, several .tst files which contain optimised parameters will be generated.
I found there are hip kinematic data in these files, such as hip flexion, abduction and rotation. But the curve of these data is not in the same trend as listed in the literature.

So I wonder whether these hip angle data are based on global system or local system (femur or pelvis).

I also found that the hip angle data in the optimised files are different from those derived after running inverse dynamics (Main.Studies.InverseDynamicStudy.Output.HumanModel.Left.Leg.JntDOF.Hip.Constraints.Orientation.Pos).

Please could someone explain this difference, and which system these two kinematic data are based on.

Many thanks.

Regards,
Jerry

Hi Jerry

I would not use the rotation measures in AnyBody without really thinking hard about what you need. There are 12 different ways of measurering rotation with euler angles, and the result will also depended on the coordinate system you start out with.

I seem to recall that the rotations of the hip are relative to the pelvis coordinate system, and that the order of rotation may not be completely obvious.

Although they are perfectly valid, they do not follow the Grood & Suntay convention which is also recommended by the ISB.

With the Grood&Suntay convention the first rotation is around a fixed axis in the proximal segment and the last rotation around a fixed axis in the distal segment. The intermediate rotation is around floating axis perpendicular to the first and last rotation axis. This can be accomplished in AnyBody by clever selection of the coordinate systems and then measuring the rotation the distal segment.

I usually just make my own measurement of rotation, so I am sure I have what I need for comparison with other studies.

It is quite annoying to rewrite the code everytime I make a new model, so I just recently made an AnyScript template.

You can find it here if you are interested in using it:
https://gist.github.com/1977368

I am not completely sure that it is with out errors, so if you find any please contribute back.

I hope this helped you a bit. Otherwise maybe the AnyBodyTech supporters can help.

Thanks
Morten

Hi,

I did take a look at https://gist.github.com/1977368 .

But I cannot load my model due to error.

Possible problems are:

In GaitLowerExtremity, I cannot find BodyModelRef.Trunk.SegmentsLumbar.PelvisSeg.StaticMarkerFrame.
I tried to replace it with Axes, and put the following lines (only these lines) in the Study folder.

AnyKinMeasureNormComb HipFlexion = {
AnyKinRotational HipMeasure ={
AnyRefFrame &PelvisRef = Main.Studies.HumanModel.BodyModel.Trunk.SegmentsLumbar.PelvisSeg.Axes;
AnyRefFrame &ThighRef = Main.Studies.HumanModel.BodyModel.Left.Leg.Seg.Thigh.Axes;

  Type=RotAxesAngles;
  Axis1 = z; Axis2 = x; Axis3 = y;
};
Order = 1;
Weight ={1,0,0}*180/pi;

};

But I still cannot load the model due to error.

Please give me a hand.

Many thanks.

Cheers,
Jerry

Hi Jerry

The ThighRef, ShankRef etc. must be reference to object of the type AnyRefFrame. So it won’t work if you point the references directly to the .Axes variable.

Also keep in mind, that joint angles will depend on the coordinates systems of the poximal and distal segment. I have put in my own anatomical cordinates systems (AnyRefNode StaticMarkerFrame) in each segments, and I use those when calculating the joint angles. They are not present in your model, so that is the reason you got an error when you first tried my code.

You need to define the coordinate systems in each segment, between which you will measure the joint angles. The template will then create the necessary anyscript code to measure the angles.

Actually, you comment got me to read the ISB recommendations ( http://goo.gl/YN3aM ) again, and I realize that it is not enough with just one coordinate system per segment. We need two for each joint (one for the proximal and distal segment).

So I have changed the code slightly to handle that. If you plan to use the code, then keep in mind that you will have to create the AnyRefNodes that represent the coordinate systems specified in the ISB recommendation ( http://goo.gl/YN3aM ). How you create those will probably depend on your marker protocol etc.

Note: You can also use the template without defining ISB recommended coordinate systems. In that case just use the joint coordinate systems (eg. Thigh.KneeJoint, Shank.KneeJoint etc.) as inputs. That also have the advantages that you don’t get kinematic crosstalk for revolute joint which you get with the ISB definition.

See the updates, and note that there may still be errors in the code
https://gist.github.com/1977368

Regards
Morten

Hi,

I think defining the coordinate system based on the ISB recommendation ( ISB recommendation on definitions of joint coordinate system of various joints for the reporting of human joint motion--part I: ankle, hip, and spine. International Society of Biomechanics - PubMed ) in GaitLowerExtremity will be tough because of its point location definitions.

But no matter which angle rotation rule I follow, I have to figure out how it is defined.

In GaitLowerExtremity, I find that there is hip kinematic output here: InverseDynamicStud--ModelEnviromentConnection--JointAndDrivers--JntDriverRightLegTD--HipFlexion.

The codes which define this (...LegTD\Interface.any):

[SIZE=3]

[SIZE=3][COLOR=#0000ff]
[SIZE=3][COLOR=#0000ff]AnyKinMeasureOrg[/SIZE] HipFlexion = {
[SIZE=3]//create new rotated node
[/SIZE]
[SIZE=3]AnyFolder[/SIZE] &HipNodeRef=..HipNodeRef;
HipNodeRef={
[SIZE=3]AnyRefNode[/SIZE] RotNode={
ARel= {{....Sign*-1,0,0},{0,....Sign*-1,0},{0,0,1}};
};
};
[SIZE=3]AnyFolder[/SIZE] &ThighNodeRef = ..Seg.Thigh.HipJoint;
ThighNodeRef ={
[SIZE=3]AnyRefNode[/SIZE] RotNode={
ARel={{....Sign*-1,0,0},{0,....Sign*-1,0},{0,0,1}};
};
};
[SIZE=3]AnyKinRotational[/SIZE] HipMeasure ={
[SIZE=3]AnyRefNode[/SIZE] &PelvisNode = ...HipNodeRef.RotNode;
[SIZE=3]AnyRefNode[/SIZE] &ThighNode = ...Seg.Thigh.HipJoint.RotNode;

PelvisNode={[SIZE=3]//AnyDrawRefFrame drw={RGB={1,0,0};};
[/SIZE]
};
ThighNode={[SIZE=3]//AnyDrawRefFrame drw={RGB={0,1,0};};
[/SIZE]
};
Type=RotAxesAngles;
};
MeasureOrganizer={0};
};

[SIZE=3]AnyKinMeasureOrg[/SIZE] HipAbduction = {
[SIZE=3]AnyKinRotational[/SIZE] &HipJoint =.HipFlexion.HipMeasure;
MeasureOrganizer={2};
};

[SIZE=3]AnyKinMeasureOrg[/SIZE] HipExternalRotation ={
[SIZE=3]AnyKinRotational[/SIZE] &HipJoint =.HipFlexion.HipMeasure;
MeasureOrganizer={1};
};

[/COLOR][/SIZE][/COLOR][/SIZE]
Could anyone tell me how it is defined? Is it composed of a sequence of rotations or just a total rotational vector?
Which rule does it follow? Any papers related to this?

Many thanks.

Cheers,
Jerry

Hi Jerry

I will let AnyBodyTechnology answer if there is any papers related to the rotation sequence they use to define hip joint angles.

But I think I can explain how the rotation sequences in the interface file is defined. Both HipFlexion, HipAbduction and HipExternalRotation use the same ‘AnyKinRotational’ structure called ‘HipMeasures’.

The AnyKinRotational measures the rotation between two coordinate systems. Pelvis.HipJoint.RotNode and Thigh.HipJoint.RotNode. They use some rotated coordinate systems, so the abduction and external rotation have the correct sign for both the right and left leg.

It is hard to see what the rotation sequence is, but AnyKinRotational have a standard order of Z,Y,X unless otherwise defined.

So HipFlexion is rotation about the Z axis, External rotation around the Y axis, and HipAbduction around the X axis.

What clear from this, is that the order of rotation is not what is recommended by ISB. Which is why I have made the Template, to get the correct measure.

I don’t know if this order of rotation is an error or intentional by the original designer of the LegTD model. But I believe AnyBodyTechnology might change this in future versions of the repository.

Regards
Morten


M-Tech
Aalborg University
Denmark

Hi Morten,

Thanks for your kind reply.

I noticed that in [GaitLowerExtremity] HumanModel--BodyModel--leg--right--thigh (...\LegTD\Seg.any), the following code is called ISB coordinate system:

[SIZE=3]AnyRefNode[/SIZE] ISBCoordinateSystem={
ARel=RotMat(.HipJoint.sRel,.EpicondylusFemorisMidPoint.sRel,.EpicondylusFemorisMedialisStandard)RotMat(pi0.5,z);
sRel=.HipJoint.sRel;
[SIZE=3]// AnyDrawRefFrame drws = {ScaleXYZ = {1,1,1}*0.3;RGB={0,0,1};};
[/SIZE]};

I guess this coordinate system on the thigh is based on ISB recommended system. Am I right?

There is also this kind of ISB system on the shank, but not on the pelvis.

As a result, I choose to use
Main.Studies.HumanModel.BodyModel.Trunk.SegmentsLumbar.PelvisSeg.HipJointRight;
as the system on the pelvis. Because it looks like the system recommended by ISB.

However, the results based on these two systems are a little bit strange, because internal/external rotation has a mean value of 0 which is different from most of the literatures.

Please could you help me take a look at this issue.

BTW, is there any other rotational rules which might be easier to define in AnyBody (GaitLowerExtremity)?

Many thanks.

Cheers,
Jerry

Hi Jerry

The ISBCoordinateSystem that you found ought to be based the ISB recommendation. But unfortunately it is not.

The ISBCoodinateSystem in LegTD has an axis along the trans-epicodylar line, while the real ISB recommendation is to have an axis along the long-axis of the femur.

The AnyBody repository is based on the work of many different research groups. Looking at the “Seg.any” file, I can see that the ISBCoordinate system was originally contributed by Associate Professer Mark de Zee at Aalborg University. Quite funny, because he is actually one of my supervisors, so I will ask him what his was thinking when he originally defined the coordinate system.

If I should define the ISB recommended coordinate system for hip rotations in the right Thigh, it would look something like this (in psudo anyscript code)

Try to compare with section 4.4 in the ISB recommenation paper:


AnyRefNode HipISBCoord = {
   AnyVec3 O = .HipJoint.sRel;
   AnyVec3 Y = O - 0.5*(.LateralEpicondyle.sRel + .MedialEpicondyle.sRel) ;
   AnyVec3 X = cross(Y, .LateralEpicondyle.sRel -.MedialEpicondyle.sRel );
   AnyVec3 Z = cross(X,Y);
   
   // Create the sRel and ARel
   sRel = O;
   // Create the rotation matrix based on X,Y,Z
   ARel = {X/vnorm(X),Y/vnorm(Y),Z/vnorm(Z)}';
};

You can use the PelvisSeg.HipJointRight Node for the Pelvis if you want. But if you want to strictly follow the ISB recommendations, then you probably also need to define a coordinate system your self for the pelvis. Just keep in mind that since ISB recommendation have the X axis along the PSIS midpoint - ASIS midpoint line, you will NOT get zero degree hip flexion when people are standing in an anatomical position. Simply because the PSIS are usually higher than the ASIS.

Regards
Morten


M-Tech
Aalborg University
Denmark

Hi Morten,

Thanks a lot.

As for the pelvis bone mark nodes, It is not easy to pinpoint their precise positions in AnyBody. So I set this as my last resort.

In my c3d files which I used to drive the model, there are kinematic information. My supervisor said it is OK to refer to this information. But the model does not use this information. So when I tried to output these data, they are not in the same allignment as other data such as joint forces.

Is there a way for me to let GaitLowerExtremity read these data first and then output these data in the same allignment as joint forces VS time?

Cheers,
Jerry

Hi Jerry

Yes. It is not always easy to find bony landmark locations in the model. But it is not that important for the pelvis. Since the pelvis is symmetrical, the only thing unknown is the rotation of the coordinate system in the sagital plane of the pelvis.

In fact this rotation will be different from subject to subject depending on the height difference between the ASIS and the PSIS when they walk.

A other very different approach to setting the coordinate systems, is to use the marker protocol directly. I have begun to use that in some of my models. Let me just sketch the idea.

  1. First I optimize/scale the model to find segment length and unknown marker positions in some gait trial.
  2. I load a static trial where the subject is standing in the neutral positions.
  3. I create coordinate systems based on mocap markers in the first frame of the static trial.
  4. Then I load the scaling and marker positions I just found in step 1, and solve the initial conditions but with the static trial data
  5. I then transform the position and orientation of the marker defined coordinate sytems in to each segment of the model, and save those result to a file.
  6. Then I load the inverse dynamic model of the trial from step 1. Before I run this as normal, I also load the marker defined coordinate systems from step 5. These coordinates systems are then used to define the joint angles.

The advantage is that the coordinate systems becomes the same as in systems like Vicon Body Builder. We are then sure that any change in kinematics are caused by the model mechanism and scaling, and not the definition of coordinate systems.

In my c3d files which I used to drive the model, there are kinematic information. My supervisor said it is OK to refer to this information. But the model does not use this information. So when I tried to output these data, they are not in the same allignment as other data such as joint forces.

Is there a way for me to let GaitLowerExtremity read these data first and then output these data in the same allignment as joint forces VS time?

Yes there is. Just keep in mind that these kinematic data probably are measured directly from coordinate systems based on the raw mocap markers without the constraints of a model. Thus they may be different from what you get in AnyBody.

To get the C3D data in the same time instances as in AnyBody, you just need to make a interpolation function that access the data. This is also what the forceplate templates do when they access the analog data in the C3D file.


AnyFloatVar  tStart = C3DFolder.Header.FirstFrameNo/C3DFolder.Header.VideoFrameRate;
AnyFloatVar   tEnd =  C3DFolder.Header.LastFrameNo/C3DFolder.Header.VideoFrameRate;
AnyInt NoAnalogData= NumElemOf(C3DFolder.Analog.Data.Var1);
AnyFloat Time=tStart+(iarr(0,NoAnalogData)*(tEnd-tStart)/NoAnalogData);
  
AnyFunInterpol Var1Interpol = 
{
  Type = Bspline;
  BsplineOrder = 4;
  T = .Time;
  Data = .C3DFolder.Analog.Data.Variable;
};

// The following should be placed inside a study. 
// t is the time varialbe in the study, so the the function Var1Interpol() will return
// a new value whenever t updates. Thus Var1 will be come an array of values.

AnyVar Var1 = Var1Interpol(t);

Hope this helps you

Regards
Morten


M-Tech
Aalborg University
Denmark

Hi Morten,

Many thanks for your kind reply.

I put the following lines in inverse dynamic study.

[SIZE=3]

[/SIZE][SIZE=3]AnyFunInterpol[/SIZE][SIZE=3] [/SIZE]Var1Interpol[SIZE=3] [/SIZE]=[SIZE=3]
[/SIZE]{
[SIZE=3][/SIZE]Type[SIZE=3] [/SIZE]=[SIZE=3] [/SIZE]Bspline;
[SIZE=3][/SIZE]BsplineOrder[SIZE=3] [/SIZE]=[SIZE=3] [/SIZE]4;
[SIZE=3][/SIZE]T[SIZE=3] [/SIZE]=[SIZE=3] [/SIZE]Main.Studies.InverseDynamicStudy.EnvironmentModel.Plate1.Time;
[SIZE=3][/SIZE]Data[SIZE=3] [/SIZE]=[SIZE=3] [/SIZE]Main.ModelSetup.C3DFileData.Points.ProcessedData.LHipAngles.Pos;
};
[SIZE=3]
[/SIZE][SIZE=3]AnyVar[/SIZE][SIZE=3] [/SIZE]Var1[SIZE=3] [/SIZE]=[SIZE=3] [/SIZE]Var1Interpol(Main.Studies.InverseDynamicStudy.t);
[SIZE=3]

[/SIZE]

But I got this error:
[SIZE=1]Var1Interpol.Data[/SIZE] : The matrix must contain the same number of columns as T has elements, i.e., the number of data and parameter values must match

I also tried to change the following lines:

C3DFileData.Points.ProcessedData.LHipAngles.Pos[0]

And the error message became like this:
'=' : Illegal operation for given argument types : 'AnyFloat' '=' 'AnyFloat[3]'

Is there Anything I missed?

Thanks.

Cheers,
Jerry

Hi Jerry

I thought you were trying to access raw analog data in the C3D file.

I think the necessary interpolation function are all ready created for the all variables in Points folder. Thus, you can just access the values with:

AnyVec3 hipAngle = Main.ModelSetup.C3DFileData.Points.ProcessedData.L HipAngles.PosInterpol(t)

Keep in mind that it is an array of 3 element vectors, because the C3D files can only store vectors in the Points section. (See c3d.org)

Regards
Morten

Hi Morten ,

Yes, you are right. Just adding this line

[SIZE=3]AnyVec3[/SIZE] hipAngle = Main.ModelSetup.C3DFileData.Points.ProcessedData.LHipAngles.PosInterpol(.t);

in the study seems to be ok.

But, the result for the above line is zero, which is not the case in my c3d files.

Cheers,
Jerry

PS:

I interpolate LHipAngles.Pos again and I can get what I want now.
Thanks for your help.

Cheers,
Jerry

Also, I do not understand why in c3d viewer,Points.ProcessedData.L HipAngles. are angles in degree. But in LowerGaitExtremity, the maximum hip flexion is 3e-2.

I do not know how it is transformed.

Thanks.

Cheers,
Jerry

Hi Jerry

You will only see the data, when you have run the entire study. Until then the values will just be zero, when looking at them in ChartFX or AnyChart

/Morten