Rigid body registeration

Hello,

I am using subject-specific data from medical images to scale anybody standard model. I knew form the scaling tutorial that, at the end, i will scale one of the standard anybody model based on my target segment and that all the exported forces will be either with respect to anybody global coordinates or a local frame of reference on the segment itself.

However, for some technical reasons, i need to export the forces with respect to my target segment frame of reference. So i need to know the transformation matrix that anybody used in the reverse rigid body transformation.

In other words, i need to know how this function “VTK_LANDMARK_RIGIDBODY” works?

Waiting for your kindly reply

Shady

1 Like

Hi Shady,

That is quite easy - you already have a reverse transformation. You just need to construct the target ref. frame in the source geometry ref. frame.

You can do it by transforming 3 points:

AnyVec3 p0 = Rev({0.0,0.0,0.0});
AnyVec3 px = Rev({1.0,0.0,0.0});
AnyVec3 py = Rev({0.0,1.0,0.0});

p0 will be your origin (sRel for AnyRefNode), and you can use RotMat function with 3 points as arguments to compute orientation (ARel of AnyRefNode).

After that you will need to report forces of interest in the constructed reference frame - please read the manual on AnyForceMomentMeasure2.

P.S. Remark about the rigidbody transformations - it is a least squares function that tries to position a set of points as close as possible in the least squares sense to a second set of points. When you switch inputs - you get an inverse transformation.

Regads,
Pavel

1 Like

Thanks Pave for your reply.

It is the first time for me to use AnyBody, and your answer is difficult to comprehend.

According to what you said, i will need to define 3 points on the target segment and then transform these points to the source segment. These points will construct similar local reference frame in both target and source segments, right?

So what i did is that i defined three points at the target segment:

AnySeg TargetFemur =
{
Mass = 0; Jii = {0, 0, 0};
AnyDrawSurf Surface =
{
FileName = “OBELIX_L Femur 1_smoothed.stl”;
};

  AnyRefNode LatAntCondyle = {
      sRel = {-40,0,0}; 
    };
    AnyRefNode LatAnt = {
      sRel = {0,30,0}; 
    };
    AnyRefNode CentAnt = { 
      sRel = {0,0,30}; 
    };

Next, i will need to transform these points to the source segment by defining P0, Px, and Py. Is this done by just adding the three AnyVec3 as you stated or i will need to do something before it?

Kindly, clarify more the procedure for a beginner.

Thanks in advance

Shady

Hi Shady,

I am sorry if it was not clear. I assumed you have had a look at the tutorials and quite familiar with the morphing concept.

Normally the bone-specific scaling function consists of a sequence of transformations: a) with the first one (AffineTransformation in the tutorials) being an affine scaling to deform the source landmarks to a size of the target landmarks set, it also moves the bone/landmarks to the location of provided landmarks (all done in a least square manner), b) second and third transformations in the pipeline will construct a nonlinear deformation transformation to deform the bone locally to ensure similarity of the shapes, c) the last transformation (i call it Rev, ReverseTransform in the tutorial) in the pipeline brings the bone back to the original source segmental ref. frame.

So this last transformation is the transformation between a CS of the target bone and the segmental ref. frame. This object in AnyBody Modeling System will contain a 4x4 transformation matrix that you want: TransformationMatrix. Applying this transformation to the origin (0,0,0) of the target CS will move it into the segmental ref. frame, similarly it will move location of points on the X and Y axes. These 3 new nodes define a child CS in the segmental ref. frame, that corresponds to the ref. frame of the target bone. This is the ref. frame that you wanted and you can use it to output forces through AnyForceMomentMeasure2 or Finite Element exporting classes (please check ref. manual and tutorials).

In your case if you want to transform these nodes you would do this:


AnyFunTransform ReverseTransformation = {...}; // defined somewhere, from Target to Source ref. frame

AnySeg TargetFemur = {
 ...
 AnyRefNode myNode = {sRel = {-30,0,0};};
};
AnySeg SourceFemur = {
 ...
 AnyRefNode myNode = {sRel = fullpath..ReverseTransformation(fullpath..TargetFemur.myNode.sRel);};
};


This will move the node into the SourceFemur ref. frame, but orientation of the node is not preserved. You would need to do the trick with 3 points to define an ARel of myNode.

Hope this makes more sense. If not - could we try to break down the question into simpler?

Kind regards,
Pavel

Hi Pavel,

Thanks so much for your kindly response.

I followed your instructions, and i think it works good. However, the local frame of reference of the target segment was far from the segment, which makes me uncertain if the transformation works correct or not!!

I attached the script+stl files. If you can, kindly, confirm that what i did was correct, it will be really appreciated. (I used only rigid transformation not affine at the first step because my points selections was not good and the scaling was quite bad, i will fix it later).

Finally, how can i define the local coordinates at the target segment in a specific point on the segment itself? For instance, how can i make the origin at the Inter-condylar of the femur?

Many thanks,
Shady

Hi Shady,

Yes, you have something working, although the registration transformation is not ideal - some rotation is present, i would probably use more points or less, but in better location (think of distributing masses):

But your reverse one as expected returns the undeformed bone exactly into the original position.

So, to answer the last question:
You can create a ref. frame by adding an AnyRefNode object as a child to the relevant ref. frame, e.g. segmental ref. frame. sRel will be the origin, ARel will provide orientation.

So if you create a node in a parent that contains the source bone using processed direction vectors, as i suggested - you will get a ref. frame that will allow you to register your target bone with the source bone.

If you need to create an unrelated ref. frame, just make an AnyRefNode and provide sRel and ARel as needed. You could use linear combination or a function of other sRels to get the right vector that will always follow the morphing.

Hope this helps,
Pavel

Thanks Pavel, that was so helpful :slight_smile: