Skip to content

Commit 107c11e

Browse files
authored
Merge pull request #2 from AnyBody/posture-prediction-tutorial-upd
Update Posture and Movement tutorial with new images and code improvements
2 parents 88c7ce9 + da60566 commit 107c11e

File tree

6 files changed

+42
-38
lines changed

6 files changed

+42
-38
lines changed
9.3 KB
Loading
-5.8 KB
Binary file not shown.
18.3 KB
Loading
-12.7 KB
Binary file not shown.
27.4 KB
Loading

Posture_and_movement/intro.md

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Posture and Movement Prediction
22

3-
{{ caution_old_tutorial }}
4-
53
Just about every example you find in these tutorials is based on the
64
concept of inverse dynamics, which in some sense is the opposite of
75
forward dynamics. To understand the difference between these two
@@ -94,11 +92,13 @@ that the leg performs a kick.
9492

9593
The system also gives you the following warning:
9694

97-
*MyStudy* : The muscles in the model are not loaded due to kinetically
95+
```none
96+
MyStudy : The muscles in the model are not loaded due to kinetically
9897
over-constrained mechanical system.
9998
100-
*MyStudy.InverseDynamics* : No muscles in the model. 49) ...Inverse
101-
dynamic analysis completed
99+
MyStudy.InverseDynamics : No muscles or other recruited actuators in the model.
100+
49) ...Inversedynamic analysis completed
101+
```
102102

103103
We get this message because the model has no muscles and the necessary
104104
joint torques to produce the movement are provided by the drivers. We
@@ -110,7 +110,7 @@ muscles" to the hip and knee joints representing realistic strengths. We
110110
are going to need such joint muscles for flexion and extension
111111
respectively for both of the two joints. The red lines below add such
112112
muscles with realistic joint strengths in Newton-meter. For an
113-
explanation of the use of the AnyGeneralMuscle class, please refer to
113+
explanation of the use of the AnyMuscleGeneric class, please refer to
114114
the {doc}`muscle modeling tutorial </Muscle_modeling/intro>`.
115115

116116
```AnyScriptDoc
@@ -120,27 +120,33 @@ AnyKinEqSimpleDriver KneeDriver = {
120120
  AnyRevoluteJoint &Joint = .Knee;
121121
};
122122
§// Hip joint muscles
123-
AnyGeneralMuscle HipFlex = {
124-
  AnyMuscleModel Model = {F0 = 232;};
125-
  ForceDirection = 1;
126-
  AnyRevoluteJoint &Joint = .Hip;
123+
AnyMuscleGeneric HipFlex = {
124+
MuscleModel = &MusMdl;
125+
Type = NonNegative;
126+
AnyRevoluteJoint &Joint = .Hip;
127+
AnyMuscleModel MusMdl = {F0 = 232;};
127128
};
128-
AnyGeneralMuscle HipExtend = {
129-
  AnyMuscleModel Model = {F0 = 251;};
130-
  ForceDirection = -1;
131-
  AnyRevoluteJoint &Joint = .Hip;
129+
130+
AnyMuscleGeneric HipExtend = {
131+
MuscleModel = &MusMdl;
132+
Type = NonPositive;
133+
AnyRevoluteJoint &Joint = .Hip;
134+
AnyMuscleModel MusMdl = {F0 = 251;};
132135
};
133136
134137
// Knee joint muscles
135-
AnyGeneralMuscle KneeExtend = {
136-
  AnyMuscleModel Model = {F0 = 554;};
137-
  ForceDirection = 1;
138-
  AnyRevoluteJoint &Joint = .Knee;
138+
AnyMuscleGeneric KneeExtend = {
139+
MuscleModel = &MusMdl;
140+
Type = NonNegative;
141+
AnyRevoluteJoint &Joint = .Knee;
142+
AnyMuscleModel MusMdl = {F0 = 554;};
139143
};
140-
AnyGeneralMuscle KneeFlex = {
141-
  AnyMuscleModel Model = {F0 = 236;};
142-
  ForceDirection = -1;
143-
  AnyRevoluteJoint &Joint = .Knee;
144+
145+
AnyMuscleGeneric KneeFlex = {
146+
MuscleModel = &MusMdl;
147+
Type = NonPositive;
148+
AnyRevoluteJoint &Joint = .Knee;
149+
AnyMuscleModel MusMdl = {F0 = 236;};
144150
};§
145151
```
146152

@@ -220,7 +226,7 @@ A fast reload and run of the model will show that the movement is
220226
somewhat different now, and plotting the joint rotation velocities will
221227
also show that the initial velocity is now zero for both joints. This is
222228
ensured by using similar values for the first two points in each
223-
interpolation, for instance -30 and -30 degrees in the HipDriver. Now we
229+
interpolation, for instance -30 and -30 degrees in the `HipDriver`. Now we
224230
could generate infinitely many different motions simply by inserting
225231
different angle values into these interpolation drivers. Among them will
226232
be the motion that generates the fastest kick without overloading the
@@ -232,8 +238,8 @@ making these variations.
232238
## The Optimization Problem
233239

234240
We already have some data now that can be used in the definition of our
235-
optimization problem. The first question is: What do we actually want to
236-
optimize? Given that the mass of the foot and football are given in
241+
optimization problem. The first question is: *What do we actually want to
242+
optimize?* Given that the mass of the foot and football are given in
237243
advance we can presume that maximising the velocity of the football
238244
after the impact is equivalent to maximizing the velocity of the foot
239245
before the impact. In fact, the law of conservation of momentum says
@@ -248,21 +254,20 @@ We can write this formula directly into the model like this:
248254
// The study: Operations to be performed on the model
249255
AnyBodyStudy MyStudy = {
250256
   AnyFolder &Model = .MyModel;
251-
   RecruitmentSolver = MinMaxSimplex;
257+
InverseDynamics.Criterion.Type = MR_MinMaxStrict;
252258
   Gravity = {0.0, -9.81, 0.0};
253259
   nStep = 50;
254260
   tEnd = 0.2;
255261
   §AnyOutputFun BallVel= {
256-
     Val =
257-
1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass);
262+
     Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass);
258263
   };§
259264
};
260265
```
261266

262267
&#160;Please load and run the model again, and then go to the Chart window
263268
and plot the new output function. You should see this:
264269

265-
![kickvel1.gif](_static/intro/image3.gif)
270+
![kickvel1](_static/intro/image3.png)
266271

267272
The function shows the predicted post-impact velocity of the ball if the
268273
foot were to hit is at any time during the imposed movement. As
@@ -277,13 +282,12 @@ purpose:
277282
// The study: Operations to be performed on the model
278283
AnyBodyStudy MyStudy = {
279284
   AnyFolder &Model = .MyModel;
280-
   RecruitmentSolver = MinMaxSimplex;
285+
   InverseDynamics.Criterion.Type = MR_MinMaxStrict;
281286
   Gravity = {0.0, -9.81, 0.0};
282287
   nStep = 50;
283288
   tEnd = 0.2;
284289
   AnyOutputFun BallVel= {
285-
     Val =
286-
1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass);
290+
     Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass);
287291
   };
288292
   §AnyOutputFun MaxAct = {
289293
     Val = .MaxMuscleActivity;
@@ -301,7 +305,7 @@ AnyOptStudy OptStudy = {
301305
  MaxIterationStep = 25;
302306
303307
  Analysis = {
304-
    AnyOperation &op = ..MyStudy.InverseDynamicAnalysis;
308+
    AnyOperation &op = ..MyStudy.InverseDynamics;
305309
  };
306310
307311
  // Constraint: All muscle activities below 100%
@@ -320,7 +324,7 @@ AnyOptStudy OptStudy = {
320324

321325
Please copy and paste those lines into the model right after the end of
322326
MyStudy but before the final ending brace of the model. The study
323-
contains two AnyDesMeasures of which the first is the maximum activity
327+
contains two `AnyDesMeasures` of which the first is the maximum activity
324328
minus one. The actual constraint is
325329

326330
max(Activity) \< 100%
@@ -330,7 +334,7 @@ constraints, it is defined on the form
330334

331335
max(Activity) - 1\< 0
332336

333-
The second AnyDesMeasure, KickVel, is defined as minus the maximum of
337+
The second AnyDesMeasure, `KickVel`, is defined as minus the maximum of
334338
the ball velocity. This is because AnyBody's optimizer is set up to
335339
always perform minimization where we want to maximize the velocity. So
336340
we simply minimize the negative velocity instead. The max value is
@@ -373,15 +377,15 @@ with the single variable. Open the OptStudy branch of the tree on the
373377
left hand side of the screen, highlight "Optimization", and click "Run.
374378
After a few moments the process will converge to a better kick. You can
375379
see how much better by going to the Chart view, openeing the OptStudy
376-
section and plotting "Main.OptStudy.Output.KickVel.Val". You will see
380+
section and plotting `Main.OptStudy.Output.KickVel.Val`. You will see
377381
that the optimization decreased the value from about -9 to about -12,
378382
indicating an improvement of the ball velocity from 9 to 12 m/s.
379383

380384
Let us quickly add some more variables:
381385

382386
```AnyScriptDoc
383387
AnyVar slack = 60*pi/180;
384-
AnyDesVar Hip3 = {
388+
§AnyDesVar Hip3 = {
385389
  Val = Main.MyModel.HipDriver.Data[0][2];
386390
  Min = -30*pi/180;
387391
  Max = Val + .slack;
@@ -413,7 +417,7 @@ Running the optimization at this stage will make the problem converge in
413417
a few interations to an optimized ball velocity of a little over 13 m/s.
414418
If we plot the two joint accelerations we get:
415419

416-
![kickacc1.gif](_static/intro/image4.gif)
420+
![kickacc1](_static/intro/image4.png)
417421

418422
The movement shows subtle signs of a whiplash action in the sense that
419423
the movement is initiated by a knee acceleration, which is taken over by

0 commit comments

Comments
 (0)