Sudden force/moment simulation on knee joint

Hello!

I just started working with AB so please have patience :slight_smile:

I have a model of a knee and I am trying to simulate a landing motion and separate a pivoting motion. The purpose is to study the effect of the two motions on the ACL, the anterior tibial translation and the internal/external rotations.

To give an idea about the model of the knee I have, it is similar to the AMMR knee model but it is adapted to a cadaver's MRI scans.

I have already tried applying a load/moment using AnyForce/Moment3D, but I realized those are constant loads/moments.

What I am trying to do is start the simulation with the knee flexed, lets say at around 60 deg, and extend it using a simple driver. This part is implemented and works. But what I actually want is that around lets say 5 deg (almost extended), firstly I would apply a sudden force of X Newtons and for the second simulation I would apply at the same knee angle a sudden moment of Y Nm. I think maybe best would be to use a sine wave with a certain frequency or to apply the force/moment with a certain acceleration starting at the certain knee extension, but I am not sure as in how I should implement this.

I appreciate any suggestions

Here is the code I have so far.

AnyFolder Loads =
{

AnyForce3D AppliedForce =
{
AnyRefFrame& target = Main.MyModel.Shank;
Flocal = {0.0, 400.0, 0.0}; //apply force on y axis

AnyDrawVector Drw = 
{
  AnyRefFrame& ref = Main.MyModel.Shank.ContactPointTibia;
  Vec = .Flocal/3000;
  Line.Thickness = 0.01;
  Line.End.Style  = Line3DCapStyleArrow ;
  Line.RGB = {1, 0, 0};
  PointAway = Off;
  GlobalCoord = Off;
};    

};

AnyMoment3D AppliedMoment =
{
AnyRefFrame& ref = Main.MyModel.Shank;
Mlocal = {0.0, 0.0, 50}; //apply moment on z axis
AnyDrawVector Drw =
{
AnyRefFrame& ref = Main.MyModel.Shank.ContactPointTibia;
Vec = .Mlocal/1000;
Line.Thickness = 0.01;
Line.End.Style = Line3DCapStyleArrow ;
Line.RGB = {0, 0, 1};
PointAway = Off;
GlobalCoord = Off;
};
};
};

AnyBodyStudy MyStudy =
{
MechObjectExclude = KneeFDKModel_ExcludeThis;

Gravity = {0.0, -9.81, 0.0};

AnyFolder &Model = .MyModel; //include segments and nodes
AnyFolder &Loads = .Loads; //include loads & moments

tEnd = 10;
nStep = 1;

//knee flexion driver
AnyKinEqSimpleDriver KneeFlexion = 
{
  AnyRevoluteJoint &Knee = .Model.Jnt.Knee;
  DriverVel = -DriverPos/.tEnd;
  DriverPos = {pi/3}; 
  AnyVector KneeFlexionDeg = Knee.Pos * 180 / pi;
  Reaction.Type = {Off};
  CType = {Soft};
};

}; //MyStudy

Thank you in advance for help!

Best,
Diana

Hi Diana,

You can apply a force or moment using any of the expressions available in AnyBody so e.g. cos, sin or smoothramp please see details on the smoothramp function in the reference manual, all available functions can be seen in the pullout menu to the right.

When you apply the force you can write e.g.

AnyForce3D AppliedForce ={
AnyRefFrame& target = Main.MyModel.Shank;
Flocal = {0.0, 400*cos(MY.KNEEANGLE.POS[0]), 0.0}; //apply force on y axis
};

Best regards
Søren

Thank you, Søren! The code worked!

I do have another question related to my initial question though. I am trying to only apply the force starting a certain angle. For instance, when the knee arrives at X deg, the force should start acting.

AnyInt IfVar = ltfun(Main.MyModel.Jnt.Knee.Pos[0], pi/6);
Flocal = (iffun(IfVar, {0.0, 400.0, 0.0}, {0.0, 0.0, 0.0})*cos(Main.MyModel.Jnt.Knee.Pos[0]));

From the code I am thinking it should only apply the force if the IfVar is true, but it always applies it and I am not sure why...

Best,
Diana

Hi Diana,

For this kind of force behavior please explore the smoothramp functions it is good for exactly this to start at zero and kick in at a certain well define point.

I read your code as this, if angle are less than pi/6 it will apply 400 otherwise the cos function.

Best regards
Søren

Hi Søren,

Thanks for your quick reply.

I am a bit confused because, from what I read, the iffun function should return either {0.0, 400.0, 0.0} or {0.0, 0.0, 0.0}, depending on the true/false of the IfVar. I have placed the *cos(...) after the return of the function. So it should multiply the cos with whatever the iffun returns, therefore it should either return {0.0, 400.0, 0.0} x cos(...), which is basically {0.0, 400.0 x cos(...), 0.0}, either {0.0, 0.0, 0.0} since multiplying the cos with that would be 0 as well. Or am I understanding this wrong?

Ok, thank you, I will look into the smoothramp functions!

Best,
Diana

Hi Diana

Ups sorry i was too quick you are right,
Try to run the model and inspect the variables (IfVar. FLocal) while the model is running this will show you what exactly is going on.

Best regards
Søren

Hi Søren,

No worries! Thank you for your help!

I am trying to run the model but I am getting the following errors:

ERROR(OBJ.MCH.MUS4) : kneemodel.main.any(357) : MyStudy.InverseDynamics : Muscle recruitment solver : solver aborted after maximum number of line-search iterations

and

ERROR(OBJ.MCH.KIN3) : kneemodel.main.any(357) : MyStudy.InverseDynamics : Kinematic analysis failed in time step 0

The model runs if I give it a manual Flocal with any value, even with cos, but if I try the code before, it has the above errors.

I have tried to modify the initial starting position of the knee, as recommended by the explanation, but whatever initial position I choose, it has the same result.

I have looked into the (Flocal) in the model tree, and it changes its values indeed. But it always gives the above errors, so I can only see the Flocal receiving the values of {0.0, 0.0, 0.0} but then it stops at the first step. I was thinking maybe the program does not like a zero force, so I also tried to make it 1 or 100, and also without the cos, but it has the same result. I am not sure why this is, because if I give it a manual Flocal, it runs as expected, but if i give it that function, it does not...

Would you have any idea of why this might happen?

Also, I was trying to implement the smoothramp function in the meantime, but I could only find this explanation:

"Generates a smooth ramp function which transition from 0 at Edge0 to 0.5 at Edge1 where the function reaches its maximum slope of 2x. After Edge1 it continues with a constant slope. First and second order derivatives are zero at the edge points."

with the following implementation example:
// smoothramp() with 3 arguments
smoothramp(Edge1:AnyFloat, Edge2:AnyFloat, Value:AnyFloat) -> AnyFloat
smoothramp(Edge1:AnyInt, Edge2:AnyInt, Value:AnyFloat) -> AnyFloat
smoothramp(Edge1:AnyInt, Edge2:AnyFloat, Value:AnyFloat) -> AnyFloat
smoothramp(Edge1:AnyFloat, Edge2:AnyInt, Value:AnyFloat) -> AnyFloat

I know this is a dumb question, but I am not sure how I am supposed to implement it. I tried searching for examples in the documentation, and I couldn't find anything.

Could you give an example on how to implement it please?

Best,
Diana

So I have tried many times, and I have realized one thing: the model always gives errors if the Flocal < 300 N.

The model runs as expected with the above mentioned code, where I can make the Flocal shift from 300N to a higher X value at whatever degree I would like it to shift, but I am confused as in why is the model giving errors if the force is lower than the said value?

Shouldn't the model work when I give it a lower force? Since when I try to run the model without any force acting on it, it runs smoothly? :thinking:

Best,
Diana

Hi Diana,

I assume the model is running with FDK right?

FDK analysis is sensitive to the stiffness configuration in the joint.

The model will have an initial position for the joint which is the defined by your FDK drivers, it will start with the position in their driver value and then move away from this starting position to obtain equilibrium on the FDK DOF'S in the model.

This means that having a force or not can influence if the model is able to find the equilibrium or not, and this may lead to both of the two errors you see.

Please see this wiki post on trouble shooting an FDK model All about Force Dependent Kinematics · AnyBody/support Wiki · GitHub

One simple crude trick to get a model running is to add artificial stiffness in the joint, this may help you understand what goes on, additionally ligament calibration is crucial if ligaments stiffness has not been calibrated the model will not solve correctly.

Please also ensure to go through tutorials if you did not already do this, FDK is to be considered an advanced topic because the complexity is higher and model behavior can be more difficult to understand, if possible try to reduce model complexity.

Sorry for the not very precise answer :wink:

Best regards
Søren

1 Like

Hi Søren,

Yes, my model does use FDK.

Ohh, I see. I think I have a better understanding now of what is actually happening in the model.

Thank you for the link! I will look into it.

I did go through the tutorials but sometimes it is a bit hard to understand what is happening and to correlate the tutorials to the model I am using.

I appreciate your help!

Best,
Diana

Hi Diana,

It is just an idea, maybe try to add the force to the simple knee model from the tutorial.
https://anyscript.org/tutorials/ForceDependentKinematics/lesson4.html

This will run quickly and possibly be easier to understand, then move the force definition to the real model.

I have added a new entry to the wiki on FDK this is an explanation on how to monitor the residual forces in the FDK DOF while the model is running, doing this can help you understand which FDK DOF is causing problems. https://github.com/AnyBody/support/wiki/All-about-Force-Dependent-Kinematics#how-to-monitor-the-fdk-convergence

Best regards
Søren

Hi Søren,

Thank you so much! I will read the wiki!

Best,
Diana

This topic was automatically closed 125 days after the last reply. New replies are no longer allowed.