diff --git a/A_Getting_started/index.md b/A_Getting_started/index.md index fba48943..a9c51332 100644 --- a/A_Getting_started/index.md +++ b/A_Getting_started/index.md @@ -1,10 +1,12 @@ # Getting Started - First steps -The objective of this tutorial is to demonstrate some of the features of -the AnyBody Modeling System using an existing model. +The objective of this tutorial is to demonstrate some of the features of the +AnyBody Modeling System using an existing model. The reader will get an +impression of the system’s capabilities and see a complex musculoskeletal model +in action. -The reader will get an impression of the system’s capabilities and see a -complex musculoskeletal model in action. +Finally, the last lesson will explain some general concepts about simulations +in AnyBody Modeling System. ::::{if-builder:: html ```{rubric} Tutorial content @@ -18,4 +20,5 @@ Introduction lesson1 lesson2 lesson3 +lesson4 ``` diff --git a/A_Getting_started/intro.md b/A_Getting_started/intro.md index 1cfefc0b..f99a58d4 100644 --- a/A_Getting_started/intro.md +++ b/A_Getting_started/intro.md @@ -21,7 +21,7 @@ the model view window This tutorial relies heavily on using the AnyBody Managed Model Repository (AMMR). Follow the steps below to unpack a local version of the AMMR. -# Setup the AMMR +## Setup the AMMR Before you continue, you must unpack the entire repository and save it on your hard disk. To get a copy of the AMMR, press the Demo tab in the AnyBody @@ -34,7 +34,7 @@ your documents folder by default. It is good practice to create a second local copy of the AMMR so that you do not overwrite the original AMMR folder by accident. -# AMMR structure +## AMMR structure Open a file manager and navigate to the directory where you unpacked the repository. You should see a folder structure that includes the following diff --git a/A_Getting_started/lesson4.md b/A_Getting_started/lesson4.md new file mode 100644 index 00000000..851e2134 --- /dev/null +++ b/A_Getting_started/lesson4.md @@ -0,0 +1,203 @@ +::: {rst-class} break +::: + +# Lesson 4: Understanding Simulations + +Now that you have a basic understanding of the AnyBody Modeling System and have +had some hands-on experience, this lesson will give you a deeper understanding +of what studies and operations are - the core components of all simulations in +AnyBody. + +In the AnyBody Modeling System, all types of simulations, whether they are pure +mechanical system analysis, musculoskeletal analysis or design analysis, are +carried out by objects that are referred to as “studies”. Studies have +operations that can be executed to perform the analysis. + +Meaning, studies and operations are the mechanisms used to specify tasks to +be performed on the model. Think of a study as a collector that brings together +a model definition, the operations that execute the model, and the results to be +analyzed afterwards. Meaning, operations are the tasks performed on the model. +They can be executed from the AnyBody interface, generating and storing output +in the study based on the function of the specific operation. + +## Why Do We Need Studies? + +You might wonder why we need studies. After all, couldn’t you just load a model +and have operations readily available in the AnyBody interface? The answer lies +in the flexibility that studies offer. + +Studies are defined as special classes, allowing you to have multiple studies in +the same model. As objects in the model, you can have as many studies as you +need (or as many as your computer can handle), and they don’t necessarily have +to operate on the same model definition, even if they share elements. + +For instance, you might want to perform different operations on the same model, +or perform the same operation on nearly identical models, and then compare the +results. With two studies, you can do this within a single AnyBody model. + +## The Hierarchy of Study Classes + +Studies are derived from a base class called `AnyStudy`, and the operations found +within studies are also defined as classes, all derived from the base class +`AnyOperation`. + +Here's a look at the hierarchy of study classes in AnyBody: + + +- `AnyStudy` (Base class for all studies) + + - `AnyTimeStudy` (Base class for time variation studies) + + - `AnyKinStudy` + + - `AnyMechStudy` + - `AnyBodyStudy` + - `AnyBodyCalibrationStudy` + + - `AnyDesStudy` (design variable studies, see *a separate tutorial*) + + +## Mechanical Studies + +Mechanical studies, derived from `AnyMechStudyBase`, are quite similar, but they +contain different sets of available operations. The base class is empty, with +`AnyKinStudy` extending it with functionality for kinematic analysis. +`AnyMechStudy` further extends this with kinetic (dynamic) analysis of basic +mechanical systems. + +`AnyBodyStudy` is the most frequently used study by AnyBody users, as it extends +the kinematic analysis functions with operations for kinetic (dynamic) analysis +of musculoskeletal systems, which is the core functionality of the AnyBody +Modeling System. It also contains almost all of the operations found in other +mechanical studies. `AnyBodyCalibrationStudy` provides additional functionality +to adjust/calibrate the musculoskeletal models systematically. + +## Understanding the Structure of a Study + +A study in AnyBody is essentially a folder that contains specifications. These +specifications are placed between a pair of braces and become part of the study. +A study has predefined properties that you can set, must set, or cannot modify. + +When you create a new model using `File` -> `New from Template...`, the system +automatically inserts an AnyBodyStudy in the main file. It looks like this: + +```AnyScriptDoc +// The study: Operations to be performed on the model +AnyBodyStudy MyStudy = { + AnyFolder &Model = .MyModel; + Gravity = {0.0, -9.81, 0.0}; +}; +``` + +This study contains all the necessary elements. The first word after +`AnyBodyStudy` defines the name of the study, which in this case is "MyStudy". The +last line `Gravity = {0.0, -9.81, 0.0};` assigns a value to the Gravity +variable, which specifies the gravitational acceleration vector affecting the +model. + +An `AnyBodyStudy` has many more predefined properties that you can modify. You +can view these properties using the Model Tree View, which is attached to the +left of the Main Frame. Double-clicking any object in the Model Tree will show +you properties of the objects in the Object Description dialog box. + +Most of the properties deal with solution methods, tolerances, and other +advanced user features. However, some properties are essential for all users: + +* `tStart`: The time at which the study begins. Usually, this is zero. +* `tEnd`: The time at which the study ends. This often needs to be set by the user. +* `nStep`: Specifies how many steps the system should use to go from tStart to tEnd. + +Let's take a closer look at the first line of the study: + +```AnyScriptDoc +AnyFolder &Model = .MyModel; +``` + +:::{note} +:class: margin +You can choose to point to some subfolders of `MyModel` instead of the entire +model. This means the study would work on just a subset of the model. For +example, you might want to compare two nearly identical models. In this case, +you can put all common parts in one folder and the distinctive parts in separate +folders. Then, you can create two studies that reference the common part and +their respective distinctive parts. +::: + +Here, "AnyFolder" is a type definition. Unlike the predefined properties +discussed above, this line introduces a new property to the study. This is a +key aspect of studies: you can add almost anything to a study, and the study +doesn't need to know its type in advance. + +This line defines a variable called "Model" and assigns it to `.MyModel`. In +this case, `MyModel` is the folder that contains the entire model. The prefix `.` +before `MyModel` indicates that it's one level up from where it's referenced. + +By assigning `MyModel` to the Model variable, the entire model comes under the +influence of the study. The `&` before "Model" means that Model doesn't get +replicated inside the study. Instead, it's a pointer to `MyModel`. If you're +familiar with C, C++, or Java programming, you'll recognize this as the concept +of pointers. If not, think of a pointer as a reference to something defined +elsewhere. When you access it, you're actually interacting with what it points +to. + +## The Standard Operations in a Study + +When you create an `AnyBodyStudy`, it automatically includes three standard +operations in the study tree. These operations represent different actions you +can perform on the model elements that the study points to: + +* `InitialConditions`: This operation reads the values of all drivers + included in the study, and sets the model to match these drivers at the + start time (tStart). Meaning it puts the model in the position it has at + `time=tStart`. The model is first initialized into the positions from + load time, and the kinematics is then solved in a few steps. This is + especially helpful for inspecting the specified initial positions if you're + having issues with the initial configuration of the mechanism. The + `InitialConditions` can only run successfully if all joints and drivers are + fully defined. + + Note, that the the model's positions after running `InitialConditions` + is different from the position after just loading the model, called + the load-time position. + +* `Kinematics`: This operation performs a kinematic analysis, which is a + simulation of the model's movement without calculating any forces. This means + you can run a Kinematics operation as soon as you've uniquely defined the + movement and the model is kinematically determinate. You don't need any + muscles in the model for this operation. + + The data you can extract from the Kinematics study includes positions, + velocities, and accelerations. + +* `InverseDynamics`: This operation simulates the forces involved in the given + movement or posture, along with anything that can be derived from them. The + InverseDynamics operation uses the Kinematics operation as a subroutine, so it + requires a correctly defined movement or posture, as well as the necessary + muscles or motors to drive the model. + This is also known as kinetic or dynamic analysis. + +:::{admonition} Note on InverseDynamics +:class: note +You might think that calculating forces in a rigid body mechanical system is +straightforward. After all, isn’t it just about setting up equilibrium equations +and solving them? Well, it’s a bit more complex than that, especially when it +comes to biomechanics. + +In biomechanics, we often deal with statically indeterminate systems. This means +we don’t have enough equilibrium equations to resolve the forces in the system. +Plus, we have to consider that muscles can only pull, not push. This adds +another layer of complexity to the problem. + +The `AnyBodyStudy` class is designed to handle these complexities. It uses +algorithms that are tailored for musculoskeletal systems. + +There’s also the `AnyMechStudy` class, which contains a simpler InverseDynamics +operation. This operation doesn’t deal with the complexities of musculoskeletal +systems. Instead, it solves the basic inverse dynamics problem for a simple +mechanical system, finding the reaction forces that balance the system. +::: + +When you execute each of these operations, they compile their output in the +Output section under the study tree. This allows you to easily access and +analyze the results of each operation. + diff --git a/A_Getting_started_anyscript/Downloads/demo.arm2d.zip b/A_Getting_started_anyscript/Downloads/demo.arm2d.zip index 95481301..ebf00d3f 100644 Binary files a/A_Getting_started_anyscript/Downloads/demo.arm2d.zip and b/A_Getting_started_anyscript/Downloads/demo.arm2d.zip differ diff --git a/A_Getting_started_anyscript/Downloads/demo.lesson5.any b/A_Getting_started_anyscript/Downloads/demo.lesson5.any index 88dc84d6..9d4917f0 100644 --- a/A_Getting_started_anyscript/Downloads/demo.lesson5.any +++ b/A_Getting_started_anyscript/Downloads/demo.lesson5.any @@ -109,19 +109,18 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; }; // Shoulder driver //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; }; // Elbow driver }; // Driver folder - }; // MyModel // The study: Operations to be performed on the model diff --git a/A_Getting_started_anyscript/Downloads/demo.lesson6.any b/A_Getting_started_anyscript/Downloads/demo.lesson6.any index 6fe4581b..671b50fe 100644 --- a/A_Getting_started_anyscript/Downloads/demo.lesson6.any +++ b/A_Getting_started_anyscript/Downloads/demo.lesson6.any @@ -112,22 +112,20 @@ Main = { AnyFolder Drivers = { //--------------------------------- - - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; Reaction.Type = {Off}; }; // Shoulder driver - //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; Reaction.Type = {Off}; }; // Elbow driver - }; // Driver folder + }; // Driver folder AnyFolder Muscles = { // Simple muscle model with constant strength = 400 Newton diff --git a/A_Getting_started_anyscript/Snippets/lesson4/snip.NewModel.main-1.any b/A_Getting_started_anyscript/Snippets/lesson4/snip.NewModel.main-1.any index 94e1f297..9a2dc524 100644 --- a/A_Getting_started_anyscript/Snippets/lesson4/snip.NewModel.main-1.any +++ b/A_Getting_started_anyscript/Snippets/lesson4/snip.NewModel.main-1.any @@ -110,16 +110,16 @@ Main = { §AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; }; // Shoulder driver //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; }; // Elbow driver }; // Driver folder§ //# END SNIPPET 1 diff --git a/A_Getting_started_anyscript/Snippets/lesson4/snip.NewModel.main-2.any b/A_Getting_started_anyscript/Snippets/lesson4/snip.NewModel.main-2.any index d01f2f1f..93a87d17 100644 --- a/A_Getting_started_anyscript/Snippets/lesson4/snip.NewModel.main-2.any +++ b/A_Getting_started_anyscript/Snippets/lesson4/snip.NewModel.main-2.any @@ -109,20 +109,20 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { //# BEGIN SNIPPET 1 AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; //# END SNIPPET 1 - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; }; // Shoulder driver //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { //# BEGIN SNIPPET 2 AnyRevoluteJoint &Jnt = ..Jnts.Elbow; //# END SNIPPET 2 - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-1.any b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-1.any index 923ef2f3..04ce5900 100644 --- a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-1.any +++ b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-1.any @@ -109,16 +109,16 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; }; // Shoulder driver //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; }; // Elbow driver //# BEGIN SNIPPET 1 }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-2.any b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-2.any index 2615c50a..7bc70f4c 100644 --- a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-2.any +++ b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-2.any @@ -109,16 +109,16 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; }; // Shoulder driver //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; }; // Elbow driver }; // Driver folder //# BEGIN SNIPPET 1 diff --git a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-3.any b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-3.any index a8be1858..9d07c0a0 100644 --- a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-3.any +++ b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-3.any @@ -109,16 +109,16 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; }; // Shoulder driver //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-4.any b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-4.any index ad13a7b1..8306fe34 100644 --- a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-4.any +++ b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-4.any @@ -109,16 +109,16 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; }; // Shoulder driver //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-5.any b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-5.any index 0870b638..2e7fee85 100644 --- a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-5.any +++ b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-5.any @@ -109,16 +109,16 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; }; // Shoulder driver //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-6.any b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-6.any index 3bae9655..4bf473c3 100644 --- a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-6.any +++ b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-6.any @@ -87,7 +87,12 @@ Main = { sRel = {-0.25,0,-0.05}; }; AnyDrawSeg DrwSeg = {}; - }; // ForeArm +//# BEGIN SNIPPET 2 + AnyRefNode PalmNode = { + sRel = {0.27,0,0}; + }; +}; // ForeArm +//# END SNIPPET 2 }; // Segs folder @@ -110,18 +115,18 @@ Main = { AnyFolder Drivers = { //--------------------------------- //# BEGIN SNIPPET 1 - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; §Reaction.Type = {Off};§ }; // Shoulder driver - + //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; §Reaction.Type = {Off};§ }; // Elbow driver }; // Driver folder @@ -197,7 +202,17 @@ Main = { AnyDrawMuscle DrwMus = {}; }; }; // Muscles folder - }; // MyModel + +//# BEGIN SNIPPET 3 + §AnyFolder Loads = { + //--------------------------------- + AnyForce3D Dumbbell = { + AnyRefNode &PalmNode = ..Segs.ForeArm.PalmNode; + F = {0,-100,0}; // Force in Newton + }; + }; // Loads folder§ +}; // MyModel +//# END SNIPPET 3 // The study: Operations to be performed on the model AnyBodyStudy ArmStudy = { diff --git a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-7.any b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-7.any index cc673d36..dad331a9 100644 --- a/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-7.any +++ b/A_Getting_started_anyscript/Snippets/lesson5/snip.NewModel.main-7.any @@ -87,12 +87,7 @@ Main = { sRel = {-0.25,0,-0.05}; }; AnyDrawSeg DrwSeg = {}; -//# BEGIN SNIPPET 1 - AnyRefNode PalmNode = { - sRel = {0.27,0,0}; - }; -}; // ForeArm -//# END SNIPPET 1 + }; // ForeArm }; // Segs folder @@ -111,26 +106,23 @@ Main = { AnyRefNode &ForeArmNode = Main.ArmModel.Segs.ForeArm.ElbowNode; }; // Elbow joint }; // Jnts folder +//# BEGIN SNIPPET 1 +AnyFolder Drivers = { + //--------------------------------- + §AnyKinMotion§ ShoulderMotion = { + AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; + }; // Shoulder driver - AnyFolder Drivers = { - //--------------------------------- - - AnyKinEqSimpleDriver ShoulderMotion = { - AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; - Reaction.Type = {Off}; - }; // Shoulder driver - - //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { - AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; - Reaction.Type = {Off}; - }; // Elbow driver - }; // Driver folder - + //--------------------------------- + §AnyKinMotion§ ElbowMotion = { + AnyRevoluteJoint &Jnt = ..Jnts.Elbow; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; + }; // Elbow driver +}; // Driver folder +//# END SNIPPET 1 AnyFolder Muscles = { // Simple muscle model with constant strength = 400 Newton AnyMuscleModel MusMdl = { @@ -201,18 +193,9 @@ Main = { AnyDrawMuscle DrwMus = {}; }; }; // Muscles folder + }; // MyModel -//# BEGIN SNIPPET 2 - §AnyFolder Loads = { - //--------------------------------- - AnyForce3D Dumbbell = { - AnyRefNode &PalmNode = ..Segs.ForeArm.PalmNode; - F = {0,-100,0}; // Force in Newton - }; - }; // Loads folder§ -}; // MyModel -//# END SNIPPET 2 - + // The study: Operations to be performed on the model AnyBodyStudy ArmStudy = { AnyFolder &Model = .ArmModel; diff --git a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-1.any b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-1.any index 389bb850..90462e62 100644 --- a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-1.any +++ b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-1.any @@ -118,18 +118,18 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; Reaction.Type = {Off}; }; // Shoulder driver - + //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; Reaction.Type = {Off}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-2.any b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-2.any index 1124009c..e1b8f7ba 100644 --- a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-2.any +++ b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-2.any @@ -119,18 +119,18 @@ AnyDrawSTL DrwSTL = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; Reaction.Type = {Off}; }; // Shoulder driver - + //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; Reaction.Type = {Off}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-3.any b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-3.any index 55cb78cd..2f97b794 100644 --- a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-3.any +++ b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-3.any @@ -120,18 +120,18 @@ Main = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; Reaction.Type = {Off}; }; // Shoulder driver - + //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; Reaction.Type = {Off}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-4.any b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-4.any index d5e2f0de..8cffe241 100644 --- a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-4.any +++ b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-4.any @@ -121,18 +121,18 @@ AnyRefNode PalmNode = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; Reaction.Type = {Off}; }; // Shoulder driver - + //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; Reaction.Type = {Off}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-5.any b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-5.any index d9696803..f5298f01 100644 --- a/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-5.any +++ b/A_Getting_started_anyscript/Snippets/lesson6/snip.NewModel.main-5.any @@ -122,18 +122,18 @@ AnyDrawSTL DrwSTL = { AnyFolder Drivers = { //--------------------------------- - AnyKinEqSimpleDriver ShoulderMotion = { + AnyKinDriver ShoulderMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; - DriverPos = {-100*pi/180}; - DriverVel = {30*pi/180}; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; Reaction.Type = {Off}; }; // Shoulder driver - + //--------------------------------- - AnyKinEqSimpleDriver ElbowMotion = { + AnyKinDriver ElbowMotion = { AnyRevoluteJoint &Jnt = ..Jnts.Elbow; - DriverPos = {90*pi/180}; - DriverVel = {45*pi/180}; + DriverPos0 = {90*pi/180}; + DriverVel0 = {45*pi/180}; Reaction.Type = {Off}; }; // Elbow driver }; // Driver folder diff --git a/A_Getting_started_anyscript/_static/lesson4/image6.png b/A_Getting_started_anyscript/_static/lesson4/image6.png index c9594d28..d98b9b91 100644 Binary files a/A_Getting_started_anyscript/_static/lesson4/image6.png and b/A_Getting_started_anyscript/_static/lesson4/image6.png differ diff --git a/A_Getting_started_anyscript/index.md b/A_Getting_started_anyscript/index.md index 7d540022..8285ac7c 100644 --- a/A_Getting_started_anyscript/index.md +++ b/A_Getting_started_anyscript/index.md @@ -1,6 +1,7 @@ ::: {rst-class} break ::: +(How_to_write_AnyScript)= # How to write AnyScript This tutorial introduces the AnyScript modeling language, which is used diff --git a/A_Getting_started_anyscript/lesson4.md b/A_Getting_started_anyscript/lesson4.md index 2fd98a43..8ee61711 100644 --- a/A_Getting_started_anyscript/lesson4.md +++ b/A_Getting_started_anyscript/lesson4.md @@ -28,20 +28,26 @@ the values of muscle forces which produce the motion. ## Measures & drivers -We need to specify the motion for two degrees of freedom (DOF) of our arm mechanism, because it has hinge joints at the -shoulder and at the elbow. +We need to specify the motion for two degrees of freedom (DOF) of our arm +mechanism, because it has hinge joints at the shoulder and at the elbow. -- **Measures** are AnyBody objects which literally measure the value of a user-specified DOF within the model. -- **Drivers** are AnyBody objects which constrain the value of a measure to a constant value or a mathematical function of time. Drivers essentially assemble and impart motion to your mechanisms. +- **Measures** are AnyBody objects which literally measure the value of a + user-specified DOF within the model. +- **Drivers** are AnyBody objects which constrain the value of a measure to a + constant value or a mathematical function of time. Drivers essentially + assemble and impart motion to your mechanisms. -In this model, we therefore need two drivers, to specify motions for the two DOF. We therefore also need two measures, -which we will chose to be measures of the shoulder and elbow joint angle values. +In this model, we therefore need two drivers, to specify motions for the two +DOF. We therefore also need two measures, which we will chose to be measures of +the shoulder and elbow joint angle values. :::{note} -**It is only important that the constrained measures represent independent DOFs of the model. The exact measures themselves are your choice**. +It is only important that the constrained measures represent independent DOFs +of the model. The exact measures themselves are your choice -Eg: For this arm model with 2 remaining DOFs, we can either apply motion drivers to the shoulder (1 DOF) and elbow joints (+1 DOF) OR the X (1 DOF) and Y (+1 DOF) coordinates -of the end-point of the ForeArm segment (the wrist). +Eg: For this arm model with 2 remaining DOFs, we can either apply motion drivers +to the shoulder (1 DOF) and elbow joints (+1 DOF) OR the X (1 DOF) and Y (+1 +DOF) coordinates of the end-point of the ForeArm segment (the wrist). Creating more than 2 driver constraints will over-constrain the model and lead to errors. ::: @@ -58,19 +64,24 @@ Let's create a new folder and define two drivers: :end-before: //# END SNIPPET 1 ``` -The folder contains two objects named `ShoulderMotion` and `ElbowMotion`, belonging to the -`AnyKinEqSimpleDriver` class. +The folder contains two objects named `ShoulderMotion` and `ElbowMotion`, +belonging to the `AnyKinDriver ` class. -**All AnyBody drivers only work on the measures that are supplied to them. The** `AnyKinEqSimpleDriver` **class used in this case, constrains -the supplied measure's positions to a given value at time = 0 (`DriverPos`) and changes this position at constant velocity thereon (`DriverVel`).** +**All AnyBody drivers only work on the measures that are supplied to them**. The +`AnyKinDriver ` class used in this case, constrains the supplied +measure's positions to a given value at time = 0 (`DriverPos0`) and changes this +position at constant velocity thereon (`DriverVel0`). -Since the measures supplied to the above drivers are rotational joints, the drivers produce joint rotation. -But the same driver class could be used to drive translations, for instance a sliding joint. +Since the measures supplied to the above drivers are rotational joints, the +drivers produce joint rotation. But the same driver class could be used to drive +translations, for instance a sliding joint. -The following lines assign the shoulder and elbow joint angle measures to the respective drivers. -Standard AnyBody joints created using classes such as `AnyRevoluteJoint`, `AnySphericalJoint` etc. automatically function as measures. -More customized measures can be created using classes such as `AnyKinLinear`, `AnyKinRotational` etc. -(see {doc}`this lesson <../The_mechanical_elements/lesson4>`).: +The following lines assign the shoulder and elbow joint angle measures to the +respective drivers. Standard AnyBody joints created using classes such as +`AnyRevoluteJoint`, `AnySphericalJoint` etc. automatically function as measures. +More customized measures can be created using classes such as `AnyKinLinear`, +`AnyKinRotational` etc. (see +{doc}`this lesson<../The_mechanical_elements/lesson4>`).: ```{literalinclude} Snippets/lesson4/snip.NewModel.main-2.any :language: AnyScriptDoc @@ -86,40 +97,45 @@ and :end-before: //# END SNIPPET 2 ``` -Since the measures constrained by these drivers are angles, the units -of `DriverPos` and `DriverVel` are radians and radians/sec respectively. +Since the measures constrained by these drivers are angles, the units of +`DriverPos0` and `DriverVel0` are radians and radians/sec respectively. -Just like in {ref}`Lesson 3 `, these lines also -use the reference operator `&` to point the local variable `Jnt` towards the -actual shoulder/elbow joint objects existing in a different folder +Just like in {ref}`Lesson 3 `, these lines also use the +reference operator `&` to point the local variable `Jnt` towards the actual +shoulder/elbow joint objects existing in a different folder -Since `Jnt` is a reference, it will automatically update as the joint angles change during motion. +Since `Jnt` is a reference, it will automatically update as the joint angles +change during motion. ## Running a kinematic simulation -Re-load the model by hitting F7, and you should see the message "Loaded successfully" with NO -warning messages about the lack of kinematic constraints. You're now ready to get this model moving. +Re-load the model by hitting F7, and you should see the message "Loaded +successfully" with NO warning messages about the lack of kinematic constraints. +You're now ready to get this model moving. :::{note} -The object named "ArmModelStudy" (of `AnyBodyStudy` class) creates simulations to run your model through. "ArmModelStudy" -contains a reference object (created with a `&`) pointing to the "ArmModel" folder. +The object named "ArmModelStudy" (of `AnyBodyStudy` class) creates simulations +to run your model through. "ArmModelStudy" contains a reference object (created +with a `&`) pointing to the "ArmModel" folder. -This allows you to create -multiple `AnyBodyStudy` objects, each of which contains a reference to same mechanical model, and a second reference object pointing to a folder with motion drivers, -that are specific to that study. +This allows you to create multiple `AnyBodyStudy` objects, each of which +contains a reference to same mechanical model, and a second reference object +pointing to a folder with motion drivers, that are specific to that study. ::: -**You must now run the "Main.ArmModelStudy.Kinematics" operation. If you need to refer back to how this is done, look at** -{ref}`this prior tutorial `. +You must now run the **"Main.ArmStudy.Kinematics"** operation. If you need to +refer back to how this is done, look at +{ref}`this prior tutorial`. -Since we have no muscles so far, a kinematic analysis is really all that -makes sense. With a kinematic analysis, you can investigate positions, velocities, and -accelerations. But force, power, energy or other such things are not computed. These properties are calculated by the -"InverseDynamics" study. +Since we have no muscles so far, a kinematic analysis is really all that makes +sense. With a kinematic analysis, you can investigate positions, velocities, and +accelerations. But force, power, energy or other such things are not computed. +These properties are calculated by the "InverseDynamics" study. ## Replaying a simulation -While the analysis is running, you can see the model move in the Model View window. +While the analysis is running, you can see the model move in the Model View +window. When the analysis in finished, you can use the replay panel to replay the motion as you would in a movie player. @@ -132,32 +148,42 @@ the motion as you would in a movie player. ## Viewing simulation outputs -If you look at the "ArmModelStudy" object in the AnyScript window, start/end times and the -number of simulation steps (time frames) are not specified. These are actually optional parameters -when using the `AnyBodyStudy` class, which by default creates an analysis of 100 steps and spanning 1 second. +If you look at the "ArmStudy" object in the AnyScript window, start/end +times and the number of simulation steps (time frames) are not specified. These +are actually optional parameters when using the `AnyBodyStudy` class, which by +default creates an analysis of 100 steps and spanning 1 second. -**To view the output variables of the study that was run, open the "ArmModelStudy" folder in the model tree and expand the "Output" folder.** +**To view the output variables of the study that was run, open the "ArmStudy"** +**folder in the model tree and expand the "Output" folder.** -Since the "ArmModelStudy" contained a reference object ("Model") pointing to the "ArmModel" folder, the "Output" -folder contains the instantaneous values of all the time varying variables (including variables in sub-folders) within "ArmModel". +Since the "ArmStudy" contained a reference object ("Model") pointing to the +"ArmModel" folder, the "Output" folder contains the instantaneous values of all +the time varying variables (including variables in sub-folders) within +"ArmModel". -In "ArmModelStudy.Output.Model.Segs.ForeArm" in the model tree, you find all the nodes on the segment. Within the "HandNode" -sub-folder, you will find {literal}`r` - the position vector of the node. Clicking on {literal}`r` -shows the hand position vector (w.r.t global) for each time instant in the Information Window. +In `ArmStudy.Output.Model.Segs.ForeArm` in the model tree, you find all the +nodes on the segment. Within the "HandNode" sub-folder, you will find +{literal}`r` - the position vector of the node. Clicking on {literal}`r` shows +the hand position vector (w.r.t global) for each time instant in the Information +Window. ## Plotting simulation results :::{note} -The chart view contains a filtered down version of the model tree, which only displays "AnyBodyStudy" objects. This -tree can also be used for plotting purposes. +The chart view contains a filtered down version of the model tree, which only +displays "AnyBodyStudy" objects. This tree can also be used for plotting +purposes. ::: -Let us say, you want to plot the position vector of the hand node over the course of movement. +Let us say, you want to plot the position vector of the hand node over the +course of movement. -You need to find and plot the variable ".....ForeArm.HandNode.r" in the chart view. If you need help with the chart view, -refer to {ref}`this prior tutorial on plotting `. +You need to find and plot the variable `.....ForeArm.HandNode.r` in the chart +view. If you need help with the chart view, refer to +{ref}`this prior tutorial on plotting `. -If you're having trouble finding the correct output variable in the chart view's filtered model tree, refer to the figure below. +If you're having trouble finding the correct output variable in the chart view's +filtered model tree, refer to the figure below. ```{image} _static/lesson4/image6.png :alt: Chart hand movement diff --git a/A_Getting_started_anyscript/lesson5.md b/A_Getting_started_anyscript/lesson5.md index 82cce10b..baeb2b38 100644 --- a/A_Getting_started_anyscript/lesson5.md +++ b/A_Getting_started_anyscript/lesson5.md @@ -11,19 +11,22 @@ previous lesson: {download}`demo.lesson5.any `. The model so far has been capable of motion despite lacking muscles. This is because a kinematic analysis that does not consider forces. -Skeletal muscles produce movement by pulling on our bones. Muscle actions -are coordinated in complicated patterns determined by our central nervous system. +Skeletal muscles produce movement by pulling on our bones. Muscle actions are +coordinated in complicated patterns determined by our central nervous system. -**AnyBody helps you predict realistic muscle activation patterns for a given movement and external load.** +AnyBody helps you predict realistic muscle activation patterns for a given +movement and external load. ## Creating a muscle model The exact behaviour of muscle tissue is a widely researched (and debated) topic. -AnyBody offers several models of varying sophistication, for modelling muscle behaviour. A detailed introduction -to muscle modeling can be found here {doc}`its own tutorial <../Muscle_modeling/intro>`. +AnyBody offers several models of varying sophistication, for modelling muscle +behaviour. A detailed introduction to muscle modeling can be found here +{doc}`its own tutorial <../Muscle_modeling/intro>`. -Here, we will create a very simple muscle model and use it to model our arm model muscles. We start by creating a folder for the muscles: +Here, we will create a very simple muscle model and use it to model our arm +model muscles. We start by creating a folder for the muscles: ```{literalinclude} Snippets/lesson5/snip.NewModel.main-1.any :language: AnyScriptDoc @@ -31,7 +34,8 @@ Here, we will create a very simple muscle model and use it to model our arm mode :end-before: //# END SNIPPET 1 ``` -The next step is to create a muscle model that defines the properties that will be assumed common for all the muscles. +The next step is to create a muscle model that defines the properties that will +be assumed common for all the muscles. :::{note} Since properties such as Max muscle strength, fiber length etc. differ between muscles, realistic AMMR human body models @@ -135,23 +139,29 @@ a gravity vector in the "ArmModelStudy" object. :::{note} :class: margin A kinematic constraint needs to be enforced by an accompanying constraint force. -For example, when you lean on a table, the normal reaction force on your hand maintains the -surface-surface constraint between hand and table. Were it not for the force you would have fallen, with your hand -passing through the table surface. Similarly motion constraints such as joint angle motions need a driving +For example, when you lean on a table, the normal reaction force on your hand +maintains the surface-surface constraint between hand and table. Were it not for +the force you would have fallen, with your hand passing through the table +surface. Similarly motion constraints such as joint angle motions need a driving force to maintain the specified trajectory. ::: -By default, all drivers in your model apply the necessary constraint forces (also called driver reactions) for their respective kinematic constraints. +By default, all drivers in your model apply the necessary constraint forces +(also called driver reactions) for their respective kinematic constraints. -**The constraint "force" is actually a generalized force i.e. whether it is actually a force or torque -depends on the type of measure that a driver constrains.** For example, a driver on a rotational measure, will apply torques, while one on -a linear measure will apply forces. AnyBody reports all of these simply as "forces", and it is up to you to interpret them. +The constraint "force" is actually a **generalized force** i.e. whether it is +actually a force or torque depends on the type of measure that driver +constrains. For example, a driver on a rotational measure, will apply torques, +while one on a linear measure will apply forces. AnyBody reports all of these +simply as "forces", and it is up to you to interpret them. -**The drivers for shoulder and elbow motion thus default to applying the required constraint reaction torques to sustain the joint motions.** -This is problematic, since we wish the muscles forces to be causing the motion instead. - -**👉 Now** The default driver reactions must therefore be switched off by setting the "Reaction.Type" property. +The drivers for shoulder and elbow motion thus default to applying the +**required constraint reaction torques to sustain the joint motions**. This is +problematic, since we wish the muscles forces to be causing the motion instead. +**👉 Now** The default driver reactions must therefore be switched off by +setting the "Reaction.Type" property, for the muscles to cause the motion and +not the drivers. ```{literalinclude} Snippets/lesson5/snip.NewModel.main-6.any :language: AnyScriptDoc @@ -159,13 +169,81 @@ This is problematic, since we wish the muscles forces to be causing the motion i :end-before: //# END SNIPPET 1 ``` -On the other hand, the driver reactions come in handy in models under development, while you are still adding -muscles or other force elements to enforce the constraints. The driver reactions will allow you to successfully run -inverse dynamic simulations at the intermediate model stages, by ensuring dynamic consistency. +On the other hand, the driver reactions come in handy in models under +development, while you are still adding muscles or other force elements to +enforce the constraints. The driver reactions will allow you to successfully run +inverse dynamic simulations at the intermediate model stages, by ensuring +dynamic consistency. + +The single `Off` is encapsulated in braces, `{Off}`, because it is a vector. A +driver can theoretically have any number of total DOF from all the measures that +it drives. Therefore all data in a driver are vector quantities, even when it is +a 1 DOF driver. + +(AnyKinMotion)= +### An Alternative Driver - AnyKinMotion + +As an alternative to the `AnyKinDriver` class and setting the +`Reaction.Type={Off}`, you can also use the `AnyKinMotion` class. This other +driver is basically identical to the general `AnyKinDriver`, except that all +constraint reaction forces are by default switched off. This implies that this driver only +specifies motion but not a mechanical actuator that produces the motion. In +contrast, AnyKinDriver has reaction forces switched on by default, implying +that the object is an “infinitely strong” mechanical actuator that will produce +the motion no matter the external loads. + +In the following studies, try using both drivers, to see that they generate the +same result. Make the following changes to use the `AnyKinMotion` driver (note, +the line defining the `Reaction.Type` is not needed): + +```{literalinclude} Snippets/lesson5/snip.NewModel.main-7.any +:language: AnyScriptDoc +:start-after: //# BEGIN SNIPPET 1 +:end-before: //# END SNIPPET 1 +``` + +Another important option for both of the drivers, is that you can define a +**driver function** - meaning the function for the movement of the driver. This is +done by defining a time-dependent function for the `AnyParamFun` option. +`AnyParamFun` is the base class for parameter functions that are functions of a +single scalar (floating point) quantity. + +AnyBody contains a number of predefined function types that you can find in the +Classes Tree or in the Reference Manual, for instance `AnyFunPolynomial`. As the +name indicates, this is polynomial driver function: + +```AnyScriptDoc +AnyKinMotion ShoulderMotion = { + AnyRevoluteJoint &Jnt = ..Jnts.Shoulder; + DriverPos0 = {-100*pi/180}; + DriverVel0 = {30*pi/180}; + §AnyFunPolynomial DriverFun = { + PolyCoef = {{0, 1, -0.9}}; + };§ +}; +``` + +In the matrix `PolyCoef`, each row contains the coefficients for a time +function driving one degree of freedom. The revolute joint we are +driving only has one degree of freedom, so the matrix only has one row, +but it still has to be defined as a matrix rather than a vector, i.e. +with double braces at each end. The polynomial coefficients then come in +increasing order and define the following driver function: + +$$ +\textrm{Joint angle} = 0 + 1t - 0.9t^2 \textrm{[rad]} +$$ + +To get higher polynomial orders, simply add more terms to the vector. A common +use is to drive motion either in a very standardized way, for instance with +constant velocity or constant acceleration, or to drive a motion by data to +which a polynomial has been fitted. -The single `Off` is encapsulated in braces, `{Off}` because it is a vector. -A driver can theoretically have any number of total DOF from all the measures -that it drives. Therefore all data in a driver are vector quantities, even when it is a 1 DOF driver . +:::{note} +In the following, **we will NOT use any driver function**, but simply the default +option. So, do not insert the above defined `AnyFunPolynomial DriverFun`. +Furthermore, it is optional to use either the `AnyKinMotion` or the `AnyKinDriver` class. +::: ## The InverseDynamicAnalysis and plotting muscle forces @@ -175,8 +253,9 @@ In this analysis, the AnyBody system computes all muscle, joint forces and much Review the instructions from {ref}`this prior tutorial ` on plotting simulation results. To plot the muscle forces in the brachialis muscle, open -"Main.Study.Output.Model.Muscles.Brachialis" in the chart view's model tree, and plot the variable named `Fm`. -You should get a curve that looks like the one below. +`Main.Study.Output.Model.Muscles.Brachialis` in the chart view's model tree, and +plot the variable named `Fm`. You should get a curve that looks like the one +below. ```{image} _static/lesson5/image3.png :alt: Brachialis muscle force @@ -184,8 +263,9 @@ You should get a curve that looks like the one below. :align: center ``` -The drop in muscle force with movement progression is due to the decreasing moment arm of the -gravity vector about the elbow joint, as the elbow flexes. Therefore lesser the muscle force. +The drop in muscle force with movement progression is due to the decreasing +moment arm of the gravity vector about the elbow joint, as the elbow flexes. +Therefore lesser the muscle force. If you look at the muscle force in the BicepsLong, you see a different pattern: @@ -195,35 +275,38 @@ If you look at the muscle force in the BicepsLong, you see a different pattern: :align: center ``` -This muscle's force increases during the movement because this muscle supports both, the shoulder and the -elbow. In addition, it collaborates both with DeltoidusA on shoulder -flexion, and with the other elbow flexors, and all these muscles have to -adjust their work in relation to each other. +This muscle's force increases during the movement because this muscle supports +both, the shoulder and the elbow. In addition, it collaborates both with +DeltoidusA on shoulder flexion, and with the other elbow flexors, and all these +muscles have to adjust their work in relation to each other. ## Creating external loads -You may want to investigate the model's behavior in different loading situations, such as when the hand -is carrying a dumbbell. Let us imagine that the model is performing a dumbbell curl. +You may want to investigate the model's behavior in different loading +situations, such as when the hand is carrying a dumbbell. Let us imagine that +the model is performing a dumbbell curl. -We start by creating a node on the forearm at the location of the palm. Add this within the curly braces of the "ForeArm" object: +We start by creating a node on the forearm at the location of the palm. Add this +within the curly braces of the "ForeArm" object: -```{literalinclude} Snippets/lesson5/snip.NewModel.main-7.any +```{literalinclude} Snippets/lesson5/snip.NewModel.main-6.any :language: AnyScriptDoc -:start-after: //# BEGIN SNIPPET 1 -:end-before: //# END SNIPPET 1 +:start-after: //# BEGIN SNIPPET 2 +:end-before: //# END SNIPPET 2 ``` -The next step is to add an external force. We make a new sub-folder for this purpose, within ArmModel: +The next step is to add an external force. We make a new sub-folder for this +purpose, within ArmModel: -```{literalinclude} Snippets/lesson5/snip.NewModel.main-7.any +```{literalinclude} Snippets/lesson5/snip.NewModel.main-6.any :language: AnyScriptDoc -:start-after: //# BEGIN SNIPPET 2 -:end-before: //# END SNIPPET 2 +:start-after: //# BEGIN SNIPPET 3 +:end-before: //# END SNIPPET 3 ``` -Now you can reload the model and re-run inverse dynamics to analyze how the model reacts -to a downward force of 100 N (approximately 10 kg dumbbell weight). The BicepsLong force again, you -should see this: +Now you can reload the model and re-run inverse dynamics to analyze how the +model reacts to a downward force of 100 N (approximately 10 kg dumbbell weight). +The BicepsLong force again, you should see this: ```{image} _static/lesson5/image5.png :alt: Biceps long with added force @@ -233,9 +316,9 @@ should see this: :::{note} :class: margin -Applied forces do not have to be constant. They can change with time -and other properties in the model. Please refer to the {doc}`tutorial on forces <../The_mechanical_elements/intro>` for more -details. +Applied forces do not have to be constant. They can change with time and other +properties in the model. Please refer to the +{doc}`tutorial on forces<../The_mechanical_elements/intro>` for more details. ::: The muscle force is obviously much larger than before, and the @@ -244,7 +327,7 @@ movement and drops off again. **The model you've built here was anatomically simplified, and it can be a difficult job to define a realistic body model from scratch. We recommend that users -start out with the body models available in the** [AnyBody Managed Model -Repository](https://www.anybodytech.com/software/ammr/). +start out with the body models available in the** +[AnyBody Managed Model Repository](https://www.anybodytech.com/software/ammr/). Now, let's continue to {doc}`Lesson 6: Adding real bone geometrics `. \ No newline at end of file diff --git a/A_Getting_started_anyscript/lesson6.md b/A_Getting_started_anyscript/lesson6.md index 048654e6..540508e1 100644 --- a/A_Getting_started_anyscript/lesson6.md +++ b/A_Getting_started_anyscript/lesson6.md @@ -10,32 +10,32 @@ previous lesson: {download}`demo.lesson6.any `. So far, the model graphically resembles a "stick figure representation". However, realistic bone geometries can improve both aesthetics and -visual comprehension of a model's anatomy, as illustrated -by the two pictures below. - -![oldleg1](_static/lesson6/image1.jpeg) ![oldleg2](_static/lesson6/image2.jpeg) +visual comprehension of a model's anatomy. ## File formats for visualization objects -3-D geometric models for model components such as bones can be specified using files -of the STL ASCII format. +3-D geometric models for model components such as bones can be specified using +files of the STL ASCII format. STL is a very simple graphical file format that represents object surfaces as -triangles. Virtually all CAD systems can export an object in the STL format. So if your files are in the IGES, -STEP, DXF, etc. formats, load them in your favorite CAD system and convert to STL. +triangles. Virtually all CAD systems can export an object in the STL format. So +if your files are in the IGES, STEP, DXF, etc. formats, load them in your +favorite CAD system and convert to STL. -STL files come in two varieties: ASCII and binary. AnyBody needs an ASCII file, so please make sure to choose that -option during the export process. +STL files come in two varieties: ASCII and binary. AnyBody needs an ASCII file, +so please make sure to choose that option during the export process. ## Importing an STL file -Since the bone models shown in the above tutorial may be a bit too elaborate for a -basic tutorial, we will demonstrate this by adding an STL file for the dumbbell in the arm model. +Since the bone models shown in the above tutorial may be a bit too elaborate for +a basic tutorial, we will demonstrate this by adding an STL file for the +dumbbell in the arm model. Download the dumbbell model {download}`here `. -The dumbbell STL should be added to the forearm, so add the following code - which imports the STL -file into AnyBody - within the "ArmModel.Segs.ForeArm" object: +The dumbbell STL should be added to the forearm, so add the following code - +which imports the STL file into AnyBody - within the "ArmModel.Segs.ForeArm" +object: :::{important} The STL file must be saved in the same folder as the AnyBody script. @@ -49,9 +49,10 @@ The STL file must be saved in the same folder as the AnyBody script. Re-loading the model will result in a fully gray model view. -This is because the STL file's units was millimeters, whereas the arm model -is in meters. This means the dumbbell's STL swallowed up the entire arm model in the model view. -We will therefore scale the dumbbell model down a 1000 times, in the following way: +This is because the STL file's units was millimeters, whereas the arm model is +in meters. This means the dumbbell's STL swallowed up the entire arm model in +the model view. We will therefore scale the dumbbell model down a 1000 times, in +the following way: ```{literalinclude} Snippets/lesson6/snip.NewModel.main-2.any :language: AnyScriptDoc @@ -59,8 +60,9 @@ We will therefore scale the dumbbell model down a 1000 times, in the following w :end-before: //# END SNIPPET 1 ``` -Post re-loading, your model should resemble the figure below.The dumbbell is visible now and has the right size, but -it is sitting at the center of mass of the lower arm rather than at the hand, and is not oriented correctly. +Post re-loading, your model should resemble the figure below.The dumbbell is +visible now and has the right size, but it is sitting at the center of mass of +the lower arm rather than at the hand, and is not oriented correctly. ```{image} _static/lesson6/image3.jpeg :alt: Dumbbell inserted @@ -70,12 +72,13 @@ it is sitting at the center of mass of the lower arm rather than at the hand, an ## Relocating your STL object -When you attach something to a segment, it is by default positioned -at the segment's origin which is also its center of mass. (This was discussed earlier {ref}`over here `) +When you attach something to a segment, it is by default positioned at the +segment's origin which is also its center of mass. (This was discussed earlier +{ref}`over here `) -Therfore moving the dumbbell to the hand is as simple as relocating the "DrwSTL" object -from the "ForeArm" folder to the "PalmNode" subfolder. Cut-paste the entire code for the -"DrwSTL" folder into "PalmNode", as shown below: +Therfore moving the dumbbell to the hand is as simple as relocating the "DrwSTL" +object from the "ForeArm" folder to the "PalmNode" subfolder. Cut-paste the +entire code for the "DrwSTL" folder into "PalmNode", as shown below: ```{literalinclude} Snippets/lesson6/snip.NewModel.main-3.any :language: AnyScriptDoc @@ -83,8 +86,8 @@ from the "ForeArm" folder to the "PalmNode" subfolder. Cut-paste the entire code :end-before: //# END SNIPPET 1 ``` -Upon reloading, we see that the dumbbell attached to the -right location, but is still not oriented correctly. +Upon reloading, we see that the dumbbell attached to the right location, but is +still not oriented correctly. ```{image} _static/lesson6/image4.jpeg :alt: Dumbbell attached at Palm @@ -94,14 +97,16 @@ right location, but is still not oriented correctly. ## Reorienting your STL object -:::{note} -You can visualize a node's local reference system, by selecting the node in the model tree -(e.g., "Main.ArmModel.Segs.ForeArm.PalmNode") and right-clicking and selecting "Model View->This object->View". +:::{note} +You can visualize a node's local reference system, by selecting the +node in the model tree (e.g., "Main.ArmModel.Segs.ForeArm.PalmNode") and +right-clicking and selecting "Model View->This object->View". ::: -An STL (or other geometrical) object's axes are always oriented parallel to the local coordinate system it is attached to. -By visualizing the palm node's local reference system, you will realize that the dumbbell needs to be rotated 90 degrees -about the local Y-axis. +An STL (or other geometrical) object's axes are always oriented parallel to the +local coordinate system it is attached to. By visualizing the palm node's local +reference system, you will realize that the dumbbell needs to be rotated 90 +degrees about the local Y-axis. To rotate the dumbbell by 90 degrees around the Y-axis, adjust the orientation of the `PalmNode`, where the dumbbell is attached. The `sRel` vector specifies @@ -118,7 +123,8 @@ You can use the `RotMat` function to generate the 3x3 rotation matrix: :end-before: //# END SNIPPET 1 ``` -The dumbbell's color can be changed adding the property RGB to the STL file reference: +The dumbbell's color can be changed adding the property RGB to the STL file +reference: ```{literalinclude} Snippets/lesson6/snip.NewModel.main-5.any :language: AnyScriptDoc @@ -126,7 +132,8 @@ The dumbbell's color can be changed adding the property RGB to the STL file refe :end-before: //# END SNIPPET 1 ``` -The RGB property specifies the blend of colors Red, Green, and Blue on a normalized scale of 0 to 1. +The RGB property specifies the blend of colors Red, Green, and Blue on a +normalized scale of 0 to 1. ```{image} _static/lesson6/image5.jpeg :alt: Final dumbbell placement @@ -134,5 +141,5 @@ The RGB property specifies the blend of colors Red, Green, and Blue on a normali :align: center ``` -This completes the Getting Started with AnyScript tutorial. The final -result of your efforts is in {download}`demo.arm2d.zip `. +This completes the Getting Started with AnyScript tutorial. The final result of +your efforts is in {download}`demo.arm2d.zip `. diff --git a/A_study_of_studies/index.md b/A_study_of_studies/index.md index 039694b4..e0ca7126 100644 --- a/A_study_of_studies/index.md +++ b/A_study_of_studies/index.md @@ -1,7 +1,7 @@ ::: {rst-class} break ::: -# A Study of Studies +# A Study of Studies (Deleted) In AnyBody, all types of analysis, whether pure mechanical system analysis, musculoskeletal analysis or design analysis, are carried out