diff --git a/Posture_and_movement/Downloads/Kick1.any b/Posture_and_movement/Downloads/Kick1.any index c879b62f..1d7dfa7c 100644 --- a/Posture_and_movement/Downloads/Kick1.any +++ b/Posture_and_movement/Downloads/Kick1.any @@ -56,15 +56,15 @@ Main = { AnyRefFrame &Thigh = .Shank.Knee; }; - AnyKinEqSimpleDriver HipDriver = { - DriverPos = {-90*pi/180}; - DriverVel = {90*pi/180}/..MyStudy.tEnd; + AnyKinDriver HipDriver = { + DriverPos0 = {-90*pi/180}; + DriverVel0 = {90*pi/180}/..MyStudy.tEnd; AnyRevoluteJoint &Joint = .Hip; }; - AnyKinEqSimpleDriver KneeDriver = { - DriverPos = {-90*pi/180}; - DriverVel = {90*pi/180}/..MyStudy.tEnd; + AnyKinDriver KneeDriver = { + DriverPos0 = {-90*pi/180}; + DriverVel0 = {90*pi/180}/..MyStudy.tEnd; AnyRevoluteJoint &Joint = .Knee; }; diff --git a/Posture_and_movement/Snippets/Intro/Kick.main.any b/Posture_and_movement/Snippets/Intro/Kick.main.any new file mode 100644 index 00000000..6b42b456 --- /dev/null +++ b/Posture_and_movement/Snippets/Intro/Kick.main.any @@ -0,0 +1,112 @@ +// This model optimizes a football kicking motion of a two-segment +// leg. The objective is to obtain maximum impact velocity within the +// given strength of the leg. + +Main = { + + // The model + AnyFolder MyModel = { + + // Global Reference Frame + AnyFixedRefFrame GlobalRef = { + AnyDrawRefFrame drw = { + ScaleXYZ = {1,1,1}/5; + }; + }; // Global reference frame + + // The thigh and shank segments both presume a center of + // mass placed one third of the length from their proximal + // ends + AnySeg Thigh = { + AnyVar Length = 0.45; + Mass = 7.5; + Jii = Mass*{1,0.05,1}/100; + AnyDrawSeg drw = {}; + r0 = {0,-Length/2,0}; + AnyRefNode Hip = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Knee = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + AnySeg Shank = { + AnyVar Length = 0.50; + Mass = 3.5; + Jii = Mass*{1,0.05,1}/100; + r0 = {0,-.Thigh.Length-Length/2,0}; + AnyDrawSeg drw = {}; + AnyRefNode Knee = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Foot = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + // We presume 2-D conditions and therefore use + // revolute joints for the hip as well as the knee. + AnyRevoluteJoint Hip = { + AnyRefFrame &Ground = .GlobalRef; + AnyRefFrame &Thigh = .Thigh.Hip; + }; + AnyRevoluteJoint Knee = { + AnyRefFrame &Ground = .Thigh.Knee; + AnyRefFrame &Thigh = .Shank.Knee; + }; + + AnyKinDriver HipDriver = { + DriverPos0 = {-90*pi/180}; + DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + AnyRevoluteJoint &Joint = .Hip; + }; + +//# BEGIN SNIPPET 1 +AnyKinDriver KneeDriver = { + DriverPos0 = {-90*pi/180}; + DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + AnyRevoluteJoint &Joint = .Knee; +}; + +§// Hip joint muscles +AnyMuscleGeneric HipFlex = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 232;}; +}; + +AnyMuscleGeneric HipExtend = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 251;}; +}; + +// Knee joint muscles +AnyMuscleGeneric KneeExtend = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 554;}; +}; + +AnyMuscleGeneric KneeFlex = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 236;}; +};§ +//# END SNIPPET 1 + + }; // MyModel + + // The study: Operations to be performed on the model + AnyBodyStudy MyStudy = { + AnyFolder &Model = .MyModel; + Gravity = {0.0, -9.81, 0.0}; + nStep = 50; + tEnd = 0.2; + }; +}; // Main \ No newline at end of file diff --git a/Posture_and_movement/Snippets/Intro/Kick2.main.any b/Posture_and_movement/Snippets/Intro/Kick2.main.any new file mode 100644 index 00000000..6bfc8280 --- /dev/null +++ b/Posture_and_movement/Snippets/Intro/Kick2.main.any @@ -0,0 +1,114 @@ +// This model optimizes a football kicking motion of a two-segment +// leg. The objective is to obtain maximum impact velocity within the +// given strength of the leg. + +Main = { + + // The model + AnyFolder MyModel = { + + // Global Reference Frame + AnyFixedRefFrame GlobalRef = { + AnyDrawRefFrame drw = { + ScaleXYZ = {1,1,1}/5; + }; + }; // Global reference frame + + // The thigh and shank segments both presume a center of + // mass placed one third of the length from their proximal + // ends + AnySeg Thigh = { + AnyVar Length = 0.45; + Mass = 7.5; + Jii = Mass*{1,0.05,1}/100; + AnyDrawSeg drw = {}; + r0 = {0,-Length/2,0}; + AnyRefNode Hip = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Knee = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + AnySeg Shank = { + AnyVar Length = 0.50; + Mass = 3.5; + Jii = Mass*{1,0.05,1}/100; + r0 = {0,-.Thigh.Length-Length/2,0}; + AnyDrawSeg drw = {}; + AnyRefNode Knee = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Foot = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + // We presume 2-D conditions and therefore use + // revolute joints for the hip as well as the knee. + AnyRevoluteJoint Hip = { + AnyRefFrame &Ground = .GlobalRef; + AnyRefFrame &Thigh = .Thigh.Hip; + }; + AnyRevoluteJoint Knee = { + AnyRefFrame &Ground = .Thigh.Knee; + AnyRefFrame &Thigh = .Shank.Knee; + }; + +//# BEGIN SNIPPET 1 +AnyKinDriver HipDriver = { + DriverPos0 = {-90*pi/180}; + DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + §Reaction.Type = {Off};§ + AnyRevoluteJoint &Joint = .Hip; +}; + +AnyKinDriver KneeDriver = { + DriverPos0 = {-90*pi/180}; + DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + §Reaction.Type = {Off};§ + AnyRevoluteJoint &Joint = .Knee; +}; +//# END SNIPPET 1 + + // Hip joint muscles + AnyMuscleGeneric HipFlex = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 232;}; + }; + + AnyMuscleGeneric HipExtend = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 251;}; + }; + + // Knee joint muscles + AnyMuscleGeneric KneeExtend = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 554;}; + }; + + AnyMuscleGeneric KneeFlex = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 236;}; + }; + + }; // MyModel + + // The study: Operations to be performed on the model + AnyBodyStudy MyStudy = { + AnyFolder &Model = .MyModel; + Gravity = {0.0, -9.81, 0.0}; + nStep = 50; + tEnd = 0.2; + }; +}; // Main \ No newline at end of file diff --git a/Posture_and_movement/Snippets/Intro/Kick3.main.any b/Posture_and_movement/Snippets/Intro/Kick3.main.any new file mode 100644 index 00000000..44f648a3 --- /dev/null +++ b/Posture_and_movement/Snippets/Intro/Kick3.main.any @@ -0,0 +1,139 @@ +// This model optimizes a football kicking motion of a two-segment +// leg. The objective is to obtain maximum impact velocity within the +// given strength of the leg. + +Main = { + + // The model + AnyFolder MyModel = { + + // Global Reference Frame + AnyFixedRefFrame GlobalRef = { + AnyDrawRefFrame drw = { + ScaleXYZ = {1,1,1}/5; + }; + }; // Global reference frame + + // The thigh and shank segments both presume a center of + // mass placed one third of the length from their proximal + // ends + AnySeg Thigh = { + AnyVar Length = 0.45; + Mass = 7.5; + Jii = Mass*{1,0.05,1}/100; + AnyDrawSeg drw = {}; + r0 = {0,-Length/2,0}; + AnyRefNode Hip = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Knee = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + AnySeg Shank = { + AnyVar Length = 0.50; + Mass = 3.5; + Jii = Mass*{1,0.05,1}/100; + r0 = {0,-.Thigh.Length-Length/2,0}; + AnyDrawSeg drw = {}; + AnyRefNode Knee = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Foot = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + // We presume 2-D conditions and therefore use + // revolute joints for the hip as well as the knee. + AnyRevoluteJoint Hip = { + AnyRefFrame &Ground = .GlobalRef; + AnyRefFrame &Thigh = .Thigh.Hip; + }; + AnyRevoluteJoint Knee = { + AnyRefFrame &Ground = .Thigh.Knee; + AnyRefFrame &Thigh = .Shank.Knee; + }; + +//# BEGIN SNIPPET 1 +§//§ AnyKinDriver HipDriver = { +§//§ DriverPos0 = {-90*pi/180}; +§//§ DriverVel0 = {90*pi/180}/..MyStudy.tEnd; +§//§ Reaction.Type = {Off}; +§//§ AnyRevoluteJoint &Joint = .Hip; +§//§ }; + +§//§ AnyKinDriver KneeDriver = { +§//§ DriverPos0 = {-90*pi/180}; +§//§ DriverVel0 = {90*pi/180}/..MyStudy.tEnd; +§//§ Reaction.Type = {Off}; +§//§ AnyRevoluteJoint &Joint = .Knee; +§//§ }; + +§// Some initial guesses for the hip and knee angle +// movements. +AnyKinEqInterPolDriver HipDriver = { + T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; + Data = {{-30, -30, -15, 0, 30}}*pi/180; + Type = Bspline; + BsplineOrder = 4; + AnyRevoluteJoint &Joint = .Hip; + Reaction.Type = {Off}; +}; + +AnyKinEqInterPolDriver KneeDriver = { + T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; + Data = {{-70, -70, -50, -40, -30}}*pi/180; + Type = Bspline; + BsplineOrder = 4; + AnyRevoluteJoint &Joint = .Knee; + Reaction.Type = {Off}; +};§ +//# END SNIPPET 1 + + // Hip joint muscles + AnyMuscleGeneric HipFlex = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 232;}; + }; + + AnyMuscleGeneric HipExtend = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 251;}; + }; + + // Knee joint muscles + AnyMuscleGeneric KneeExtend = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 554;}; + }; + + AnyMuscleGeneric KneeFlex = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 236;}; + }; + + }; // MyModel +//# BEGIN SNIPPET 2 +// The study: Operations to be performed on the model +AnyBodyStudy MyStudy = { + AnyFolder &Model = .MyModel; + InverseDynamics.Criterion.Type = MR_MinMaxStrict; + Gravity = {0.0, -9.81, 0.0}; + nStep = 50; + tEnd = 0.2; + §AnyOutputFun BallVel= { + Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass); + };§ +}; +//# END SNIPPET 2 +}; // Main \ No newline at end of file diff --git a/Posture_and_movement/Snippets/Intro/Kick4.main.any b/Posture_and_movement/Snippets/Intro/Kick4.main.any new file mode 100644 index 00000000..f4f0d55a --- /dev/null +++ b/Posture_and_movement/Snippets/Intro/Kick4.main.any @@ -0,0 +1,164 @@ +// This model optimizes a football kicking motion of a two-segment +// leg. The objective is to obtain maximum impact velocity within the +// given strength of the leg. + +Main = { + + // The model + AnyFolder MyModel = { + + // Global Reference Frame + AnyFixedRefFrame GlobalRef = { + AnyDrawRefFrame drw = { + ScaleXYZ = {1,1,1}/5; + }; + }; // Global reference frame + + // The thigh and shank segments both presume a center of + // mass placed one third of the length from their proximal + // ends + AnySeg Thigh = { + AnyVar Length = 0.45; + Mass = 7.5; + Jii = Mass*{1,0.05,1}/100; + AnyDrawSeg drw = {}; + r0 = {0,-Length/2,0}; + AnyRefNode Hip = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Knee = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + AnySeg Shank = { + AnyVar Length = 0.50; + Mass = 3.5; + Jii = Mass*{1,0.05,1}/100; + r0 = {0,-.Thigh.Length-Length/2,0}; + AnyDrawSeg drw = {}; + AnyRefNode Knee = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Foot = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + // We presume 2-D conditions and therefore use + // revolute joints for the hip as well as the knee. + AnyRevoluteJoint Hip = { + AnyRefFrame &Ground = .GlobalRef; + AnyRefFrame &Thigh = .Thigh.Hip; + }; + AnyRevoluteJoint Knee = { + AnyRefFrame &Ground = .Thigh.Knee; + AnyRefFrame &Thigh = .Shank.Knee; + }; + + // AnyKinDriver HipDriver = { + // DriverPos0 = {-90*pi/180}; + // DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + // Reaction.Type = {Off}; + // AnyRevoluteJoint &Joint = .Hip; + // }; + + // AnyKinDriver KneeDriver = { + // DriverPos0 = {-90*pi/180}; + // DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + // Reaction.Type = {Off}; + // AnyRevoluteJoint &Joint = .Knee; + // }; + + // Some initial guesses for the hip and knee angle + // movements. + AnyKinEqInterPolDriver HipDriver = { + T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; + Data = {{-30, -30, -15, 0, 30}}*pi/180; + Type = Bspline; + BsplineOrder = 4; + AnyRevoluteJoint &Joint = .Hip; + Reaction.Type = {Off}; + }; + + AnyKinEqInterPolDriver KneeDriver = { + T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; + Data = {{-70, -70, -50, -40, -30}}*pi/180; + Type = Bspline; + BsplineOrder = 4; + AnyRevoluteJoint &Joint = .Knee; + Reaction.Type = {Off}; + }; + + // Hip joint muscles + AnyMuscleGeneric HipFlex = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 232;}; + }; + + AnyMuscleGeneric HipExtend = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 251;}; + }; + + // Knee joint muscles + AnyMuscleGeneric KneeExtend = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 554;}; + }; + + AnyMuscleGeneric KneeFlex = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 236;}; + }; + + }; // MyModel +//# BEGIN SNIPPET 1 +// The study: Operations to be performed on the model +AnyBodyStudy MyStudy = { + AnyFolder &Model = .MyModel; + InverseDynamics.Criterion.Type = MR_MinMaxStrict; + Gravity = {0.0, -9.81, 0.0}; + nStep = 50; + tEnd = 0.2; + AnyOutputFun BallVel= { + Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass); + }; + §AnyOutputFun MaxAct = { + Val = .MaxMuscleActivity; + };§ +}; +//# END SNIPPET 1 + +//# BEGIN SNIPPET 2 +§// Optimize the ball velocity after the kick. +AnyOptStudy OptStudy = { + LogFile = "OptStudy.log"; + MaxIterationStep = 25; + + Analysis = { + AnyOperation &op = ..MyStudy.InverseDynamics; + }; + + // Constraint: All muscle activities below 100% + AnyDesMeasure MaxActivity = { + Val = max(..MyStudy.MaxAct()-1); + Type = LessThanZero; + }; + + // Objective function: Max horizontal velocity of the foot + AnyDesMeasure KickVel = { + Val = -max(..MyStudy.BallVel()); + Type = ObjectiveFun; + }; +};§ +//# END SNIPPET 2 +}; // Main \ No newline at end of file diff --git a/Posture_and_movement/Snippets/Intro/Kick5.main.any b/Posture_and_movement/Snippets/Intro/Kick5.main.any new file mode 100644 index 00000000..4117359a --- /dev/null +++ b/Posture_and_movement/Snippets/Intro/Kick5.main.any @@ -0,0 +1,171 @@ +// This model optimizes a football kicking motion of a two-segment +// leg. The objective is to obtain maximum impact velocity within the +// given strength of the leg. + +Main = { + + // The model + AnyFolder MyModel = { + + // Global Reference Frame + AnyFixedRefFrame GlobalRef = { + AnyDrawRefFrame drw = { + ScaleXYZ = {1,1,1}/5; + }; + }; // Global reference frame + + // The thigh and shank segments both presume a center of + // mass placed one third of the length from their proximal + // ends + AnySeg Thigh = { + AnyVar Length = 0.45; + Mass = 7.5; + Jii = Mass*{1,0.05,1}/100; + AnyDrawSeg drw = {}; + r0 = {0,-Length/2,0}; + AnyRefNode Hip = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Knee = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + AnySeg Shank = { + AnyVar Length = 0.50; + Mass = 3.5; + Jii = Mass*{1,0.05,1}/100; + r0 = {0,-.Thigh.Length-Length/2,0}; + AnyDrawSeg drw = {}; + AnyRefNode Knee = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Foot = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + // We presume 2-D conditions and therefore use + // revolute joints for the hip as well as the knee. + AnyRevoluteJoint Hip = { + AnyRefFrame &Ground = .GlobalRef; + AnyRefFrame &Thigh = .Thigh.Hip; + }; + AnyRevoluteJoint Knee = { + AnyRefFrame &Ground = .Thigh.Knee; + AnyRefFrame &Thigh = .Shank.Knee; + }; + + // AnyKinDriver HipDriver = { + // DriverPos0 = {-90*pi/180}; + // DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + // Reaction.Type = {Off}; + // AnyRevoluteJoint &Joint = .Hip; + // }; + + // AnyKinDriver KneeDriver = { + // DriverPos0 = {-90*pi/180}; + // DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + // Reaction.Type = {Off}; + // AnyRevoluteJoint &Joint = .Knee; + // }; + + // Some initial guesses for the hip and knee angle + // movements. + AnyKinEqInterPolDriver HipDriver = { + T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; + Data = {{-30, -30, -15, 0, 30}}*pi/180; + Type = Bspline; + BsplineOrder = 4; + AnyRevoluteJoint &Joint = .Hip; + Reaction.Type = {Off}; + }; + + AnyKinEqInterPolDriver KneeDriver = { + T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; + Data = {{-70, -70, -50, -40, -30}}*pi/180; + Type = Bspline; + BsplineOrder = 4; + AnyRevoluteJoint &Joint = .Knee; + Reaction.Type = {Off}; + }; + + // Hip joint muscles + AnyMuscleGeneric HipFlex = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 232;}; + }; + + AnyMuscleGeneric HipExtend = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 251;}; + }; + + // Knee joint muscles + AnyMuscleGeneric KneeExtend = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 554;}; + }; + + AnyMuscleGeneric KneeFlex = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 236;}; + }; + + }; // MyModel + + // The study: Operations to be performed on the model + AnyBodyStudy MyStudy = { + AnyFolder &Model = .MyModel; + InverseDynamics.Criterion.Type = MR_MinMaxStrict; + Gravity = {0.0, -9.81, 0.0}; + nStep = 50; + tEnd = 0.2; + AnyOutputFun BallVel= { + Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass); + }; + AnyOutputFun MaxAct = { + Val = .MaxMuscleActivity; + }; + }; + +// Optimize the ball velocity after the kick. +AnyOptStudy OptStudy = { + LogFile = "OptStudy.log"; + MaxIterationStep = 25; + + Analysis = { + AnyOperation &op = ..MyStudy.InverseDynamics; + }; + + // Constraint: All muscle activities below 100% + AnyDesMeasure MaxActivity = { + Val = max(..MyStudy.MaxAct()-1); + Type = LessThanZero; + }; + +//# BEGIN SNIPPET 1 + // Objective function: Max horizontal velocity of the foot + AnyDesMeasure KickVel = { + Val = -max(..MyStudy.BallVel()); + Type = ObjectiveFun; + }; + + §AnyVar slack = 60*pi/180; + + AnyDesVar Knee4 = { + Val = Main.MyModel.KneeDriver.Data[0][3]; + Min = Val - .slack; + Max = Val + .slack; + };§ +}; +//# END SNIPPET 1 +}; // Main \ No newline at end of file diff --git a/Posture_and_movement/Snippets/Intro/Kick6.main.any b/Posture_and_movement/Snippets/Intro/Kick6.main.any new file mode 100644 index 00000000..29fea850 --- /dev/null +++ b/Posture_and_movement/Snippets/Intro/Kick6.main.any @@ -0,0 +1,188 @@ +// This model optimizes a football kicking motion of a two-segment +// leg. The objective is to obtain maximum impact velocity within the +// given strength of the leg. + +Main = { + + // The model + AnyFolder MyModel = { + + // Global Reference Frame + AnyFixedRefFrame GlobalRef = { + AnyDrawRefFrame drw = { + ScaleXYZ = {1,1,1}/5; + }; + }; // Global reference frame + + // The thigh and shank segments both presume a center of + // mass placed one third of the length from their proximal + // ends + AnySeg Thigh = { + AnyVar Length = 0.45; + Mass = 7.5; + Jii = Mass*{1,0.05,1}/100; + AnyDrawSeg drw = {}; + r0 = {0,-Length/2,0}; + AnyRefNode Hip = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Knee = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + AnySeg Shank = { + AnyVar Length = 0.50; + Mass = 3.5; + Jii = Mass*{1,0.05,1}/100; + r0 = {0,-.Thigh.Length-Length/2,0}; + AnyDrawSeg drw = {}; + AnyRefNode Knee = { + sRel = {0,.Length/3,0}; + }; + AnyRefNode Foot = { + sRel = {0,-2*.Length/3,0}; + }; + }; + + // We presume 2-D conditions and therefore use + // revolute joints for the hip as well as the knee. + AnyRevoluteJoint Hip = { + AnyRefFrame &Ground = .GlobalRef; + AnyRefFrame &Thigh = .Thigh.Hip; + }; + AnyRevoluteJoint Knee = { + AnyRefFrame &Ground = .Thigh.Knee; + AnyRefFrame &Thigh = .Shank.Knee; + }; + + // AnyKinDriver HipDriver = { + // DriverPos0 = {-90*pi/180}; + // DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + // Reaction.Type = {Off}; + // AnyRevoluteJoint &Joint = .Hip; + // }; + + // AnyKinDriver KneeDriver = { + // DriverPos0 = {-90*pi/180}; + // DriverVel0 = {90*pi/180}/..MyStudy.tEnd; + // Reaction.Type = {Off}; + // AnyRevoluteJoint &Joint = .Knee; + // }; + + // Some initial guesses for the hip and knee angle + // movements. + AnyKinEqInterPolDriver HipDriver = { + T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; + Data = {{-30, -30, -15, 0, 30}}*pi/180; + Type = Bspline; + BsplineOrder = 4; + AnyRevoluteJoint &Joint = .Hip; + Reaction.Type = {Off}; + }; + + AnyKinEqInterPolDriver KneeDriver = { + T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; + Data = {{-70, -70, -50, -40, -30}}*pi/180; + Type = Bspline; + BsplineOrder = 4; + AnyRevoluteJoint &Joint = .Knee; + Reaction.Type = {Off}; + }; + + // Hip joint muscles + AnyMuscleGeneric HipFlex = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 232;}; + }; + + AnyMuscleGeneric HipExtend = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Hip; + AnyMuscleModel MusMdl = {F0 = 251;}; + }; + + // Knee joint muscles + AnyMuscleGeneric KneeExtend = { + MuscleModel = &MusMdl; + Type = NonNegative; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 554;}; + }; + + AnyMuscleGeneric KneeFlex = { + MuscleModel = &MusMdl; + Type = NonPositive; + AnyRevoluteJoint &Joint = .Knee; + AnyMuscleModel MusMdl = {F0 = 236;}; + }; + + }; // MyModel + + // The study: Operations to be performed on the model + AnyBodyStudy MyStudy = { + AnyFolder &Model = .MyModel; + InverseDynamics.Criterion.Type = MR_MinMaxStrict; + Gravity = {0.0, -9.81, 0.0}; + nStep = 50; + tEnd = 0.2; + AnyOutputFun BallVel= { + Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass); + }; + AnyOutputFun MaxAct = { + Val = .MaxMuscleActivity; + }; + }; + +// Optimize the ball velocity after the kick. +AnyOptStudy OptStudy = { + LogFile = "OptStudy.log"; + MaxIterationStep = 25; + + Analysis = { + AnyOperation &op = ..MyStudy.InverseDynamics; + }; + + // Constraint: All muscle activities below 100% + AnyDesMeasure MaxActivity = { + Val = max(..MyStudy.MaxAct()-1); + Type = LessThanZero; + }; + + // Objective function: Max horizontal velocity of the foot + AnyDesMeasure KickVel = { + Val = -max(..MyStudy.BallVel()); + Type = ObjectiveFun; + }; + +//# BEGIN SNIPPET 1 +AnyVar slack = 60*pi/180; + +§AnyDesVar Hip3 = { + Val = Main.MyModel.HipDriver.Data[0][2]; + Min = -30*pi/180; + Max = Val + .slack; +}; +AnyDesVar Hip4 = { + Val = Main.MyModel.HipDriver.Data[0][3]; + Min = Val - .slack; + Max = Val + .slack; +}; +AnyDesVar Knee3 = { + Val = Main.MyModel.KneeDriver.Data[0][2]; + Min = Val - .slack; + Max = Val + .slack; +};§ + +AnyDesVar Knee4 = { + Val = Main.MyModel.KneeDriver.Data[0][3]; + Min = Val - .slack; + Max = Val + .slack; +}; +//# END SNIPPET 1 +}; + +}; // Main \ No newline at end of file diff --git a/Posture_and_movement/_static/intro/image1.png b/Posture_and_movement/_static/intro/image1.png index 1d1570b5..7c122350 100644 Binary files a/Posture_and_movement/_static/intro/image1.png and b/Posture_and_movement/_static/intro/image1.png differ diff --git a/Posture_and_movement/_static/intro/image2.png b/Posture_and_movement/_static/intro/image2.png index be0c738c..2a1abaf0 100644 Binary files a/Posture_and_movement/_static/intro/image2.png and b/Posture_and_movement/_static/intro/image2.png differ diff --git a/Posture_and_movement/_static/intro/image3.png b/Posture_and_movement/_static/intro/image3.png index 7d0d3bf2..31469152 100644 Binary files a/Posture_and_movement/_static/intro/image3.png and b/Posture_and_movement/_static/intro/image3.png differ diff --git a/Posture_and_movement/_static/intro/image4.png b/Posture_and_movement/_static/intro/image4.png index 2e65f5c5..2fc0a06e 100644 Binary files a/Posture_and_movement/_static/intro/image4.png and b/Posture_and_movement/_static/intro/image4.png differ diff --git a/Posture_and_movement/intro.md b/Posture_and_movement/intro.md index 5001ad1b..c9d1db16 100644 --- a/Posture_and_movement/intro.md +++ b/Posture_and_movement/intro.md @@ -9,7 +9,9 @@ forward dynamics. To understand the difference between these two concepts it is useful to have a brief look at Newton's second law. It states the following: -**F** = *m* **a** +$$ +\mathbf{F} = m \mathbf{a} +$$ where **F** is the vector of resulting forces acting on a body with mass *m* causing an acceleration vector, **a**. So, if we know the @@ -20,7 +22,9 @@ before it can compute anything for us. But we can also re-arrange the equation to this form: -**a** = **F**/m +$$ +\mathbf{a} = \frac{\mathbf{F}}{m} +$$ In this version, if we know the forces, we can determine the movement. This is called forward dynamics. The problem with forward dynamics is @@ -76,31 +80,34 @@ objectives and decide on one that leads to a plausible movement. So we need a simple model to play with. We are going to try to optimize a two-dimensional football kick. There are all sorts of reasons why a simple model of this task might be totally inadequate, but it will serve -well to demonstrate the idea. Please download a model to begin on. -{download}`Right-click the link and save the fileKick1.any ` in some working directory. Then open -it up in the AnyBody Modeling System, load it in and open a Model View -window to have a look at the model. You should see something like this -(except the legends): - -![kick1.png](_static/intro/image1.png) +well to demonstrate the idea. Please download this model to begin on. +{download}`Right-click the link and save the file Kick1.any ` +in some working directory. Then open it up in the AnyBody Modeling System, load +it in and open a Model View window to have a look at the model. You should see +something like this (except the legends): + +```{image} _static/intro/image1.png +:alt: Kick model +:align: center +:width: 30% +``` It is a two-segment model with revolute joints at the hip and the knee, so it has in total two degrees of freedom. Let us imagine that no motion capture experiment has been performed, so we do not really know how the model will kick. But we have made the initial guess that both of the two joints are moving with constant velocity just to have some movement to -look at. Please select the InverseDynamicAnalysis operation and run it. +look at. Please select the 'InverseDynamicAnalysis' operation and run it. You will be rewarded with a very fast analysis but should be able to see that the leg performs a kick. The system also gives you the following warning: ```none -MyStudy : The muscles in the model are not loaded due to kinetically -over-constrained mechanical system. - -MyStudy.InverseDynamics : No muscles or other recruited actuators in the model. -49) ...Inversedynamic analysis completed +WARNING(OBJ.MCH.MUS1): Kick1.any(74): MyStudy: The muscles in the model are not loaded due to +kinetically over-constrained mechanical system. +NOTICE(OBJ1): Kick1.any(74): MyStudy.InverseDynamics: No muscles or other recruited actuators +in the model. ``` We get this message because the model has no muscles and the necessary @@ -113,70 +120,34 @@ muscles" to the hip and knee joints representing realistic strengths. We are going to need such joint muscles for flexion and extension respectively for both of the two joints. The red lines below add such muscles with realistic joint strengths in Newton-meter. For an -explanation of the use of the AnyMuscleGeneric class, please refer to +explanation of the use of the `AnyMuscleGeneric` class, please refer to the {doc}`muscle modeling tutorial `. -```AnyScriptDoc -AnyKinEqSimpleDriver KneeDriver = { -  DriverPos = {-90*pi/180}; -  DriverVel = {90*pi/180}/..MyStudy.tEnd; -  AnyRevoluteJoint &Joint = .Knee; -}; -§// Hip joint muscles -AnyMuscleGeneric HipFlex = { - MuscleModel = &MusMdl; - Type = NonNegative; - AnyRevoluteJoint &Joint = .Hip; - AnyMuscleModel MusMdl = {F0 = 232;}; -}; - -AnyMuscleGeneric HipExtend = { - MuscleModel = &MusMdl; - Type = NonPositive; - AnyRevoluteJoint &Joint = .Hip; - AnyMuscleModel MusMdl = {F0 = 251;}; -}; - -// Knee joint muscles -AnyMuscleGeneric KneeExtend = { - MuscleModel = &MusMdl; - Type = NonNegative; - AnyRevoluteJoint &Joint = .Knee; - AnyMuscleModel MusMdl = {F0 = 554;}; -}; - -AnyMuscleGeneric KneeFlex = { - MuscleModel = &MusMdl; - Type = NonPositive; - AnyRevoluteJoint &Joint = .Knee; - AnyMuscleModel MusMdl = {F0 = 236;}; -};§ +```{literalinclude} Snippets/Intro/Kick.main.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 1 +:end-before: //# END SNIPPET 1 ``` Please copy and paste the red lines into your model just below the -KneeDriver definition as indicated. Then remove the reaction moments -from the drivers like this: - -```AnyScriptDoc -AnyKinEqSimpleDriver HipDriver = { -  DriverPos = {-90*pi/180}; -  DriverVel = {90*pi/180}/..MyStudy.tEnd; -  §Reaction.Type = {Off};§ -  AnyRevoluteJoint &Joint = .Hip; -}; - -AnyKinEqSimpleDriver KneeDriver = { -  DriverPos = {-90*pi/180}; -  DriverVel = {90*pi/180}/..MyStudy.tEnd; -  §Reaction.Type = {Off};§ -  AnyRevoluteJoint &Joint = .Knee; -}; +`KneeDriver` definition as indicated. Then remove the reaction moments +from the hip and knee drivers like this: + +```{literalinclude} Snippets/Intro/Kick2.main.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 1 +:end-before: //# END SNIPPET 1 ``` After you reload and re-run the model you should be able to open a Chart -window, plot the MaxMuscleActivity and get this: +window, plot the `MaxMuscleActivity` under folder +`Main.MyStudy.Output.MaxMuscleActivity` and get this: -![...](_static/intro/image2.png) +```{image} _static/intro/image2.png +:alt: Max Muscle Activity +:align: center +:width: 75% +``` The movement we have imposed is unrealistic. Both joints move with constant angular velocity while, in a realistic case, the model should @@ -189,54 +160,23 @@ position of each joint in certain time steps through the kick and subsequently will interpolate between those loctions to generate a smooth motion. -```AnyScriptDoc -§//§    AnyKinEqSimpleDriver HipDriver = { -§//§      DriverPos = {-90*pi/180}; -§//§      DriverVel = {90*pi/180}/..MyStudy.tEnd; -§//§      Reaction.Type = {Off}; -§//§      AnyRevoluteJoint &Joint = .Hip; -§//§    }; -§//§ -§//§    AnyKinEqSimpleDriver KneeDriver = { -§//§      DriverPos = {-90*pi/180}; -§//§      DriverVel = {90*pi/180}/..MyStudy.tEnd; -§//§      Reaction.Type = {Off}; -§//§      AnyRevoluteJoint &Joint = .Knee; -§//§    }; - -    §// Some initial guesses for the hip and knee angle -    // movements. -    AnyKinEqInterPolDriver HipDriver = { -      T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; -      Data = {{-30, -30, -15, 0, 30}}*pi/180; -      Type = Bspline; -      BsplineOrder = 4; -      AnyRevoluteJoint &Joint = .Hip; -      Reaction.Type = {Off}; -    }; - -    AnyKinEqInterPolDriver KneeDriver = { -      T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd; -      Data = {{-70, -70, -50, -40, -30}}*pi/180; -      Type = Bspline; -      BsplineOrder = 4; -      AnyRevoluteJoint &Joint = .Knee; -      Reaction.Type = {Off}; -    };§ +```{literalinclude} Snippets/Intro/Kick3.main.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 1 +:end-before: //# END SNIPPET 1 ``` A fast reload and run of the model will show that the movement is -somewhat different now, and plotting the joint rotation velocities will -also show that the initial velocity is now zero for both joints. This is -ensured by using similar values for the first two points in each -interpolation, for instance -30 and -30 degrees in the `HipDriver`. Now we -could generate infinitely many different motions simply by inserting -different angle values into these interpolation drivers. Among them will -be the motion that generates the fastest kick without overloading the -muscles. Unfortunately, infinity is a very high number and we could -never finish searching for our solution and this is where the optimizer -can help us. We ask the optimizer to determine the best movement by -making these variations. +somewhat different now, and plotting the joint rotation velocities +(`Main.MyStudy.Output.Model.*.Vel`) will also show that the initial velocity is +now zero for both joints. This is ensured by using similar values for the first +two points in each interpolation, for instance -30 and -30 degrees in the +`HipDriver`. Now we could generate infinitely many different motions simply by +inserting different angle values into these interpolation drivers. Among them +will be the motion that generates the fastest kick without overloading the +muscles. Unfortunately, infinity is a very high number and we could never finish +searching for our solution and this is where the optimizer can help us. We ask +the optimizer to determine the best movement by making these variations. ## The Optimization Problem @@ -253,27 +193,24 @@ impact then we have enough information to predict the velocity of the ball after the impact given the velocity of the foot before the impact. We can write this formula directly into the model like this: -```AnyScriptDoc - // The study: Operations to be performed on the model - AnyBodyStudy MyStudy = { -   AnyFolder &Model = .MyModel; - InverseDynamics.Criterion.Type = MR_MinMaxStrict; -   Gravity = {0.0, -9.81, 0.0}; -   nStep = 50; -   tEnd = 0.2; -   §AnyOutputFun BallVel= { -     Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass); -   };§ - }; +```{literalinclude} Snippets/Intro/Kick3.main.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 2 +:end-before: //# END SNIPPET 2 ``` - Please load and run the model again, and then go to the Chart window -and plot the new output function. You should see this: +Please load and run the model again, and then go to the Chart window +and plot the new output function `Main.MyStudy.Output.BallVel.Val`. +You should see this: -![kickvel1](_static/intro/image3.png) +```{image} _static/intro/image3.png +:alt: BallVel +:align: center +:width: 80% +``` The function shows the predicted post-impact velocity of the ball if the -foot were to hit is at any time during the imposed movement. As +foot were to hit it at any time during the imposed movement. As expected, the exit velocity is higher the later in the movement the ball is hit because the foot velocity increases all the time. @@ -281,48 +218,20 @@ We also want to be able to limit the muscle activation to prevent overloading of the muscles, and we make a similar function for that purpose: -```AnyScriptDoc - // The study: Operations to be performed on the model - AnyBodyStudy MyStudy = { -   AnyFolder &Model = .MyModel; -   InverseDynamics.Criterion.Type = MR_MinMaxStrict; -   Gravity = {0.0, -9.81, 0.0}; -   nStep = 50; -   tEnd = 0.2; -   AnyOutputFun BallVel= { -     Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass); -   }; -   §AnyOutputFun MaxAct = { -     Val = .MaxMuscleActivity; -   };§ - }; +```{literalinclude} Snippets/Intro/Kick4.main.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 1 +:end-before: //# END SNIPPET 1 ``` -With that we should be ready to define an optimization problem. A basic -optimization study would look like this: - -```AnyScriptDoc -§// Optimize the ball velocity after the kick. -AnyOptStudy OptStudy = { -  LogFile = "OptStudy.log"; -  MaxIterationStep = 25; - -  Analysis = { -    AnyOperation &op = ..MyStudy.InverseDynamics; -  }; - -  // Constraint: All muscle activities below 100% -  AnyDesMeasure MaxActivity = { -    Val = max(..MyStudy.MaxAct()-1); -    Type = LessThanZero; -  }; - -  // Objective function: Max horizontal velocity of the foot -  AnyDesMeasure KickVel = { -    Val = -max(..MyStudy.BallVel()); -    Type = ObjectiveFun; -  }; -};§ +With that we should be ready to define an optimization problem as a new study +inserted just below the existing `MyStudy`. A basic optimization study would +look like this: + +```{literalinclude} Snippets/Intro/Kick4.main.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 2 +:end-before: //# END SNIPPET 2 ``` Please copy and paste those lines into the model right after the end of @@ -330,12 +239,16 @@ MyStudy but before the final ending brace of the model. The study contains two `AnyDesMeasures` of which the first is the maximum activity minus one. The actual constraint is -max(Activity) \< 100% +$$ +max(Activity) < 100\% +$$ but, because AnyBody requires zero right hand sides for all its constraints, it is defined on the form -max(Activity) - 1\< 0 +$$ +max(Activity) - 1< 0 +$$ The second AnyDesMeasure, `KickVel`, is defined as minus the maximum of the ball velocity. This is because AnyBody's optimizer is set up to @@ -348,79 +261,82 @@ Loading the model at this time will produce an error message because we have not defined any design variables yet. Let us begin with a single variable just to make sure we get it right before adding a lot of them: -```AnyScriptDoc -    // Objective function: Max horizontal velocity of the foot -    AnyDesMeasure KickVel = { -      Val = -max(..MyStudy.BallVel()); -      Type = ObjectiveFun; -    }; - -§    AnyVar slack = 60*pi/180; -    AnyDesVar Knee4 = { -      Val = Main.MyModel.KneeDriver.Data[0][3]; -      Min = Val - .slack; -      Max = Val + .slack; -    };§ +```{literalinclude} Snippets/Intro/Kick5.main.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 1 +:end-before: //# END SNIPPET 1 ``` This design variable controls the position of the fourth data point (remember that items in arrays are numbered from zero, so number three is the fourth position) in the knee joint driver. There are five -point in total in each driver, but we do not want to include the last +points in total in each driver, but we do not want to include the last one in the optimization because it determines the position of the foot at the end of the analysis and we want this to be on the ball. -The variable names "slack" determines the upper and lower bound of the +The variable named "slack" determines the upper and lower bound of the variations of joint angle position. We have placed this in a variable because it makes it easy to change the bounds simultaneously for all design variables later. If you reload the model now you can actually already do an optimization -with the single variable. Open the OptStudy branch of the tree on the -left hand side of the screen, highlight "Optimization", and click "Run. +with the single variable. Now run the operation "OptStudy.Optimization". After a few moments the process will converge to a better kick. You can -see how much better by going to the Chart view, openeing the OptStudy +see how much better by going to the Chart view, opening the `OptStudy` section and plotting `Main.OptStudy.Output.KickVel.Val`. You will see -that the optimization decreased the value from about -9 to about -12, +that the optimization decreased the value from about -9 to about -12,4, indicating an improvement of the ball velocity from 9 to 12 m/s. Let us quickly add some more variables: -```AnyScriptDoc -AnyVar slack = 60*pi/180; -§AnyDesVar Hip3 = { -  Val = Main.MyModel.HipDriver.Data[0][2]; -  Min = -30*pi/180; -  Max = Val + .slack; -}; -AnyDesVar Hip4 = { -  Val = Main.MyModel.HipDriver.Data[0][3]; -  Min = Val - .slack; -  Max = Val + .slack; -}; -AnyDesVar Knee3 = { -  Val = Main.MyModel.KneeDriver.Data[0][2]; -  Min = Val - .slack; -  Max = Val + .slack; -};§ -AnyDesVar Knee4 = { -  Val = Main.MyModel.KneeDriver.Data[0][3]; -  Min = Val - .slack; -  Max = Val + .slack; -}; +```{literalinclude} Snippets/Intro/Kick6.main.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 1 +:end-before: //# END SNIPPET 1 ``` Notice how we have only added design variables for points 3 and 4 in each joint angle interpolation. This is because we want to retain the beginning and ending positions and we want to make sure the velocity in the beginning remains zero, which is accomplished by keeping the second -point the same as the first point. +point the same as the first point. With this, the final optimization problem +is defined as follows: + +**Minimize the function** + +$$ +g_0(x) = -\text{BallVel} +$$ + +**Subject to the constraints** + +```{math} +g_1(x) = \max(\text{MuscleActivity}) - 1 < 0 \\ +``` + +```{math} +\text{and} +``` + +```{math} +\begin{aligned} +-30^\circ &\leq \text{Hip}_3 \leq \text{Hip}_3 + \text{slack} \\ +\text{Hip}_4 - \text{slack} &\leq \text{Hip}_4 \leq \text{Hip}_4 + \text{slack} \\ +\text{Knee}_3 - \text{slack} &\leq \text{Knee}_3 \leq \text{Knee}_3 + \text{slack} \\ +\text{Knee}_4 - \text{slack} &\leq \text{Knee}_4 \leq \text{Knee}_4 + \text{slack} +\end{aligned} +``` + Running the optimization at this stage will make the problem converge in a few interations to an optimized ball velocity of a little over 13 m/s. If we plot the two joint accelerations we get: -![kickacc1](_static/intro/image4.png) +```{image} _static/intro/image4.png +:alt: KickAcc +:align: center +:width: 80% +``` The movement shows subtle signs of a whiplash action in the sense that the movement is initiated by a knee acceleration, which is taken over by @@ -434,5 +350,5 @@ likely be because the optimizer does not have enough freedom to control the movement, and this can possibly be improved by adding additional points to the interpolation and making them variables in the optimization problem. Optimization problems are often ongoing projects -in the sense that is it difficult to know when the model is good enough -to capture the features of the body's function that we are looking for. +in the sense that it is difficult to know when the model is good enough +to capture the features of the body's function that we are looking for.