change morphology/orientation of a segment

Dear colleagues,

i would like to change the geometry/location of the pelvis for static analyses of the StandingModel during standing. In a first step i would like to rotate the pelvis around the z axis at the SacroPelvisJnt. What would be a good way to do this?

(I don’t mean a rotation as part of the analysis, but as a change of morphology.)

Thanks,

Thomaz

Hi Thomaz ,

Attached please find a zip file which contains a very simple example for pelvis bone rotation morphing.

But the assumption is that I didn’t do anything for mass property change.

So you might have to consider the morphing of the pelvis mass property if possible.

I hope this may be what you want to try.

Best regards,
Moonki

Hi Moonki,

thanks for the code. Standalone it works (although it do not entirely know how), and when i insert it into the StandingModel the pelvis also is rotated, but the nodes of the pelvis are not transformed. I inserted the code directly in PelvisSeg.any inside the PelvisSeg. Is this the correct place?

Thanks a lot,

Thomaz

Hi Moonki,

sorry, i think we should forget about my last post. Now i realized that your code was just meant to transform the graphical output.

I think i got it and changed the Pelvis folder in ScalingUniform.any (please have a look at my attachment).
Now i get an error because of a circular dependency from “Offset”. Could you please help me about that?

Furthermore i am not sure about the order. Should the first transformation (GeomScale) be the first or the last transformation?

Thanks again,

Thomaz

Hi Thomaz,

First, I misunderstood what your intention is. So you may want to rotate everything about pelvis including muscle attachment points.

You are right. My suggestion only works for the geometry of pelvis. Then you have to apply this transformation into all muscle attachment points. It will be a big task.

Instead, I would recommend you to modify the SpineRhythmDrv.
In the ‘…\Body\AAUHuman\Trunk\JointsLumbar.any’ file,

  //Spine rhythm leaves three rotational dof between pelvis and thorax free 
  AnyKinEqSimpleDriver SpineRhythmDrv = {
    
    AnyKinMeasureLinComb Measure = {
      
      [b]AnyJoint &u1 = ..SacrumPelvisJnt;[/b]
      AnyJoint &u2 = ..L5SacrumJnt;
      AnyJoint &u3 = ..L4L5Jnt;
      AnyJoint &u4 = ..L3L4Jnt;
      AnyJoint &u5 = ..L2L3Jnt;
      AnyJoint &u6 = ..L1L2Jnt;
      AnyJoint &u7 = ..T12L1Jnt;
      
      #include "SRMatrixes.any"            
      
    }; // Measure
    
    DriverPos = {0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0};
    DriverVel = {0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0};
    Reaction.Type = {Off,Off,Off, Off,Off,Off, Off,Off,Off, Off,Off,Off, Off,Off,Off, Off,Off,Off};
    
    
  }; // SpineRhythmDrv
  #endif

This SpineRhythmDrv contains 18 constraints.
If you want to rotate the pelvis segment with respect to the SacrumPelvisJnt(AnySphericalJoint), then I would try to remove 3 lines of SpineRhythmDrv which are related to the SacrumPelvisJnt.
Instead then you should put 3 more constraints regarding this SacrumPelvisJnt. In these constraints you can specify an angle to make the pelvis be rotated with respect to the SacrumPelvisJnt.

If you still want to keep this SacrumPelvisJnt as a part of SpineRhythmDrv, then I would try to change the coefficient of the matrix.

I hope this may be helpful to you.

Best regards,
Moonki

Hi Moonki,

thanks for your help. In fact, in managed to rotate the pelvis now including its nodes with the help of your first hint by adapting the Pelvis folder in ScalingUniform.any.

But i have two concerns:

1.) Why are all the nodes transformed although you wrote it would be a big task. Either i made an error, or it was not a big task. (I prefer the latter alternative. :slight_smile: )

2.) In order to avoid a circular dependency i replaced PelvisSacrumJntNode.ARel and PelvisSacrumJntNode.sRel in your code by their values ({{1,0,0},{0,1,0},{0,0,1}} and {0.027, -0.03, 0}). Under which conditions is this all right or when is this not all right?

Kind regards,

Thomaz

Hi Thomaz,

It seems that you could find your nice way to do that!

I guess that you could modify the ‘ScaleFunction’ of the Pelvis directly in the ‘GeometricalScaling’ folder.

Yes, you are right. Because PelvisSacrumJntNode also needs the scaling function you may see the circular dependency problem.

So I would suggest you an alternative way.

You can define a new ‘ScaleFunctionOriginal’ in the GeometricalScaling folder for pelvis.

And you can use this ‘ScaleFunctionOriginal’ for the scaling of PelvisSacrumJntNode. Of course you should make a reference(AnyFunTransform3D&) for this ‘ScaleFunctionOriginal’ inside the pelvis segment.

I think this will work.

In conclusion, you can use both your new rotational scaling function and the original scaling function(only for PelvisSacrumJntNode).

I hope this may work for you.

Best regards,
Moonki

P.S) One concern is that (I think) you have to transform the mass property of the pelvis segment(Jii, Jij, sCoM) because you have rotated the pelvis segment w.r.t. the PelvisSacrumJnt.

Hi Moonki,

nice, creating two scaling functions works :slight_smile:

But i am now unsure about other things :eek: I hope i don’t bother you too much.

1.) The sCoM is also subject to the scaling function. Shouldn’t this do the job? At least the sCoM is influenced by the ROTATION_ANGLE.

2.) Jii should also change by the rotation, but for the time being i only use static analyses.

3.) There are also other places where the Pelvis.ScaleFunction is used. At the sacrum segment the original scaling should be used, but I am really concerned about the Pelvis.ScaleFunction which is also used in LegTD/HipNodes. Here i really don’t understand the code. Should here the original scaling apply, or the new one with rotation? Could you please have a look? The results for these two scaling methods are different.

I would be mavellous if you could help me on this.

Thanks, Thomaz

Hi Thomaz,

I think that your guess about question 1 & 2 may be right at the moment.

Regarding question 3, yes we have to find every place where the scaling function of pelvis are used.

I tried to find them very quickly, but there may be some files that I might miss. You can start your searching from ‘…/Body/AAUHuman/Trunk/Trunk.root.any’ file.

Here is the list of some ‘candidate’ files that we should look into:
(In the trunk folder)
‘…/Body/AAUHuman/Trunk/PelvisSeg.any’
‘…/Body/AAUHuman/Trunk/PelvisMuscleAttachmentNodes.any’ (most import for you because this file contains several AnyRefNode objects for spine muscles)
‘…/Body/AAUHuman/Trunk/Buckle.any’
‘…/Body/AAUHuman/Trunk/ContactPoints.any’
‘…/Body/AAUHuman/Trunk/NodeForScalingExt.any’

(In the leg folder)
‘…/Body/AAUHuman/LegTD/HipNodes.any’

(In the arm folder)
‘…/Body/AAUHuman/Arm/AddOnOutSideBlockForMuscles.any’

I could see that in these files the reference of pelvis scaling function is used.

Regarding this ‘HipNodes.any’ file, this file is important for the muscles between the pelvis and the leg segments(thigh and shank).
First, I would recommend you to test whether the hip joint location is correct when you run the initial condition operation of your static analysis model.

Also in the ‘PelvisSeg.any’ file, you can see the following pieces of code:

  /// This node are used by different body part for adding mirrored nodes
  /// (muscle origins/insertions etc) to the pelvis segment
  AnyRefNode Right= {
    AnyInt Sign = 1;
    AnyFunTransform3D &Scale=.Scale;
  };
  /// This node are used by different body part for adding mirrored nodes
  /// (muscle origins/insertions etc) to the pelvis segment
  AnyRefNode Left=  {
    AnyInt Sign = -1;
    AnyFunTransform3D &Scale=.Scale;
  };

Here you can switch between two different scaling functions. Then all the internal nodes which are included in these ‘Right’ and ‘Left’ nodes will be modified.

I’m not sure whether my comments are helpful to you. But I believe you can do well for your purpose.

Best regards,
Moonki

Hi Thomaz,

Suddenly I can guess another idea.

In the ‘PelvisSeg.any’ file, you can see the following code:

AnySeg PelvisSeg = {
  
  AnyFunTransform3D &Scale =..Scaling.GeometricalScaling.PelvisSeg.ScaleFunction;
....

If you can modify this code like:

AnyFunTransform3D &Scale =..Scaling.GeometricalScaling.PelvisSeg.NewRotationalScaleFunction;

Then all nodes which uses PelvisSeg.Scale will be applied by your new scaling function.

But even in this case, you should use the ‘original’ scaling function for ‘PelvisSacrumJntNode’.

I’m not sure whether this will work for you. :slight_smile:

Best regards,
Moonki

Hi Moonki,

thanks for your help.

Your last hint is exactly what i did (only the other way round). My major concern is the Pelvis.ScaleFunction in the HipNodes.any as i don’t know where it is used by, which nodes are changed by this function.

Kind regards,

Thomas

Hi Thomas,

Let’s see some pieces of code in the ‘HipNodes.any’ file:

AnyRefNode HipJoint = {
  AnyVec3 sRel0 = .LegAttachmentNodes.sRel0+(.LegAttachmentNodes.ARel*.LegAttachmentNodes.StdPar.HipJoint')';
  // The Hip Joint is positioned based on the data in the cadaver data set 
  sRel = [b].Scale[/b]( sRel0 );
  #ifdef USE_AMMR14_HIP_ROTATIONS
  // Setting the USE_AMMR14_HIP_ROTATIONSflag will emitate AMMR1.4 behaviour
  ARel=RotMat(-24*pi/180,z);
  #endif
};


/// All muscle attachment nodes from the leg is placed inside
/// their own node (coordinate system). The reason for using
/// this procedure instead of putting the nodes directly on the 
/// pelvis segment, is that it makes it possible to have the
/// leg as a selfcontained block. The nodes in this folder is
/// used by the LegTD model for muscle attachements on pelvis.
AnyRefNode LegAttachmentNodes= {
  
  /// Folder with cadaver parameters for pelvis in the LegTD model 
  AnyFolder &StdPar = ..CadaverParameters.Pelvis;
  
  /// Rotation of the Pelvis Anatomical Frame relative to lab frame of the Cadaver dataset
  AnyMat33 CadaverPelvisAnatomicalFrame_ARel = RotMat(0.5*(StdPar.PsisIpsilateral+StdPar.PsisColateral),
                          0.5*(StdPar.AsisIpsilateral+StdPar.AsisColateral) ,
                          0.5*(StdPar.PsisIpsilateral+StdPar.PsisColateral)+..Sign*(StdPar.AsisIpsilateral-StdPar.AsisColateral) )*RotMat(-pi/2,x);
  /// Position of the Pelvis Anatomical Coordinate system relative to the lab  frame of the Cadaver dataset
  AnyVec3 CadaverPelvisAnatomicalFrame_sRel  = 0.5*(StdPar.AsisIpsilateral+StdPar.AsisColateral);
  /// Rotation of the Pelvis Anatomical Coordinate system relative to the Pelvis Segment coordinate system
  AnyMat33 PelvisAnatomicalFrame_ARel = ..Trunk.SegmentsLumbar.PelvisSeg.PelvisAnatomicalFrame.ARelUnscaled;
  /// Position of the Pelvis Anatomical Coordinate system relative to the Pelvis Segment coordinate system
  AnyVec3 PelvisAnatomicalFramePos =  ..Trunk.SegmentsLumbar.PelvisSeg.PelvisAnatomicalFrame.sRelUnscaled;
  
  
  /// The ARel rotates the LegTD dataset to match the generic pelvis in the AnyBody repository. 
  /// This is done by alligning the anatomically defined coordinate systems
  ARel = PelvisAnatomicalFrame_ARel *CadaverPelvisAnatomicalFrame_ARel';
  /// The sRel aligns the LegTD dataset to match the generic pelvis in the AnyBody repository. 
  /// This is done by alligning the anatomically defined coordinate systems 
  AnyVec3 sRel0 = PelvisAnatomicalFramePos - CadaverPelvisAnatomicalFrame_sRel*ARel';
  sRel = .Scale(sRel0);



AnyFunTransform3DLin Scale = {
  AnyFunTransform3DLin Transform_HipNode = {
    // The -24 degree rotation is added to allign the muscles origins from the LegTD data set
    // with the generic AnyBody pelvic bone. 
    ScaleMat = ..ARel;
    Offset = ..sRel0*..ARel;
  };
  
  PreTransforms = {
    &Transform_HipNode,
    &...Scaling.GeometricalScaling.PelvisSeg.ScaleFunction
  };
  ScaleMat = .ARel';
  Offset = -.sRel;
};
...

I can’t explain 100% sure right now, but I think you should care about these three lines. The last Scale function will be used for some muscle attachment points which are defined ‘inside’ this LegAttachmentNodes object.

First, I would check whether the HipJoint is correct or not. You can just run the initial condition operation whether it looks correct.

If there is no problem in the HipJoint location, then I would check the muscle attachment points.

Best regards,
Moonki

Hi Moonki,

i hope my questions are not too simple.
The HipJoint seems to be all right, but i don’t know how to decide whether the LegAttachmentNodes are all right (though they look all right with the new AND the old scaling).

I always like to understand what the code does rather than just follow a certain recipe, although it is sometimes faster with trial and error ;). My major difficulty is the part within “AnyFunTransform3DLin Scale”. What does it mean that an (inner) Transform3DLin is called within another (outer) Transform3DLin and as PreTransforms the inner one is referenced?

Kind regards,

Thomaz

Hi Thomas,

The muscle attachment points on the ‘pelvis side’ for the muscles between the pelvis and the leg segments are defined in this ‘LegAttachmentNodes’ AnyRefNode object.
Thus the parameters of those muscle attachment points are defined with respect to the CadaverPelvisAnatomicalFrame of LegAttachmentNodes node.

Let’s see the ‘Scale’ function inside the LegAttachmentNodes:

AnyFunTransform3DLin Scale = {
  AnyFunTransform3DLin Transform_HipNode = {
    // The -24 degree rotation is added to allign the muscles origins from the LegTD data set
    // with the generic AnyBody pelvic bone. 
    ScaleMat = ..ARel;
    Offset = ..sRel0*..ARel;
  };
  
  PreTransforms = {
    &Transform_HipNode,
    &...Scaling.GeometricalScaling.PelvisSeg.ScaleFunction
  };
  ScaleMat = .ARel';
  Offset = -.sRel;
};

This scale function is used for the muscle attachment points inside ‘LegAttachmentNodes’ node.

The role of this scale function is to to transform the LegAttachmentNodes to the PelvisAnatomicalFrame , next scaling and finally move back to the LegAttachmentNodes.

The reason why we are doing this thing is to ‘scale’ the muscle attachment points inside the LegAttachmentNodes with respect to the pelvis anatomical frame.
But after the scaling process, those scaled muscle attachment points should be moved back to the LegAttachmentNodes.

I’m not sure whether my explanation is enough for you to understand.

Best regards,
Moonki