Issue with pull strings (i.e. example JumpingJack)

Hello,
I’m new to AnyBody and I’ve run into a problem that I lack the knowledge to fix. I did learn a great deal going through all the tutorials but none of them specifically tackled the use of AnyDrawWidgetLin or AnyDrawWidgetLRot. I was trying to alter the JumpingJack example in AMMRV1.3.1, the one with the pull string using AnyDrawWidgetLin. I tried to make a simple model to use a pull string to cause a rotation around a joint. Though I thought I had dissected ever part of the JumpingJack example, I was unable to make my model work. The condensed program I made from the JumpingJack example is below. If I run the program as is and try to set the model into initial conditions AnyBody spits out a long list of:

Failed to resolve kinematic constraints. Newton relaxation too small. (final kin. error = 4.306968E-001)
Constraint no. 1 above error tolerance 0.000001, error = 0.000067.
Constraint no. 4 above error tolerance 0.000001, error = 0.000027.
etc, etc.

I did try several different initial positions of the drivers but none of them fixed this issue. If I remove the driver labelled ‘TendonDrv’ the kinematics works fine and I can drive the model with just the ‘MCPDrv’ driver. However, since I am most interested in understanding and getting the model to move using the pull string, a functional ‘TendonDrv’ driver is important.

Please can anyone help me to understand what is wrong and how to fix it?

Thank you,
Raymond King
University of Utah

Main = {
AnyOperationSequence RunApplication = {
AnyOperation &InvAnal=Main.Study.InverseDynamics;
};
AnyFolder MyModel = {
AnyFixedRefFrame GlobalRef = {
AnyRefNode HandleBase={
sRel={0,0,0};
};
}; // Global reference frame
AnySeg Body = {
r0 = {0, -.15, 0};
Mass=2;
Jii={0.01,0.001,0.01};
AnyDrawSeg drw ={ RGB = {1, 0, 0};};
AnyRefNode MCP = { sRel = {0,.15,0};};
AnyRefNode Nail = { sRel = {0,0,0};};
AnyRefNode Hook = { sRel = {0,0,-.03};};
};
AnySeg seg1 = {
r0 = {0, .15, 0};
Mass=2;
Jii={0.01,0.001,0.01};
AnyDrawSeg drw = { RGB = {0, 1, 0};};
AnyRefNode MCP = { sRel = {0,-.15,0};};
AnyRefNode PIP = { sRel = {0,.15,0};};
AnyRefNode BaseMCP = { sRel = {0,-.1,-.03};};
AnyRefNode BasePIP = { sRel = {0,.1,-.03};};
};
AnyFixedRefFrame Handle ={
Origin={0.000000, -0.399000, 0.000000};
AnyDrawSurf drw={
FileName =“handle”;
RGB={0,1,1};
};
};
AnyRevoluteJoint MCP = {
Axis = x;
AnyRefNode &FirstNode = .Body.MCP;
AnyRefNode &SecondNode = .seg1.MCP;
};
AnyKinEq NailBodyJnt={
AnyKinLinear lin ={
AnyRefFrame &ref1=…GlobalRef;
AnyRefFrame &ref2=…Body.Nail;
};
AnyKinRotational rot ={
AnyRefFrame &ref1=…GlobalRef;
AnyRefFrame &ref2=…Body.Nail;
Type=RotAxesAngles;
};
};
AnyFunConst WeightFun ={Value = {0.001};};
AnyKinEqSimpleDriver MCPDrv ={
AnyRevoluteJoint &ref=.MCP;
DriverPos={0};
DriverVel={0};
CType={Soft};
Reaction.Type={Off};
WeightFun={&.WeightFun };
};
AnyKinPLine Tendon ={
AnyRefNode &ref1=.seg1.BaseMCP;
AnyRefNode &ref2=.Body.Hook;
AnySeg &ref3=.Handle;
AnyDrawPLine drw={Thickness=0.0015; RGB={1,0,0};};
};
AnyKinEqSimpleDriver TendonDrv={
AnyKinPLine &ref1=.Tendon;
DriverPos={0};
DriverVel={0.0};
CType = {Soft};
};
AnyDrawWidgetLin handle = {
Operation = &Main.Study.Kinematics;
UpdateEvent = OnMouseRelease;
MaxDrawSize = 0.1;
MinDrawSize = 0.1;
RefFrame = &Main.MyModel.GlobalRef;
Target = &.Main.MyModel.Handle.Origin ;
AxisOnOff = {Off, On, Off};
};
}; // MyModel
AnyBodyStudy Study = {
AnyFolder &Model = .MyModel;
InitialConditions.SolverType = KinSolOverDeterminate;
Kinematics.SolverType = KinSolOverDeterminate;
Gravity = {0.0, -9.81, 0.0};
tEnd=10;
nStep=100;
};
}; // Main

Hi Raymond,

I run your script and found an error:

You are rotating around the x-Axis, however, that is fixed. If you change the
AnyRevoluteJoint MCP = {
Axis = x;
AnyRefNode &FirstNode = .Body.MCP;
AnyRefNode &SecondNode = .seg1.MCP;};

into:

AnyRevoluteJoint MCP = {
Axis = z;
AnyRefNode &FirstNode = .Body.MCP;
AnyRefNode &SecondNode = .seg1.MCP;};

It runs fine. I did also not get what kind of rotation you want to perform. Have a look at my simpler version of your model. It makes a rotation around the MCP point. However I changed some nodes…

hope that helps
Amir

Main = {
AnyOperationSequence RunApplication = {
AnyOperation &InvAnal=Main.Study.InverseDynamics; };
AnyFolder MyModel = {
AnyFixedRefFrame GlobalRef = {
AnyDrawRefFrame drw= {
ScaleXYZ = {0.15,0.15,0.15};};
AnyRefNode HandleBase={
sRel={0,-0.4,0};}; }; // Global reference frame

AnySeg Body = {
  r0 = {0, -0.15, 0};
  Mass=2;
  Jii={0.01,0.001,0.01};
  AnyDrawSeg drw ={ RGB = {1, 0, 0};};
  AnyRefNode MCP = { sRel = {0.0, 0.15,0};};
  AnyRefNode Nail = { sRel = {0,0,0};}; };

AnySeg seg1 = {
  r0 = {0.0, 0.150, 0};
  Mass=2;
  Jii={0.01,0.001,0.01};
  AnyDrawSeg drw = { RGB = {0, 1, 0};};
  AnyRefNode MCP2 = { sRel =    {0.0,-0.15,0};};
  AnyRefNode Tend = { sRel =    {0.1,-0.15,0};}; };

AnyFixedRefFrame  Handle ={
  Origin={0.000000, -0.399000, 0.000000};
  AnyDrawSurf drw={
    FileName ="handle";
    RGB={0,1,1}; }; };

AnyRevoluteJoint MCPJoint = {
  Axis = z;
  AnyRefNode &FirstNode = .Body.MCP;
  AnyRefNode &SecondNode = .seg1.MCP2; }; 

AnyKinEq NailBodyJnt={
  AnyKinLinear lin ={
    AnyRefFrame &ref1=..GlobalRef;
    AnyRefFrame &ref2=..Body.Nail;  };
  AnyKinRotational rot ={
    AnyRefFrame &ref1=..GlobalRef;
    AnyRefFrame &ref2=..Body.Nail;
    Type=RotAxesAngles;  };  };

AnyFunConst WeightFun ={Value = {0.001};};
AnyKinEqSimpleDriver MCPDrv ={
  AnyRevoluteJoint &ref=.MCPJoint;
  DriverPos={0};
  DriverVel={0};
  CType={Soft};
  Reaction.Type={Off};
  WeightFun={&.WeightFun }; };

AnyKinPLine Tendon ={
  AnyRefNode &ref1=.seg1.Tend;
  AnyRefNode &ref2=.Body.Nail;
  AnySeg &ref3= .Handle;   
  AnyDrawPLine drw={Thickness=0.0015; RGB={1,0,0};};  };
AnyKinEqSimpleDriver TendonDrv={
  AnyKinPLine &ref1= .Tendon;  
  DriverPos={0.45};
  DriverVel={0.0}; 
  CType = {Soft}; };

AnyDrawWidgetLin handleX =         {
  Operation = &Main.Study.Kinematics;
  UpdateEvent = OnMouseRelease;
  MaxDrawSize = 0.1;
  MinDrawSize = 0.1;
  RefFrame = &Main.MyModel.GlobalRef;
  Target = &.Main.MyModel.Handle.Origin ;
  AxisOnOff = {Off, On, Off}; };   

}; // MyModel

AnyBodyStudy Study = {
AnyFolder &Model = .MyModel;
InitialConditions.SolverType = KinSolOverDeterminate;
Kinematics.SolverType = KinSolOverDeterminate;
Gravity = {0.0, -9.81, 0.0};
tEnd=10;
nStep=1; };
}; // Main

Hello Amir, Thank you for responding so quickly.

It does seem strange to me that it complains when rotating about the x-axis but not the z-axis. I guess from now on I’ll use only the z-axis for my rotations. As for your question about what I was trying to do, I was trying to build a simple finger model with a single tendon. In this case I was trying to just implement a stationary metacarpal bone and have the proximal phalanx rotation around it. I’d like to make a finger like John Wu did in the Beta folder of the AMMRV1.3.1 but with anydrawwidgetlin to move tendons and thus the finger around. Is this going to be possible with AnyBody or am I going to run into some major issues? Also is it possible to change the kinematic equations of a model to something user specified or is that all internal code that can’t be touch?

Also, I’ve just been playing around with the code you sent me (thank you again). I still do not understand how to find good initial conditions for the drivers, I noticed that in:
AnyKinEqSimpleDriver TendonDrv={
AnyKinPLine &ref1= .Tendon;
DriverPos={0.45};
DriverVel={0.0};
CType = {Soft}; };

if I change the DriverPos to something smaller the simulation fails. How did you figure out that this value needed to be at least 0.45?

Thank you,
Raymond King
University of Utah

Hey,

I realised that I used different coordinates and in my model a X-Rotation made no sense. I changed my coordinates and could do a rotation around x as well.

About the Initial Position: When you run it and even if it fails kinematically, you can klick in the Model Tree on the Pos of the desired Node, then it gives you a value in a pop-up window.

It sounds interesting what you want to do and I don’t see major problems coming, but you’ll never know…
The kinematic equations are internally, but the AnyBody still gives you many possibilities.

Thanks again for all your help in clarifying the issues I was having with AnyBody. I do have one more question though, is it possible to use multiple pull strings in such a way that allows the either of them to drive the entire system? For example I have make the model with two pull strings, but if I move one without moving the other the program explodes in errors. Can I make the top string get shorter based on the amount of movement of the bottom string to avoid crashing the system?

Thanks again,
Raymond King
University of Utah

Here is my current code:

Main = {
AnyOperationSequence RunApplication = {
AnyOperation &InvAnal=Main.Study.InverseDynamics;
};
AnyFolder MyModel = {
AnyFixedRefFrame GlobalRef = {
AnyRefNode HandleBase={
sRel={0,0,0};
};
}; // Global reference frame
AnySeg Body = {
r0 = {0, -.15, 0};
Mass=2;
Jii={0.01,0.001,0.01};
AnyDrawSeg drw ={ RGB = {1, 0, 0};};
AnyRefNode MCP = { sRel = {0,.15,0};};
AnyRefNode Nail = { sRel = {0,0,0};};
AnyRefNode Hook = { sRel = {.03,-.1,0};};
AnyRefNode BaseMCP = { sRel = {.03,.1,0};};
AnyRefNode TopHook = { sRel = {-.03,-.1,0};};
AnyRefNode TopBaseMCP = { sRel = {-.03,.1,0};};
};
AnySeg seg1 = {
r0 = {0, .15, 0};
Mass=2;
Jii={0.01,0.001,0.01};
AnyDrawSeg drw = { RGB = {0, 1, 0};};
AnyRefNode MCP = { sRel = {0,-.15,0};};
AnyRefNode PIP = { sRel = {0,.15,0};};
AnyRefNode BaseMCP = { sRel = {.03,-.1,0};};
AnyRefNode BasePIP = { sRel = {.03,.1,0};};
AnyRefNode TopBaseMCP = { sRel = {-.03,-.1,0};};
AnyRefNode TopBasePIP = { sRel = {-.03,.1,0};};
};
AnySeg seg2 = {
r0 = {0, .45, 0};
Mass=2;
Jii={0.01,0.001,0.01};
AnyDrawSeg drw = { RGB = {0, 0, 1};};
AnyRefNode PIP = { sRel = {0,-.15,0};};
AnyRefNode DIP = { sRel = {0,.15,0};};
AnyRefNode BasePIP = { sRel = {.03,-.1,0};};
AnyRefNode BaseDIP = { sRel = {.03,.1,0};};
AnyRefNode TopBasePIP = { sRel = {-.03,-.1,0};};
AnyRefNode TopBaseDIP = { sRel = {-.03,.1,0};};
};
AnySeg seg3 = {
r0 = {0, .75, 0};
Mass=2;
Jii={0.01,0.001,0.01};
AnyDrawSeg drw = { RGB = {.5, 0, .5};};
AnyRefNode DIP = { sRel = {0,-.15,0};};
AnyRefNode BaseDIP = { sRel = {.03,-.1,0};};
AnyRefNode TopBaseDIP = { sRel = {-.03,-.1,0};};
};
AnyFixedRefFrame HandleFDP ={
Origin={0.03, -0.42, 0.0};
AnyDrawSurf drw={
FileName =“handle”;
RGB={0,1,1};
};
};
AnyFixedRefFrame HandleED={
Origin={-0.03, -0.42, 0.0};
AnyDrawSurf drw={
FileName =“handle”;
RGB={0,1,1};
};
};
AnyRevoluteJoint MCP = {
Axis = z;
AnyRefNode &FirstNode = .Body.MCP;
AnyRefNode &SecondNode = .seg1.MCP;
};
AnyRevoluteJoint PIP = {
Axis = z;
AnyRefNode &FirstNode = .seg1.PIP;
AnyRefNode &SecondNode = .seg2.PIP;
};
AnyRevoluteJoint DIP = {
Axis = z;
AnyRefNode &FirstNode = .seg2.DIP;
AnyRefNode &SecondNode = .seg3.DIP;
};
AnyKinEq NailBodyJnt={
AnyKinLinear lin ={
AnyRefFrame &ref1=…GlobalRef;
AnyRefFrame &ref2=…Body.Nail;
};
AnyKinRotational rot ={
AnyRefFrame &ref1=…GlobalRef;
AnyRefFrame &ref2=…Body.Nail;
Type=RotAxesAngles;
};
};
AnyFunConst WeightFun ={Value = {0.001};};
AnyKinEqSimpleDriver MCPDrv ={
AnyRevoluteJoint &ref=.MCP;
DriverPos={0};
DriverVel={0};
CType={Soft};
Reaction.Type={Off};
WeightFun={&.WeightFun };
};
AnyKinEqSimpleDriver PIPDrv ={
AnyRevoluteJoint &ref=.PIP;
DriverPos={0};
DriverVel={0};
CType={Soft};
Reaction.Type={Off};
WeightFun={&.WeightFun };
};
AnyKinEqSimpleDriver DIPDrv ={
AnyRevoluteJoint &ref=.DIP;
DriverPos={0};
DriverVel={0};
CType={Soft};
Reaction.Type={Off};
WeightFun={&.WeightFun };
};
AnyKinPLine TendonFDP ={
AnyRefNode &ref1=.seg3.BaseDIP;
AnyRefNode &ref2=.seg2.BaseDIP;
AnyRefNode &ref3=.seg2.BasePIP;
AnyRefNode &ref4=.seg1.BasePIP;
AnyRefNode &ref5=.seg1.BaseMCP;
AnyRefNode &ref6=.Body.BaseMCP;
AnyRefNode &ref7=.Body.Hook;
AnySeg &ref8=.HandleFDP;
AnyDrawPLine drw={Thickness=0.0015; RGB={1,0,0};};
};
AnyKinPLine TendonED ={
AnyRefNode &ref1=.seg3.TopBaseDIP;
AnyRefNode &ref2=.seg2.TopBaseDIP;
AnyRefNode &ref3=.seg2.TopBasePIP;
AnyRefNode &ref4=.seg1.TopBasePIP;
AnyRefNode &ref5=.seg1.TopBaseMCP;
AnyRefNode &ref6=.Body.TopBaseMCP;
AnyRefNode &ref7=.Body.TopHook;
AnySeg &ref8=.HandleED;
AnyDrawPLine drw={Thickness=0.0015; RGB={1,0,0};};
};
AnyKinEqSimpleDriver TendonFDPDrv={
AnyKinPLine &ref1=.TendonFDP;
DriverPos={1.22};
DriverVel={-0.0};
CType = {Soft};
};
AnyKinEqSimpleDriver TendonEDDrv={
AnyKinPLine &ref1=.TendonED;
DriverPos={1.22};
DriverVel={0.00};
CType = {Soft};
};
AnyDrawWidgetLin HandleFDPline = {
Operation = &Main.Study.Kinematics;
UpdateEvent = OnMouseRelease;
MaxDrawSize = 0.1;
MinDrawSize = 0.1;
RefFrame = &Main.MyModel.GlobalRef;
Target = &.Main.MyModel.HandleFDP.Origin ;
AxisOnOff = {Off, On, Off};
};
AnyDrawWidgetLin HandleEDline = {
Operation = &Main.Study.Kinematics;
UpdateEvent = OnMouseRelease;
MaxDrawSize = 0.1;
MinDrawSize = 0.1;
RefFrame = &Main.MyModel.GlobalRef;
Target = &.Main.MyModel.HandleED.Origin ;
AxisOnOff = {Off, On, Off};
};
}; // MyModel
AnyBodyStudy Study = {
AnyFolder &Model = .MyModel;
InitialConditions.SolverType = KinSolOverDeterminate;
Kinematics.SolverType = KinSolOverDeterminate;
Gravity = {0.0, -9.81, 0.0};
tEnd=10;
nStep=1;
};
}; // Main

Hi Raymond,

try to keep it simple at the beginning! You can do that, check out my script, it’s a lot simpler:

  AnyRefNode Tend2 = { sRel =    {0.1,-0.15,0.15};};
};
AnyFixedRefFrame  Handle1 ={
  Origin={0.000000, -0.399000, -0.010000};
  AnyDrawSurf drw={
    FileName ="handle";
    RGB={0,1,1};
  };
};
    AnyFixedRefFrame  Handle2 ={
  Origin={0.000000, -0.399000, 0.010000};
  AnyDrawSurf drw={
    FileName ="handle";
    RGB={0,1,1};
  };
};
AnyRevoluteJoint MCPJoint = {
  Axis = x;
  AnyRefNode &FirstNode = .Body.MCP;
  AnyRefNode &SecondNode = .seg1.MCP2;
};     
AnyKinEq NailBodyJnt={
  AnyKinLinear lin ={
    AnyRefFrame &ref1=..GlobalRef;
    AnyRefFrame &ref2=..Body.Nail;
  };
  AnyKinRotational rot ={
    AnyRefFrame &ref1=..GlobalRef;
    AnyRefFrame &ref2=..Body.Nail;
    Type=RotAxesAngles;
  };
};
AnyFunConst WeightFun ={Value = {0.001};};
AnyKinEqSimpleDriver MCPDrv ={
  AnyRevoluteJoint &ref=.MCPJoint;
  DriverPos={0};
  DriverVel={0};
  CType={Soft};
  Reaction.Type={Off};
  WeightFun={&.WeightFun };
};
AnyKinPLine Tendon1 ={
  AnyRefNode &ref1=.seg1.Tend1;
  AnyRefNode &ref2=.Body.Nail;
  AnySeg &ref3= .Handle1;   
  AnyDrawPLine drw={Thickness=0.0015; RGB={1,0,0};};
};
AnyKinEqSimpleDriver Tendon1Drv={
  AnyKinPLine &ref1= .Tendon1;  
  DriverPos={0.45};
  DriverVel={0.0}; 
  CType = {Soft};
};
AnyKinPLine Tendon2 ={
  AnyRefNode &ref1=.seg1.Tend2;
  AnyRefNode &ref2=.Body.Nail;
  AnySeg &ref3= .Handle2;   
  AnyDrawPLine drw={Thickness=0.0015; RGB={1,0,0};};
};
AnyKinEqSimpleDriver Tendon2Drv={
  AnyKinPLine &ref1= .Tendon2;  
  DriverPos={0.45};
  DriverVel={0.0}; 
  CType = {Soft};
};
AnyDrawWidgetLin handle1X =         {
  Operation = &Main.Study.Kinematics;
  UpdateEvent = OnMouseRelease;
  MaxDrawSize = 0.1;
  MinDrawSize = 0.1;
  RefFrame = &Main.MyModel.GlobalRef;
  Target = &.Main.MyModel.Handle1.Origin ;
  AxisOnOff = {Off, On, Off};
};   
AnyDrawWidgetLin handle2X =         {
  Operation = &Main.Study.Kinematics;
  UpdateEvent = OnMouseRelease;
  MaxDrawSize = 0.1;
  MinDrawSize = 0.1;
  RefFrame = &Main.MyModel.GlobalRef;
  Target = &.Main.MyModel.Handle2.Origin ;
  AxisOnOff = {Off, On, Off};
};  

}; // MyModel
AnyBodyStudy Study = {
AnyFolder &Model = .MyModel;
InitialConditions.SolverType = KinSolOverDeterminate;
Kinematics.SolverType = KinSolOverDeterminate;
Gravity = {0.0, -9.81, 0.0};
tEnd=10;
nStep=1;
};
}; // Main