├── .gitignore ├── CPP ├── .clang-format ├── CMakeLists.txt ├── MuscleForceDirection │ ├── CMakeLists.txt │ ├── MuscleForceDirection.cpp │ ├── MuscleForceDirection.h │ ├── RegisterTypes_osimPlugin.cpp │ ├── RegisterTypes_osimPlugin.h │ └── osimPluginDLL.h ├── data │ └── Arm26 │ │ ├── MySetupFile.xml │ │ ├── arm26.osim │ │ ├── arm26_MuscleForceDirection_attachments.sto │ │ ├── arm26_MuscleForceDirection_vectors.sto │ │ └── elbow_flexion.mot └── legacy_code │ ├── OpenSim2.4 │ ├── MuscleForceDirection.cpp │ ├── MuscleForceDirection.h │ ├── MuscleForceDirection_v1.0.zip │ ├── RegisterTypes_osimPlugin.cpp │ ├── RegisterTypes_osimPlugin.h │ └── osimPluginDLL.h │ ├── OpenSim2.4_KULeuven │ ├── MuscleForceDirection.cpp │ └── MuscleForceDirection.h │ ├── OpenSim2.4_prototype │ ├── CMakeLists.txt │ ├── ForceDirection.cpp │ ├── ForceDirection.h │ ├── RegisterTypes_osimPlugin.cpp │ ├── RegisterTypes_osimPlugin.h │ └── osimPluginDLL.h │ ├── OpenSim3.3 │ ├── CMakeLists.txt │ ├── FindOpenSim.cmake │ └── lib │ │ ├── CMakeLists.txt │ │ └── MuscleForceDirection │ │ ├── CMakeLists.txt │ │ ├── MuscleForceDirection.cpp │ │ ├── MuscleForceDirection.h │ │ ├── RegisterTypes_osimPlugin.cpp │ │ ├── RegisterTypes_osimPlugin.h │ │ └── osimPluginDLL.h │ └── README.md ├── LICENSE.md ├── MATLAB ├── .gitignore ├── TEST_plugin.m ├── _dev_deal_withMuscleWrap.m ├── getMuscleForceDirection.m ├── matlab_tool_v4.0 │ ├── .gitignore │ ├── MFD matlab tool v4.0 update notes (K. Song WUSTL).pdf │ ├── TEST_plugin.m │ ├── _dev_deal_withMuscleWrap.m │ ├── getBodyorGround.m │ ├── getCurrentMusclePathAsMat.m │ ├── getMatStructColumn.m │ ├── getMuscleForceDirection.m │ ├── isBodyInModel.m │ ├── isKinMatchingModelCoords.m │ ├── isMuscleConnectedToBody.m │ ├── printtoSTO.m │ ├── realizeMatStructKinematics.m │ ├── sto2Mat.m │ └── transformVec.m ├── private │ ├── Mat2sto.m │ ├── getCurrentMusclePathAsMat.m │ ├── getMatStructColumn.m │ ├── isBodyInModel.m │ ├── isKinMatchingModelCoords.m │ ├── isMuscleConnectedToBody.m │ ├── realizeMatStructKinematics.m │ └── sto2Mat.m └── runTests_MATLAB.m ├── README.md ├── _simtk_releases ├── 2012-05-08_MFD_osim2.4_v1.0.zip ├── 2015-09-03_MFD_osim3.3.zip ├── 2020-12-14_MFD_osim4.1.zip └── README.md ├── doc ├── papers │ ├── Phillips et al. Inter Biomech 2015.pdf │ └── van Arkel et al. J Orthop Res 2013.pdf └── users_guide │ ├── MFD_users_guide_Aug2015.pdf │ ├── MFD_users_guide_Dec2020.pdf │ ├── MFD_users_guide_Sept2015.pdf │ ├── MuscleForceDirection UsersGuide_2012.pdf │ ├── example_Matlab │ └── run_MuscleForceDirection.m │ └── word │ ├── 2-5-2012 MuscleForceDirection_release.docx │ ├── 2-5-2012 MuscleForceDirection_release_updAugust2015.docx │ ├── 2020-12-14_MuscleForceDirection_doc.docx │ └── Images.zip ├── images ├── anatomical_vs_effective.png ├── logo.png ├── logo_v2.png └── plugin_workflow.png └── tests ├── Arm26 ├── MySetupFile.xml ├── arm26.osim └── elbow_flexion.mot ├── MFD_tests ├── Wrapping2.m ├── dev1_Plugin_verification.m ├── testKinematics_file.mot ├── testModel.osim └── validated_res │ ├── GLOBAL_ANATOM_MuscleForceDirection_vectors.sto │ ├── GLOBAL_EFFECT_MuscleForceDirection_vectors.sto │ ├── LOCAL_ANATOM_MuscleForceDirection_vectors.sto │ ├── LOCAL_EFFECT_MuscleForceDirection_vectors.sto │ ├── MuscleForceDirection Test Model_MuscleForceDirection_attachments.sto │ └── MuscleForceDirection Test Model_MuscleForceDirection_vectors.sto ├── gait2392 ├── subject01.osim └── subject01_walk1_ik.mot └── test_checklist.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.asv 3 | *.*~ 4 | *.clangd/ 5 | /CPP/.dir-locals.el 6 | CPP/build/ 7 | /CPP/compile_commands.json 8 | /CPP/install/ 9 | -------------------------------------------------------------------------------- /CPP/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | AccessModifierOffset: -3 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveAssignments: false 6 | AlignConsecutiveDeclarations: false 7 | AlignEscapedNewlines: Right 8 | AlignOperands: true 9 | AlignTrailingComments: true 10 | AllowAllParametersOfDeclarationOnNextLine: true 11 | AllowShortBlocksOnASingleLine: true 12 | AllowShortCaseLabelsOnASingleLine: true 13 | AllowShortFunctionsOnASingleLine: All 14 | AllowShortIfStatementsOnASingleLine: true 15 | AllowShortLoopsOnASingleLine: true 16 | AlwaysBreakAfterReturnType: None 17 | AlwaysBreakBeforeMultilineStrings: false 18 | BinPackArguments: true 19 | BinPackParameters: true 20 | BraceWrapping: 21 | AfterClass: true 22 | AfterControlStatement: false 23 | AfterEnum: false 24 | AfterFunction: false 25 | AfterNamespace: false 26 | AfterObjCDeclaration: false 27 | AfterStruct: false 28 | AfterUnion: false 29 | AfterExternBlock: false 30 | BeforeCatch: false 31 | BeforeElse: false 32 | IndentBraces: false 33 | # SplitEmptyFunction: true 34 | # SplitEmptyRecord: true 35 | # SplitEmptyNamespace: true 36 | BreakBeforeBinaryOperators: None 37 | # BreakBeforeBraces: Attach 38 | BreakBeforeInheritanceComma: false 39 | # BreakInheritanceList: BeforeColon 40 | BreakBeforeTernaryOperators: true 41 | BreakConstructorInitializersBeforeComma: false 42 | BreakConstructorInitializers: BeforeColon 43 | BreakAfterJavaFieldAnnotations: false 44 | BreakStringLiterals: true 45 | ColumnLimit: 80 46 | CompactNamespaces: false 47 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 48 | ConstructorInitializerIndentWidth: 8 49 | ContinuationIndentWidth: 8 50 | Cpp11BracedListStyle: true 51 | DerivePointerAlignment: false 52 | DisableFormat: false 53 | ExperimentalAutoDetectBinPacking: false 54 | FixNamespaceComments: true 55 | ForEachMacros: 56 | - foreach 57 | - Q_FOREACH 58 | - BOOST_FOREACH 59 | IncludeBlocks: Regroup 60 | IndentCaseLabels: false 61 | IndentPPDirectives: AfterHash 62 | IndentWidth: 4 63 | IndentWrappedFunctionNames: false 64 | KeepEmptyLinesAtTheStartOfBlocks: false 65 | MacroBlockBegin: '' 66 | MacroBlockEnd: '' 67 | MaxEmptyLinesToKeep: 1 68 | NamespaceIndentation: None 69 | PenaltyBreakAssignment: 2 70 | PenaltyBreakBeforeFirstCallParameter: 19 71 | PenaltyBreakComment: 300 72 | PenaltyBreakFirstLessLess: 120 73 | PenaltyBreakString: 1000 74 | # PenaltyBreakTemplateDeclaration: 10 75 | PenaltyExcessCharacter: 1000000 76 | PenaltyReturnTypeOnItsOwnLine: 60 77 | PointerAlignment: Left 78 | ReflowComments: true 79 | SortIncludes: true 80 | SortUsingDeclarations: true 81 | SpaceAfterCStyleCast: true 82 | SpaceAfterTemplateKeyword: true 83 | SpaceBeforeAssignmentOperators: true 84 | SpaceBeforeParens: ControlStatements 85 | SpaceInEmptyParentheses: false 86 | SpacesBeforeTrailingComments: 1 87 | SpacesInAngles: false 88 | SpacesInContainerLiterals: true 89 | SpacesInCStyleCastParentheses: false 90 | SpacesInParentheses: false 91 | SpacesInSquareBrackets: false 92 | Standard: Auto 93 | TabWidth: 4 94 | UseTab: Never 95 | -------------------------------------------------------------------------------- /CPP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(MuscleForceDirection VERSION 1.0.0) 3 | 4 | if(UNIX AND NOT CMAKE_BUILD_TYPE) 5 | set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the build type" FORCE) 6 | endif() 7 | 8 | # compilation database (completion for Linux) 9 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 10 | 11 | add_subdirectory(MuscleForceDirection) 12 | -------------------------------------------------------------------------------- /CPP/MuscleForceDirection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # find OpenSim 2 | find_package(OpenSim REQUIRED) 3 | include_directories(${OpenSim_INCLUDE_DIRS}) 4 | link_directories(${OpenSim_LIB_DIR}) 5 | 6 | # header and sources 7 | set(MuscleForceDirection_HEADERS 8 | MuscleForceDirection.h RegisterTypes_osimPlugin.h osimPluginDLL.h) 9 | set(MuscleForceDirection_SOURCES 10 | MuscleForceDirection.cpp RegisterTypes_osimPlugin.cpp) 11 | source_group("MuscleForceDirection_headers" 12 | FILES ${MuscleForceDirection_HEADERS}) 13 | source_group("MuscleForceDirection_sources" 14 | FILES ${MuscleForceDirection_SOURCES}) 15 | 16 | # library 17 | set(target MuscleForceDirection) 18 | add_library(${target} SHARED 19 | ${MuscleForceDirection_HEADERS} 20 | ${MuscleForceDirection_SOURCES}) 21 | target_link_libraries(${target} ${OpenSim_LIBRARIES}) 22 | set_target_properties( 23 | ${target} PROPERTIES 24 | DEFINE_SYMBOL OSIMPLUGIN_EXPORTS 25 | PROJECT_LABEL "Libraries - MuscleForceDirection") 26 | install(TARGETS ${target} 27 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 28 | -------------------------------------------------------------------------------- /CPP/MuscleForceDirection/MuscleForceDirection.h: -------------------------------------------------------------------------------- 1 | #ifndef _MuscleForceDirection_h_ 2 | #define _MuscleForceDirection_h_ 3 | 4 | #include "osimPluginDLL.h" // Header to define plugin (DLL) interface 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace OpenSim { 19 | 20 | class Model; 21 | 22 | class OSIMPLUGIN_API MuscleForceDirection : public Analysis { 23 | OpenSim_DECLARE_CONCRETE_OBJECT(MuscleForceDirection, Analysis); 24 | 25 | protected: 26 | // Lines of action in local or global frame. 27 | PropertyBool _expressInLocalFrameProp; 28 | bool& _expressInLocalFrame; 29 | 30 | // Print or not a .sto file with the muscle attachments. 31 | PropertyBool _boolPrintAttachPointProp; 32 | bool& _printAttachPoints; 33 | 34 | // Anatomical muscle insertions or effective muscle insertions. 35 | PropertyBool _boolEffectiveInsertionsProp; 36 | bool& _effectInsertion; 37 | 38 | // string array with the bodies to analyze 39 | PropertyStrArray _strArrayBodyProp; 40 | Array& _bodyNames; 41 | 42 | /*-------------- NOTE --------------- 43 | The original idea was to include the option for the user of 44 | deciding a single muscle to analyze. 45 | This option has been removed as for finite element applications 46 | is generally an entire body (or more) and the forces connected to it 47 | to be of interest. 48 | //string array with the muscles to analyze 49 | //PropertyStrArray _strArrayMuscleProp; 50 | //Array &_muscleNames; 51 | --------------------------------------*/ 52 | 53 | //========== INTERNAL USE ============== 54 | // Indices of bodies for kinematics to be reported and muscle for direction 55 | Array _muscleIndices; 56 | 57 | // Storage for recording muscle direction 58 | Storage _storeDir; 59 | 60 | // Storage for recording attachment position 61 | Storage _storeAttachPointPos; 62 | 63 | // Internal work arrays to hold muscle directions at each time step. 64 | Array _muscledir; 65 | Array _attachpointpos; 66 | 67 | // ===================================== METHODS 68 | // ================================== 69 | public: 70 | // CONSTRUCTORS 71 | MuscleForceDirection(Model* aModel = 0); 72 | MuscleForceDirection(const std::string& aFileName, bool aUpdateFromXMLNode); 73 | // COPY CONSTRUCTOR 74 | MuscleForceDirection(const MuscleForceDirection& aObject); 75 | // DESTRUCTOR 76 | ~MuscleForceDirection(); 77 | // CLONE 78 | Object* copy() const; 79 | 80 | private: 81 | // ZERO DATA AND NULL POINTERS 82 | void setNull(); 83 | // SETUP PROPERTIES 84 | void setupProperties(); 85 | 86 | public: 87 | #ifndef SWIG 88 | // Assign this object to the values of another.@return Reference to this 89 | // object. 90 | MuscleForceDirection& 91 | operator=(const MuscleForceDirection& aMuscleForceDirection); 92 | #endif 93 | 94 | //========================== Required Methods ============================= 95 | void setModel(Model& aModel) override; 96 | // INTEGRATION 97 | int begin(SimTK::State& s); 98 | int step(const SimTK::State& s, int stepNumber) override; 99 | int end(SimTK::State& s); 100 | // IO 101 | int printResults(const std::string& aBaseName, const std::string& aDir = "", 102 | double aDT = -1.0, 103 | const std::string& aExtension = ".sto") override; 104 | 105 | protected: 106 | //========================== Internal Methods ============================= 107 | int record(const SimTK::State& s); 108 | void constructDescription(); 109 | void constructColumnLabels(); 110 | void setupStorage(); 111 | 112 | // Utilities implemented by Luca Modenese (check on 15th March 2012). 113 | void constructDescriptionAttachments(); 114 | void setupStorageAttachments(); 115 | static Array 116 | getMusclesIndexForBody(Model* model, const Array& bodyNames); 117 | static bool isMuscleAttachedToBody(const OpenSim::Muscle& aMuscle, 118 | const std::string& aBodyName); 119 | static void 120 | getEffectiveAttachments(const Array& aPFDs, 121 | int& effecInsertProx, int& effecInsertDist); 122 | void NormalizeVec3(SimTK::Vec3& v1, SimTK::Vec3& rNormv1); 123 | }; // END of class MuscleForceDirection 124 | 125 | }; // namespace OpenSim 126 | #endif // #ifndef __AnalysisPlugin_Template_h__ 127 | -------------------------------------------------------------------------------- /CPP/MuscleForceDirection/RegisterTypes_osimPlugin.cpp: -------------------------------------------------------------------------------- 1 | // RegisterTypes_osimPlugin.cpp 2 | /* -------------------------------------------------------------------------- * 3 | * OpenSim: RegisterTypes_osimPlugin.cpp * 4 | * -------------------------------------------------------------------------- * 5 | * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. * 6 | * See http://opensim.stanford.edu and the NOTICE file for more information. * 7 | * OpenSim is developed at Stanford University and supported by the US * 8 | * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA * 9 | * through the Warrior Web program. * 10 | * * 11 | * Copyright (c) 2005-2017 Stanford University and the Authors * 12 | * * 13 | * Licensed under the Apache License, Version 2.0 (the "License"); you may * 14 | * not use this file except in compliance with the License. You may obtain a * 15 | * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 16 | * * 17 | * Unless required by applicable law or agreed to in writing, software * 18 | * distributed under the License is distributed on an "AS IS" BASIS, * 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 20 | * See the License for the specific language governing permissions and * 21 | * limitations under the License. * 22 | * -------------------------------------------------------------------------- */ 23 | 24 | #include "RegisterTypes_osimPlugin.h" 25 | 26 | #include 27 | #include 28 | #include 29 | //#include "MyAnalysis.h" 30 | #include "MuscleForceDirection.h" 31 | 32 | using namespace OpenSim; 33 | using namespace std; 34 | 35 | static dllObjectInstantiator instantiator; 36 | 37 | //_____________________________________________________________________________ 38 | /** 39 | * The purpose of this routine is to register all class types exported by 40 | * the Plugin library. 41 | */ 42 | OSIMPLUGIN_API void RegisterTypes_osimPlugin() { 43 | Object::RegisterType(MuscleForceDirection()); 44 | } 45 | 46 | dllObjectInstantiator::dllObjectInstantiator() { registerDllClasses(); } 47 | 48 | void dllObjectInstantiator::registerDllClasses() { RegisterTypes_osimPlugin(); } 49 | -------------------------------------------------------------------------------- /CPP/MuscleForceDirection/RegisterTypes_osimPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef _RegisterTypes_OsimPlugin_h_ 2 | #define _RegisterTypes_OsimPlugin_h_ 3 | 4 | /* -------------------------------------------------------------------------- * 5 | * OpenSim: RegisterTypes_osimPlugin.h * 6 | * -------------------------------------------------------------------------- * 7 | * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. * 8 | * See http://opensim.stanford.edu and the NOTICE file for more information. * 9 | * OpenSim is developed at Stanford University and supported by the US * 10 | * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA * 11 | * through the Warrior Web program. * 12 | * * 13 | * Copyright (c) 2005-2017 Stanford University and the Authors * 14 | * * 15 | * Licensed under the Apache License, Version 2.0 (the "License"); you may * 16 | * not use this file except in compliance with the License. You may obtain a * 17 | * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 18 | * * 19 | * Unless required by applicable law or agreed to in writing, software * 20 | * distributed under the License is distributed on an "AS IS" BASIS, * 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 22 | * See the License for the specific language governing permissions and * 23 | * limitations under the License. * 24 | * -------------------------------------------------------------------------- */ 25 | 26 | #include "osimPluginDLL.h" 27 | 28 | // COMPATIBILE CON C: #ifndef: 29 | // http://forum.html.it/forum/showthread/t-1335669.html 30 | extern "C" { 31 | OSIMPLUGIN_API void RegisterTypes_osimPlugin(); 32 | } 33 | 34 | class dllObjectInstantiator { 35 | public: 36 | dllObjectInstantiator(); 37 | 38 | private: 39 | void registerDllClasses(); 40 | }; 41 | 42 | #endif // _RegisterTypes_OsimPlugin_h_ 43 | -------------------------------------------------------------------------------- /CPP/MuscleForceDirection/osimPluginDLL.h: -------------------------------------------------------------------------------- 1 | #ifndef _osimPluginDLL_h_ 2 | #define _osimPluginDLL_h_ 3 | 4 | #ifdef WIN32 5 | # ifdef OSIMPLUGIN_EXPORTS 6 | # define OSIMPLUGIN_API __declspec(dllexport) 7 | # else 8 | # define OSIMPLUGIN_API __declspec(dllimport) 9 | # endif 10 | #else 11 | # define OSIMPLUGIN_API 12 | #endif // WIN32 13 | 14 | #endif // __osimPluginDLL_h__ 15 | -------------------------------------------------------------------------------- /CPP/data/Arm26/MySetupFile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | arm26.osim 5 | . 6 | 12 7 | 0.00000000 8 | 1.00000000 9 | 10 | 11 | 12 | true 13 | 0.00000000 14 | 1.00000000 15 | 1 16 | true 17 | true 18 | false 19 | false 20 | all 21 | 22 | 23 | 24 | 25 | elbow_flexion.mot 26 | 6.0 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4/MuscleForceDirection.h: -------------------------------------------------------------------------------- 1 | #ifndef _MuscleForceDirection_h_ 2 | #define _MuscleForceDirection_h_ 3 | 4 | // MuscleForceDirection.h 5 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 | // AUTHOR: Frank C. Anderson, Ajay Seth 7 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 | /* 10 | * Copyright (c) 2005, Stanford University. All rights reserved. 11 | * Use of the OpenSim software in source form is permitted provided that the following 12 | * conditions are met: 13 | * 1. The software is used only for non-commercial research and education. It may not 14 | * be used in relation to any commercial activity. 15 | * 2. The software is not distributed or redistributed. Software distribution is allowed 16 | * only through https://simtk.org/home/opensim. 17 | * 3. Use of the OpenSim software or derivatives must be acknowledged in all publications, 18 | * presentations, or documents describing work in which OpenSim or derivatives are used. 19 | * 4. Credits to developers may not be removed from executables 20 | * created from modifications of the source. 21 | * 5. Modifications of source code must retain the above copyright notice, this list of 22 | * conditions and the following disclaimer. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 25 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 27 | * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 | * OR BUSINESS INTERRUPTION) OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 32 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | // Plugin written by Luca Modenese 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include "osimPluginDLL.h"// Header to define plugin (DLL) interface 49 | 50 | namespace OpenSim { 51 | 52 | class Model; 53 | 54 | class OSIMPLUGIN_API MuscleForceDirection : public Analysis 55 | 56 | { 57 | // ======================= DATA ============================ 58 | 59 | private: 60 | 61 | protected: 62 | 63 | // Lines of action in local or global frame. 64 | PropertyBool _expressInLocalFrameProp; 65 | bool &_expressInLocalFrame; 66 | 67 | // Print or not a .sto file with the muscle attachments. 68 | PropertyBool _boolPrintAttachPointProp; 69 | bool &_printAttachPoints; 70 | 71 | // Anatomical muscle insertions or effective muscle insertions. 72 | PropertyBool _boolEffectiveInsertionsProp; 73 | bool &_effectInsertion; 74 | 75 | // string array with the bodies to analyze 76 | PropertyStrArray _strArrayBodyProp; 77 | Array &_bodyNames; 78 | 79 | /*-------------- NOTE --------------- 80 | The original idea was to include the option for the user of 81 | deciding a single muscle to analyze. 82 | This option has been removed as for finite element applications 83 | is generally an entire body (or more) and the forces connected to it 84 | to be of interest. 85 | //string array with the muscles to analyze 86 | //PropertyStrArray _strArrayMuscleProp; 87 | //Array &_muscleNames; 88 | --------------------------------------*/ 89 | 90 | 91 | //========== INTERNAL USE ============== 92 | // Indices of bodies for kinematics to be reported and muscle for direction 93 | Array _muscleIndices; 94 | 95 | // Storage for recording muscle direction 96 | Storage _storeDir; 97 | 98 | // Storage for recording attachment position 99 | Storage _storeAttachPointPos; 100 | 101 | // Internal work arrays to hold muscle directions at each time step. 102 | Array _muscledir; 103 | Array _attachpointpos; 104 | 105 | // ===================================== METHODS ================================== 106 | public: 107 | // CONSTRUCTORS 108 | MuscleForceDirection(Model *aModel=0); 109 | MuscleForceDirection(const std::string &aFileName); 110 | // COPY CONSTRUCTOR 111 | MuscleForceDirection(const MuscleForceDirection& aObject); 112 | // DESTRUCTOR 113 | virtual ~MuscleForceDirection(); 114 | // CLONE 115 | virtual Object* copy() const; 116 | 117 | private: 118 | // ZERO DATA AND NULL POINTERS 119 | void setNull(); 120 | // SETUP PROPERTIES 121 | void setupProperties(); 122 | 123 | public: 124 | 125 | #ifndef SWIG 126 | //Assign this object to the values of another.@return Reference to this object. 127 | MuscleForceDirection& operator=(const MuscleForceDirection &aMuscleForceDirection); 128 | #endif 129 | 130 | //========================== Required Methods ============================= 131 | virtual void setModel(Model& aModel); 132 | // INTEGRATION 133 | virtual int begin(SimTK::State& s); 134 | virtual int step(const SimTK::State& s, int stepNumber); 135 | virtual int end(SimTK::State& s); 136 | // IO 137 | virtual int printResults(const std::string &aBaseName,const std::string &aDir="",double aDT=-1.0,const std::string &aExtension=".sto"); 138 | 139 | protected: 140 | //========================== Internal Methods ============================= 141 | int record(const SimTK::State& s); 142 | void constructDescription(); 143 | void constructColumnLabels(); 144 | void setupStorage(); 145 | 146 | // Utilities implemented by Luca Modenese (check on 15th March 2012). 147 | void constructDescriptionAttachments(); 148 | void setupStorageAttachments(); 149 | bool IsMuscleAttachedToBody(OpenSim::Muscle &aMuscle, std::string aBodyName); 150 | void GetMusclesIndexForBody(OpenSim::Model * _model, Array aBodyNameSet, Array & MusclesIndexForBody ); 151 | void MuscleForceDirection::EffectiveAttachments(Array & aPFDs, int & effecInsertProx, int & effecInsertDist); 152 | inline void NormalizeVec3(SimTK::Vec3 & v1, SimTK::Vec3 & rNormv1); 153 | 154 | }; // END of class MuscleForceDirection 155 | 156 | }; //namespace 157 | #endif // #ifndef __AnalysisPlugin_Template_h__ 158 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4/MuscleForceDirection_v1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/CPP/legacy_code/OpenSim2.4/MuscleForceDirection_v1.0.zip -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4/RegisterTypes_osimPlugin.cpp: -------------------------------------------------------------------------------- 1 | // RegisterTypes_osimPlugin.cpp 2 | /* -------------------------------------------------------------------------- * 3 | * OpenSim: RegisterTypes_osimPlugin.cpp * 4 | * -------------------------------------------------------------------------- * 5 | * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. * 6 | * See http://opensim.stanford.edu and the NOTICE file for more information. * 7 | * OpenSim is developed at Stanford University and supported by the US * 8 | * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA * 9 | * through the Warrior Web program. * 10 | * * 11 | * Copyright (c) 2005-2017 Stanford University and the Authors * 12 | * * 13 | * Licensed under the Apache License, Version 2.0 (the "License"); you may * 14 | * not use this file except in compliance with the License. You may obtain a * 15 | * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 16 | * * 17 | * Unless required by applicable law or agreed to in writing, software * 18 | * distributed under the License is distributed on an "AS IS" BASIS, * 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 20 | * See the License for the specific language governing permissions and * 21 | * limitations under the License. * 22 | * -------------------------------------------------------------------------- */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include "RegisterTypes_osimPlugin.h" 28 | //#include "MyAnalysis.h" 29 | #include "MuscleForceDirection.h" 30 | 31 | using namespace OpenSim; 32 | using namespace std; 33 | 34 | static dllObjectInstantiator instantiator; 35 | 36 | //_____________________________________________________________________________ 37 | /** 38 | * The purpose of this routine is to register all class types exported by 39 | * the Plugin library. 40 | */ 41 | OSIMPLUGIN_API void RegisterTypes_osimPlugin() 42 | { 43 | //Object::RegisterType( MyAnalysis() ); 44 | Object::RegisterType( MuscleForceDirection() ); 45 | } 46 | 47 | dllObjectInstantiator::dllObjectInstantiator() 48 | { 49 | registerDllClasses(); 50 | } 51 | 52 | void dllObjectInstantiator::registerDllClasses() 53 | { 54 | RegisterTypes_osimPlugin(); 55 | } 56 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4/RegisterTypes_osimPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef _RegisterTypes_OsimPlugin_h_ 2 | #define _RegisterTypes_OsimPlugin_h_ 3 | /* -------------------------------------------------------------------------- * 4 | * OpenSim: RegisterTypes_osimPlugin.h * 5 | * -------------------------------------------------------------------------- * 6 | * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. * 7 | * See http://opensim.stanford.edu and the NOTICE file for more information. * 8 | * OpenSim is developed at Stanford University and supported by the US * 9 | * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA * 10 | * through the Warrior Web program. * 11 | * * 12 | * Copyright (c) 2005-2017 Stanford University and the Authors * 13 | * * 14 | * Licensed under the Apache License, Version 2.0 (the "License"); you may * 15 | * not use this file except in compliance with the License. You may obtain a * 16 | * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 17 | * * 18 | * Unless required by applicable law or agreed to in writing, software * 19 | * distributed under the License is distributed on an "AS IS" BASIS, * 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 21 | * See the License for the specific language governing permissions and * 22 | * limitations under the License. * 23 | * -------------------------------------------------------------------------- */ 24 | 25 | 26 | 27 | #include "osimPluginDLL.h" 28 | 29 | //COMPATIBILE CON C: #ifndef: http://forum.html.it/forum/showthread/t-1335669.html 30 | extern "C" 31 | 32 | { 33 | OSIMPLUGIN_API void RegisterTypes_osimPlugin(); 34 | } 35 | 36 | class dllObjectInstantiator 37 | { 38 | public: 39 | dllObjectInstantiator(); 40 | private: 41 | void registerDllClasses(); 42 | }; 43 | 44 | #endif // _RegisterTypes_OsimPlugin_h_ 45 | 46 | 47 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4/osimPluginDLL.h: -------------------------------------------------------------------------------- 1 | // SUPPORT MATERIAL 2 | 3 | // #ifndef: http://forum.html.it/forum/showthread/t-1335669.html 4 | // #DEFINE: http://msdn.microsoft.com/en-us/library/teas0593%28v=vs.80%29.aspx 5 | 6 | #ifndef _osimPluginDLL_h_ 7 | #define _osimPluginDLL_h_ 8 | 9 | // UNIX PLATFORM 10 | #ifndef WIN32 11 | 12 | #define OSIMPLUGIN_API 13 | 14 | // WINDOWS PLATFORM 15 | #else 16 | // removes some headers from 17 | #define WIN32_LEAN_AND_MEAN //http://blogs.msdn.com/b/oldnewthing/archive/2009/11/30/9929944.aspx 18 | #define NOMINMAX //http://stackoverflow.com/questions/4913922/possible-problems-with-nominmax-on-visual-c 19 | #include 20 | 21 | #ifdef OSIMPLUGIN_EXPORTS 22 | #define OSIMPLUGIN_API __declspec(dllexport) 23 | #else 24 | #define OSIMPLUGIN_API __declspec(dllimport) 25 | #endif 26 | 27 | #endif // PLATFORM 28 | #endif // __osimPluginDLL_h__ 29 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4_KULeuven/MuscleForceDirection.h: -------------------------------------------------------------------------------- 1 | #ifndef _MuscleForceDirection_h_ 2 | #define _MuscleForceDirection_h_ 3 | // MuscleForceDirection.h 4 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | // AUTHOR: Frank C. Anderson, Ajay Seth 6 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | /* 9 | * Copyright (c) 2005, Stanford University. All rights reserved. 10 | * Use of the OpenSim software in source form is permitted provided that the following 11 | * conditions are met: 12 | * 1. The software is used only for non-commercial research and education. It may not 13 | * be used in relation to any commercial activity. 14 | * 2. The software is not distributed or redistributed. Software distribution is allowed 15 | * only through https://simtk.org/home/opensim. 16 | * 3. Use of the OpenSim software or derivatives must be acknowledged in all publications, 17 | * presentations, or documents describing work in which OpenSim or derivatives are used. 18 | * 4. Credits to developers may not be removed from executables 19 | * created from modifications of the source. 20 | * 5. Modifications of source code must retain the above copyright notice, this list of 21 | * conditions and the following disclaimer. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR BUSINESS INTERRUPTION) OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 31 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | 35 | //============================================================================= 36 | // INCLUDES 37 | //============================================================================= 38 | #include "osimAnalysesDLL.h" 39 | #ifdef SWIG 40 | #ifdef OSIMANALYSES_API 41 | #undef OSIMANALYSES_API 42 | #define OSIMANALYSES_API 43 | #endif 44 | #endif 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | const int MuscleForceDirectionNAME_LENGTH = 256; 59 | const int MuscleForceDirectionBUFFER_LENGTH = 2048; 60 | 61 | //============================================================================= 62 | //============================================================================= 63 | namespace OpenSim { 64 | 65 | class Model; 66 | class Body; 67 | 68 | /** 69 | * A class for recording the kinematics of a point on a body 70 | * of a model during a simulation. 71 | * 72 | * @author Frank C. Anderson 73 | * @version 1.0 74 | */ 75 | class OSIMANALYSES_API MuscleForceDirection : public Analysis { 76 | OpenSim_DECLARE_CONCRETE_OBJECT(MuscleForceDirection, Analysis); 77 | 78 | //============================================================================= 79 | // DATA 80 | //============================================================================= 81 | public: 82 | static const int NAME_LENGTH; 83 | static const int BUFFER_LENGTH; 84 | private: 85 | 86 | 87 | protected: 88 | // Lines of action in local or global frame. 89 | PropertyBool _expressInLocalFrameProp; 90 | bool &_expressInLocalFrame; 91 | 92 | // Print or not a .sto file with the muscle attachments. 93 | PropertyBool _boolPrintAttachPointProp; 94 | bool &_printAttachPoints; 95 | 96 | // Anatomical muscle insertions or effective muscle insertions. 97 | PropertyBool _boolEffectiveInsertionsProp; 98 | bool &_effectInsertion; 99 | 100 | // string array with the bodies to analyze 101 | PropertyStrArray _strArrayBodyProp; 102 | Array &_bodyNames; 103 | 104 | // results will be expressed with respect to this body 105 | PropertyStr _relativeToBodyNameProp; 106 | std::string &_relativeToBodyName; 107 | 108 | 109 | 110 | //========== INTERNAL USE ============== 111 | // Indices of bodies for kinematics to be reported and muscle for direction 112 | Array _muscleIndices; 113 | 114 | // Storage for recording muscle direction 115 | Storage _storeDir; 116 | 117 | // Storage for recording attachment position 118 | Storage _storeAttachPointPos; 119 | 120 | // Internal work arrays to hold muscle directions at each time step. 121 | Array _muscledir; 122 | Array _attachpointpos; 123 | 124 | //============================================================================= 125 | // METHODS 126 | //============================================================================= 127 | public: 128 | // CONSTRUCTORS 129 | MuscleForceDirection(Model *aModel=0); 130 | MuscleForceDirection(const std::string &aFileName); 131 | // COPY CONSTRUCTOR 132 | MuscleForceDirection(const MuscleForceDirection& aObject); 133 | // DESTRUCTOR 134 | virtual ~MuscleForceDirection(); 135 | // CLONE 136 | virtual Object* copy() const; 137 | 138 | private: 139 | void setNull(); 140 | void setupProperties(); 141 | 142 | //-------------------------------------------------------------------------- 143 | // CONSTRUCTION 144 | //-------------------------------------------------------------------------- 145 | public: 146 | 147 | //-------------------------------------------------------------------------- 148 | // OPERATORS 149 | //-------------------------------------------------------------------------- 150 | #ifndef SWIG 151 | MuscleForceDirection& operator=(const MuscleForceDirection &aMuscleForceDirection); 152 | #endif 153 | 154 | 155 | //-------------------------------------------------------------------------- 156 | // ANALYSIS 157 | //-------------------------------------------------------------------------- 158 | virtual void setModel(Model& aModel); 159 | // INTEGRATION 160 | virtual int begin( SimTK::State& s); 161 | virtual int step(const SimTK::State& s, int setNumber); 162 | virtual int end( SimTK::State& s); 163 | // IO 164 | virtual int printResults(const std::string &aBaseName,const std::string &aDir="",double aDT=-1.0,const std::string &aExtension=".sto"); 165 | 166 | protected: 167 | int record(const SimTK::State& s ); 168 | void constructDescription(); 169 | void constructColumnLabels(); 170 | void setupStorage(); 171 | 172 | // Utilities implemented by Luca Modenese (check on 15th March 2012). 173 | void constructDescriptionAttachments(); 174 | void setupStorageAttachments(); 175 | bool IsMuscleAttachedToBody(OpenSim::Muscle &aMuscle, std::string aBodyName); 176 | void GetMusclesIndexForBody(OpenSim::Model * _model, Array aBodyNameSet, Array & MusclesIndexForBody ); 177 | void MuscleForceDirection::EffectiveAttachments(Array & aPFDs, int & effecInsertProx, int & effecInsertDist); 178 | inline void NormalizeVec3(SimTK::Vec3 & v1, SimTK::Vec3 & rNormv1); 179 | 180 | 181 | //============================================================================= 182 | }; // END of class MuscleForceDirection 183 | 184 | }; //namespace 185 | //============================================================================= 186 | //============================================================================= 187 | 188 | 189 | #endif // #ifndef __MuscleForceDirection_h__ 190 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4_prototype/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | Project(ForceDirection_v2) 2 | 3 | cmake_minimum_required(VERSION 2.6) 4 | if(COMMAND cmake_policy) 5 | cmake_policy(SET CMP0003 NEW) 6 | cmake_policy(SET CMP0005 NEW) 7 | endif(COMMAND cmake_policy) 8 | 9 | SET(KIT plugin) 10 | SET(UKIT PLUGIN) 11 | 12 | SET(NameSpace "OpenSim_") 13 | 14 | FILE(GLOB SOURCE_FILES *.cpp) 15 | FILE(GLOB INCLUDE_FILES *.h) 16 | 17 | SET(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release" 18 | CACHE STRING "Semicolon separated list of supported configuration types, only supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything else will be ignored." FORCE ) 19 | 20 | SET(EXPORT_MACRO OSIM${UKIT}_EXPORTS) 21 | 22 | SET(OPENSIM_INSTALL_DIR "C:/OpenSim2.4.0/" CACHE PATH "Top-level directory of OpenSim install") 23 | 24 | SET(PLUGIN_NAME "ForceDirection_v2" CACHE STRING "Name of shared library to create") 25 | 26 | ### HEADERS 27 | SET(OPENSIM_HEADERS_DIR ${OPENSIM_INSTALL_DIR}/sdk/include) 28 | SET(XERCES_HEADER_DIR ${OPENSIM_INSTALL_DIR}/sdk/include/xercesc) 29 | SET(SIMTK_HEADERS_DIR ${OPENSIM_INSTALL_DIR}/sdk/include/SimTK/include) 30 | 31 | INCLUDE_DIRECTORIES(${OPENSIM_HEADERS_DIR} ${XERCES_HEADER_DIR} ${SIMTK_HEADERS_DIR}) 32 | 33 | ### LIBRARIES 34 | SET(OPENSIM_LIBS_DIR ${OPENSIM_INSTALL_DIR}/sdk/lib) 35 | LINK_DIRECTORIES(${OPENSIM_LIBS_DIR}) 36 | 37 | # SimmKinematicsEngine library only needed for SimmFileWriter... 38 | LINK_LIBRARIES( 39 | debug osimCommon_d optimized osimCommon 40 | debug osimSimulation_d optimized osimSimulation 41 | debug osimAnalyses_d optimized osimAnalyses 42 | debug osimActuators_d optimized osimActuators 43 | debug osimTools_d optimized osimTools 44 | debug ${NameSpace}SimTKcommon${CMAKE_DEBUG_POSTFIX} optimized ${NameSpace}SimTKcommon 45 | debug ${NameSpace}SimTKmath${CMAKE_DEBUG_POSTFIX} optimized ${NameSpace}SimTKmath 46 | debug ${NameSpace}SimTKsimbody${CMAKE_DEBUG_POSTFIX} optimized ${NameSpace}SimTKsimbody 47 | SimTKlapack pthreadVC2 48 | ) 49 | 50 | ADD_LIBRARY(${PLUGIN_NAME} SHARED ${SOURCE_FILES} ${INCLUDE_FILES}) 51 | 52 | IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 53 | SET(CMAKE_INSTALL_PREFIX ${OPENSIM_INSTALL_DIR}/ CACHE PATH "Install path prefix." FORCE) 54 | ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 55 | 56 | ## MARK_AS_ADVANCED(CMAKE_INSTALL_PREFIX) 57 | MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH) 58 | MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH) 59 | 60 | SET_TARGET_PROPERTIES( 61 | ${PLUGIN_NAME} PROPERTIES 62 | DEFINE_SYMBOL ${EXPORT_MACRO} 63 | PROJECT_LABEL "Libraries - ${PLUGIN_NAME}") 64 | 65 | INSTALL_TARGETS(/plugins RUNTIME_DIRECTORY /plugins ${PLUGIN_NAME}) 66 | 67 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4_prototype/ForceDirection.h: -------------------------------------------------------------------------------- 1 | #ifndef _ForceDirection_h_ 2 | #define _ForceDirection_h_ 3 | 4 | // MuscleForceDirection.h 5 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 | // AUTHOR: Frank C. Anderson, Ajay Seth 7 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 | /* 10 | * Copyright (c) 2005, Stanford University. All rights reserved. 11 | * Use of the OpenSim software in source form is permitted provided that the following 12 | * conditions are met: 13 | * 1. The software is used only for non-commercial research and education. It may not 14 | * be used in relation to any commercial activity. 15 | * 2. The software is not distributed or redistributed. Software distribution is allowed 16 | * only through https://simtk.org/home/opensim. 17 | * 3. Use of the OpenSim software or derivatives must be acknowledged in all publications, 18 | * presentations, or documents describing work in which OpenSim or derivatives are used. 19 | * 4. Credits to developers may not be removed from executables 20 | * created from modifications of the source. 21 | * 5. Modifications of source code must retain the above copyright notice, this list of 22 | * conditions and the following disclaimer. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 25 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 27 | * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 | * OR BUSINESS INTERRUPTION) OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 32 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | //============================================================================= 36 | // INCLUDES 37 | //============================================================================= 38 | // Headers define the various property types that OpenSim objects can read 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | // Header to define plugin (DLL) interface 50 | #include "osimPluginDLL.h" 51 | 52 | 53 | //============================================================================= 54 | //============================================================================= 55 | /* 56 | * A class template for writing a custom Analysis 57 | * Currenlty reports the position and orientation of bodies listed in its 58 | * properties. 59 | * 60 | * @author Frank C. Anderson, Ajay Seth 61 | * @version 1.6 62 | */ 63 | namespace OpenSim { 64 | 65 | class Model; 66 | 67 | 68 | class OSIMPLUGIN_API ForceDirection : public Analysis 69 | { 70 | //============================================================================= 71 | // DATA 72 | //============================================================================= 73 | private: 74 | 75 | protected: 76 | // Properties are the user-specified quantities that are read in from 77 | // file and are used to configure your class. 78 | // 79 | // A property consists of a type, a name, and a value. You can 80 | // access each of these by calling methods on the property. For example, 81 | // 82 | // string type = property.getType(); 83 | // string name = property.getName(); 84 | // double value = property.getValueDbl(); 85 | // double x = 1.0; 86 | // property.setValue(x); 87 | // 88 | // To make writing your code more streamlined, you can initialize 89 | // a reference to point to the value of a property. For example, 90 | // 91 | // double &_param1 = _param1Prop.getValueDbl(); 92 | // 93 | // In this way you can write your code using _param1 as a normal 94 | // variable, instead of using get and set methods on 95 | // _param1Prop all the time. The references to the properties 96 | // (e.g., _param1) are initialized in the initialization list 97 | // of the class constructors. 98 | // 99 | // Below are example member variables of different property 100 | // types available. 101 | // 102 | // To write your own custom analysis, delete the property types 103 | // you don't need and, if needed, add additional propertes of the 104 | // appropriate type. Then, choose meaningful names for the properties. 105 | // For example, rename _boolProp to _expressInLocalFrameProp and 106 | // _bool to _expressInLocalFrame. The names of the member variables 107 | // use names similar to the type of the variable (e.g., bool, int, dbl), 108 | // but this is just for convenience. You can name the variables 109 | // anything you like, as long as it's a legal name. 110 | // 111 | // As a convention, all member variables of a class are 112 | // preceded with an underscore (e.g., _param1). In this way, 113 | // you can tell which variables are member variables and which 114 | // are not as you code up your analysis. 115 | 116 | /** Boolean Property */ 117 | PropertyBool _boolProp; 118 | bool &_boolref; 119 | PropertyBool _boolPropcsv; 120 | bool &_boolcsv; 121 | 122 | 123 | /** Boolean Array Property */ 124 | //PropertyBoolArray _boolArrayProp; 125 | //Array &_boolArray; 126 | 127 | /** Integer Property */ 128 | //PropertyInt _intProp; 129 | //int &_int; 130 | 131 | /** Integer Array Property */ 132 | //PropertyIntArray _intArrayProp; 133 | //Array &_intArray; 134 | 135 | /** Double Property */ 136 | //PropertyDbl _dblProp; 137 | //double &_dbl; 138 | 139 | /** Double Array Property */ 140 | //PropertyDblArray _dblArrayProp; 141 | //Array &_dblArray; 142 | 143 | /** Dboule Vec3 Property */ 144 | //PropertyDblVec3 _vec3Prop; 145 | //SimTK::Vec3 &_vec3; 146 | 147 | /** String Property */ 148 | //PropertyStr _strProp; 149 | //std::string &_str; 150 | 151 | /** String Array Property */ 152 | PropertyStrArray _strArrayProp; 153 | Array &_bodyNames; 154 | /*PropertyStrArray _strArrayPropMuscle;*/ 155 | Array _muscleNames; 156 | 157 | // In addition to properties, add any additional member variables 158 | // you need for your analysis. These variables are not read from 159 | // or written to file. They are just variables you use to execute 160 | // your analysis. For example, you will almost certainly need a 161 | // storage object for storing the results of your analysis. 162 | 163 | // Storage object for storing and writing out results. In general, 164 | // each storage file that you create will contain only one kind of data. 165 | // Create a different storage object for each kind of data. For example, 166 | // create a _storePos for positions, _storeVel for velocities, 167 | // _storeAcc for accelerations, etc. */ 168 | 169 | // Indices of bodies for kinematics to be reported and muscle for direction 170 | Array _muscleIndices; 171 | 172 | Array _musclebodies; 173 | 174 | /** Storage for recording body positions and muscle direction*/ 175 | Storage _storeDir; 176 | 177 | /** Internal work arrays to hold muscle directions at each time step. */ 178 | Array _muscledir; 179 | 180 | /** Internal array for storing data to write a second result file (without the storage class) */ 181 | Array _datagroundref; 182 | Array _databodyref; 183 | Array _labels; 184 | 185 | // Markers 186 | std::string _groundname; 187 | int _firstrecord; 188 | 189 | 190 | //============================================================================= 191 | // METHODS 192 | //============================================================================= 193 | public: 194 | /** 195 | * Construct an ForceDirection instance with a Model. 196 | * 197 | * @param aModel Model for which the analysis is to be run. 198 | */ 199 | ForceDirection(Model *aModel=0); 200 | 201 | 202 | /** 203 | * Construct an object from file. 204 | * 205 | * @param aFileName File name of the document. 206 | */ 207 | ForceDirection(const std::string &aFileName); 208 | 209 | /** 210 | * Copy constructor. 211 | */ 212 | ForceDirection(const ForceDirection& aObject); 213 | 214 | //------------------------------------------------------------------------- 215 | // DESTRUCTOR 216 | //------------------------------------------------------------------------- 217 | virtual ~ForceDirection(); 218 | 219 | /** Clone of object */ 220 | virtual Object* copy() const; 221 | private: 222 | /** Zero data and set pointers to Null */ 223 | void setNull(); 224 | 225 | /** 226 | * Set up the properties for the analysis. 227 | * Each property should have meaningful name and an informative comment. 228 | * The name you give each property is the tag that will be used in the XML 229 | * file. The comment will appear before the property in the XML file. 230 | * In addition, the comments are used for tool tips in the OpenSim GUI. 231 | * 232 | * All properties are added to the property set. Once added, they can be 233 | * read in and written to file. 234 | */ 235 | void setupProperties(); 236 | 237 | public: 238 | 239 | #ifndef SWIG 240 | /** 241 | * Assign this object to the values of another. 242 | * 243 | * @return Reference to this object. 244 | */ 245 | ForceDirection& operator=(const ForceDirection &aForceDirection); 246 | #endif 247 | 248 | //========================== Required Methods ============================= 249 | //------------------------------------------------------------------------- 250 | // GET AND SET 251 | //------------------------------------------------------------------------- 252 | virtual void setModel(Model& aModel); 253 | 254 | //------------------------------------------------------------------------- 255 | // INTEGRATION 256 | //------------------------------------------------------------------------- 257 | virtual int 258 | begin(SimTK::State& s); 259 | virtual int 260 | step(const SimTK::State& s, int stepNumber); 261 | virtual int 262 | end(SimTK::State& s); 263 | 264 | //------------------------------------------------------------------------- 265 | // IO 266 | //------------------------------------------------------------------------- 267 | virtual int 268 | printResults(const std::string &aBaseName,const std::string &aDir="", 269 | double aDT=-1.0,const std::string &aExtension=".sto"); 270 | 271 | 272 | protected: 273 | //========================== Internal Methods ============================= 274 | int record(const SimTK::State& s); 275 | void constructDescription(); 276 | void constructColumnLabels(); 277 | void setupStorage(); 278 | 279 | //============================================================================= 280 | }; // END of class ForceDirection 281 | }; //namespace 282 | //============================================================================= 283 | //============================================================================= 284 | 285 | #endif // #ifndef __ForceDirection_h__ 286 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4_prototype/RegisterTypes_osimPlugin.cpp: -------------------------------------------------------------------------------- 1 | // RegisterTypes_osimPlugin.cpp 2 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | /* Copyright (c) 2006 Stanford University 4 | * Use of the OpenSim software in source form is permitted provided that the following 5 | * conditions are met: 6 | * 1. The software is used only for non-commercial research and education. It may not 7 | * be used in relation to any commercial activity. 8 | * 2. The software is not distributed or redistributed. Software distribution is allowed 9 | * only through https://simtk.org/home/opensim. 10 | * 3. Use of the OpenSim software or derivatives must be acknowledged in all publications, 11 | * presentations, or documents describing work in which OpenSim or derivatives are used. 12 | * 4. Credits to developers may not be removed from executables 13 | * created from modifications of the source. 14 | * 5. Modifications of source code must retain the above copyright notice, this list of 15 | * conditions and the following disclaimer. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR BUSINESS INTERRUPTION) OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 25 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include "RegisterTypes_osimPlugin.h" 32 | 33 | #include "ForceDirection.h" 34 | //#include "MyAnalysis.h" 35 | //#include "MyJointReaction.h" 36 | 37 | using namespace OpenSim; 38 | using namespace std; 39 | 40 | static dllObjectInstantiator instantiator; 41 | 42 | //_____________________________________________________________________________ 43 | /** 44 | * The purpose of this routine is to register all class types exported by 45 | * the Plugin library. 46 | */ 47 | OSIMPLUGIN_API void RegisterTypes_osimPlugin() 48 | { 49 | //Object::RegisterType( MyAnalysis() ); 50 | Object::RegisterType( ForceDirection() ); 51 | } 52 | 53 | dllObjectInstantiator::dllObjectInstantiator() 54 | { 55 | registerDllClasses(); 56 | } 57 | 58 | void dllObjectInstantiator::registerDllClasses() 59 | { 60 | RegisterTypes_osimPlugin(); 61 | } 62 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4_prototype/RegisterTypes_osimPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef _RegisterTypes_OsimPlugin_h_ 2 | #define _RegisterTypes_OsimPlugin_h_ 3 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | /* 6 | * Copyright (c) 2005, Stanford University. All rights reserved. 7 | * Use of the OpenSim software in source form is permitted provided that the following 8 | * conditions are met: 9 | * 1. The software is used only for non-commercial research and education. It may not 10 | * be used in relation to any commercial activity. 11 | * 2. The software is not distributed or redistributed. Software distribution is allowed 12 | * only through https://simtk.org/home/opensim. 13 | * 3. Use of the OpenSim software or derivatives must be acknowledged in all publications, 14 | * presentations, or documents describing work in which OpenSim or derivatives are used. 15 | * 4. Credits to developers may not be removed from executables 16 | * created from modifications of the source. 17 | * 5. Modifications of source code must retain the above copyright notice, this list of 18 | * conditions and the following disclaimer. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR BUSINESS INTERRUPTION) OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 28 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "osimPluginDLL.h" 32 | 33 | 34 | extern "C" { 35 | 36 | OSIMPLUGIN_API void RegisterTypes_osimPlugin(); 37 | 38 | } 39 | 40 | class dllObjectInstantiator 41 | { 42 | public: 43 | dllObjectInstantiator(); 44 | private: 45 | void registerDllClasses(); 46 | }; 47 | 48 | 49 | #endif // _RegisterTypes_OsimPlugin_h_ 50 | 51 | 52 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim2.4_prototype/osimPluginDLL.h: -------------------------------------------------------------------------------- 1 | #ifndef _osimPluginDLL_h_ 2 | #define _osimPluginDLL_h_ 3 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 | /* 5 | * Copyright (c) 2005, Stanford University. All rights reserved. 6 | * Use of the OpenSim software in source form is permitted provided that the following 7 | * conditions are met: 8 | * 1. The software is used only for non-commercial research and education. It may not 9 | * be used in relation to any commercial activity. 10 | * 2. The software is not distributed or redistributed. Software distribution is allowed 11 | * only through https://simtk.org/home/opensim. 12 | * 3. Use of the OpenSim software or derivatives must be acknowledged in all publications, 13 | * presentations, or documents describing work in which OpenSim or derivatives are used. 14 | * 4. Credits to developers may not be removed from executables 15 | * created from modifications of the source. 16 | * 5. Modifications of source code must retain the above copyright notice, this list of 17 | * conditions and the following disclaimer. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 22 | * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 24 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR BUSINESS INTERRUPTION) OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 27 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | // UNIX PLATFORM 31 | #ifndef WIN32 32 | 33 | #define OSIMPLUGIN_API 34 | 35 | // WINDOWS PLATFORM 36 | #else 37 | 38 | #define WIN32_LEAN_AND_MEAN 39 | #define NOMINMAX 40 | #include 41 | #ifdef OSIMPLUGIN_EXPORTS 42 | #define OSIMPLUGIN_API __declspec(dllexport) 43 | #else 44 | #define OSIMPLUGIN_API __declspec(dllimport) 45 | #endif 46 | 47 | #endif // PLATFORM 48 | 49 | 50 | #endif // __osimPluginDLL_h__ 51 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim3.3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8.5) 2 | project(MuscleForceDirection) 3 | 4 | set(CMAKE_BUILD_TYPE Release) 5 | 6 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}) 7 | find_package(OpenSim) 8 | 9 | add_subdirectory(lib) 10 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim3.3/FindOpenSim.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find OpenSim and SimTK 2 | # Once done this will define 3 | # OPENSIM_FOUND - System has OpenSim 4 | # OPENSIM_INCLUDE_DIRS - The OpenSim include directories 5 | # SIMTK_INCLUDE_DIRS - The SimTK include directories 6 | # OPENSIM_LIBRARIES - The libraries needed to use Opensim 7 | # OPENSIM_DEFINITIONS - Compiler switches required for using OpenSim 8 | 9 | 10 | set(OPENSIM_POSSIBLE_DIRECTORIES 11 | # ~/Programs/opensim 12 | $ENV{OPENSIM_HOME} 13 | # "C:/OpenSim\ 3.0/"# 14 | # "C:/OpenSim3.1/" 15 | ) 16 | 17 | find_path(OPENSIM_INCLUDE_DIRS OpenSim/OpenSim.h 18 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 19 | PATH_SUFFIXES sdk/include ) 20 | MESSAGE( STATUS "OpenSim Include path: ${OPENSIM_INCLUDE_DIRS}") 21 | 22 | find_path(SIMTK_INCLUDE_DIRS Simbody.h 23 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 24 | PATH_SUFFIXES sdk/include/SimTK/include sdk/include/SimTK/simbody) 25 | MESSAGE( STATUS "SimTK Include path: ${SIMTK_INCLUDE_DIRS}") 26 | 27 | #find_path(OPENSIM_LIBS_DIR 28 | # NAMES 29 | # osimCommon.lib 30 | # osimCommon.so 31 | # libosimCommon.so 32 | # PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 33 | # PATH_SUFFIXES sdk/lib lib) 34 | #MESSAGE( STATUS "OpenSim Lib path: ${OPENSIM_LIBS_DIR}") 35 | 36 | #why? 37 | find_path(OPENSIM_DLL_DIR 38 | NAMES 39 | osimCommon.dll 40 | # id 41 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 42 | PATH_SUFFIXES bin) 43 | MESSAGE( STATUS "OpenSim dll path: ${OPENSIM_DLL_DIR}") 44 | 45 | #SET(OPENSIM_LIBRARY_DIRS ${OPENSIM_LIBS_DIR} ${OPENSIM_DLL_DIR}) 46 | #MESSAGE( STATUS "OpenSim Library path: ${OPENSIM_LIBRARY_DIRS}") 47 | 48 | if(UNIX) 49 | set(NameSpace ) 50 | else() 51 | set(NameSpace OpenSim_) 52 | endif() 53 | 54 | find_library(osimSimulation 55 | NAMES osimSimulation 56 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 57 | PATH_SUFFIXES sdk/lib lib) 58 | 59 | find_library(osimCommon 60 | NAMES osimCommon 61 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 62 | PATH_SUFFIXES sdk/lib lib) 63 | 64 | find_library(osimActuators 65 | NAMES osimActuators 66 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 67 | PATH_SUFFIXES sdk/lib lib) 68 | 69 | find_library(osimAnalyses 70 | NAMES osimAnalyses 71 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 72 | PATH_SUFFIXES sdk/lib lib) 73 | 74 | find_library(osimTools 75 | NAMES osimTools 76 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 77 | PATH_SUFFIXES sdk/lib lib) 78 | 79 | find_library(${NameSpace}SimTKcommon 80 | NAMES ${NameSpace}SimTKcommon SimTKcommon 81 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 82 | PATH_SUFFIXES sdk/lib lib) 83 | 84 | find_library(${NameSpace}SimTKmath 85 | NAMES ${NameSpace}SimTKmath SimTKmath 86 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 87 | PATH_SUFFIXES sdk/lib lib) 88 | 89 | find_library(${NameSpace}SimTKsimbody SimTKsimbody 90 | NAMES ${NameSpace}SimTKsimbody 91 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 92 | PATH_SUFFIXES sdk/lib lib) 93 | #does this exist? 94 | find_library(SimTKlapack 95 | NAMES SimTKlapack lapack 96 | PATHS ${OPENSIM_POSSIBLE_DIRECTORIES} 97 | PATH_SUFFIXES sdk/lib lib) 98 | 99 | set(OPENSIM_LIBRARIES ${osimSimulation} ${osimCommon} ${osimActuators} ${osimAnalyses} ${osimTools} ${${NameSpace}SimTKcommon} ${${NameSpace}SimTKmath} ${${NameSpace}SimTKsimbody} ${${NameSpace}SimTKlapack} ${SimTKlapack}) 100 | 101 | 102 | #IF(WIN32) 103 | # SET(PLATFORM_LIBS pthreadVC2) 104 | #ELSE (WIN32) 105 | # SET(NameSpace "") 106 | # IF(APPLE) 107 | # SET(PLATFORM_LIBS SimTKAtlas) 108 | # ELSE(APPLE) 109 | # SET(PLATFORM_LIBS SimTKAtlas_Lin_generic) 110 | # ENDIF(APPLE) 111 | #ENDIF (WIN32) 112 | 113 | include(FindPackageHandleStandardArgs) 114 | # handle the QUIETLY and REQUIRED arguments and set OPENSIM_FOUND to TRUE 115 | # if all listed variables are TRUE 116 | # DEFAULT_MSG is predefined... change only if you need a custom msg 117 | find_package_handle_standard_args(OpenSim DEFAULT_MSG 118 | OPENSIM_LIBRARIES OPENSIM_INCLUDE_DIRS SIMTK_INCLUDE_DIRS) 119 | 120 | # Mark the following variables as advanced (they are not displayed in any 121 | # of the cmake GUIs unless the show advanced option is on. 122 | #mark_as_advanced(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARY ) 123 | 124 | 125 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim3.3/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(MuscleForceDirection) -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim3.3/lib/MuscleForceDirection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | Project(MuscleForceDirection) 2 | 3 | 4 | link_directories(${OPENSIM_LIBS_DIR}) 5 | 6 | set(MuscleForceDirection_HEADERS 7 | MuscleForceDirection.h RegisterTypes_osimPlugin.h osimPluginDLL.h) 8 | 9 | set(MuscleForceDirection_SOURCES 10 | MuscleForceDirection.cpp RegisterTypes_osimPlugin.cpp) 11 | 12 | source_group("MuscleForceDirection_headers" FILES ${MuscleForceDirection_HEADERS}) 13 | source_group("MuscleForceDirection_sources" FILES ${MuscleForceDirection_SOURCES}) 14 | 15 | 16 | # Define target 17 | add_library(MuscleForceDirection SHARED 18 | ${MuscleForceDirection_HEADERS} 19 | ${MuscleForceDirection_SOURCES} 20 | ) 21 | 22 | target_include_directories(MuscleForceDirection 23 | PUBLIC 24 | ${OPENSIM_INCLUDE_DIRS} 25 | ${SIMTK_INCLUDE_DIRS} 26 | ) 27 | target_link_libraries(MuscleForceDirection ${OPENSIM_LIBRARIES}) 28 | 29 | set_target_properties( 30 | MuscleForceDirection PROPERTIES 31 | DEFINE_SYMBOL OSIMPLUGIN_EXPORTS 32 | PROJECT_LABEL "Libraries - MuscleForceDirection") 33 | 34 | #INSTALL_TARGETS(/plugins RUNTIME_DIRECTORY /plugins MuscleForceDirection) 35 | 36 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim3.3/lib/MuscleForceDirection/MuscleForceDirection.h: -------------------------------------------------------------------------------- 1 | #ifndef _MuscleForceDirection_h_ 2 | #define _MuscleForceDirection_h_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "osimPluginDLL.h"// Header to define plugin (DLL) interface 16 | 17 | namespace OpenSim { 18 | 19 | class Model; 20 | 21 | class OSIMPLUGIN_API MuscleForceDirection : public Analysis 22 | 23 | { 24 | OpenSim_DECLARE_CONCRETE_OBJECT(MuscleForceDirection, Analysis); 25 | 26 | protected: 27 | 28 | // Lines of action in local or global frame. 29 | PropertyBool _expressInLocalFrameProp; 30 | bool &_expressInLocalFrame; 31 | 32 | // Print or not a .sto file with the muscle attachments. 33 | PropertyBool _boolPrintAttachPointProp; 34 | bool &_printAttachPoints; 35 | 36 | // Anatomical muscle insertions or effective muscle insertions. 37 | PropertyBool _boolEffectiveInsertionsProp; 38 | bool &_effectInsertion; 39 | 40 | // string array with the bodies to analyze 41 | PropertyStrArray _strArrayBodyProp; 42 | Array &_bodyNames; 43 | 44 | /*-------------- NOTE --------------- 45 | The original idea was to include the option for the user of 46 | deciding a single muscle to analyze. 47 | This option has been removed as for finite element applications 48 | is generally an entire body (or more) and the forces connected to it 49 | to be of interest. 50 | //string array with the muscles to analyze 51 | //PropertyStrArray _strArrayMuscleProp; 52 | //Array &_muscleNames; 53 | --------------------------------------*/ 54 | 55 | 56 | //========== INTERNAL USE ============== 57 | // Indices of bodies for kinematics to be reported and muscle for direction 58 | Array _muscleIndices; 59 | 60 | // Storage for recording muscle direction 61 | Storage _storeDir; 62 | 63 | // Storage for recording attachment position 64 | Storage _storeAttachPointPos; 65 | 66 | // Internal work arrays to hold muscle directions at each time step. 67 | Array _muscledir; 68 | Array _attachpointpos; 69 | 70 | // ===================================== METHODS ================================== 71 | public: 72 | // CONSTRUCTORS 73 | MuscleForceDirection(Model *aModel=0); 74 | MuscleForceDirection(const std::string &aFileName, bool aUpdateFromXMLNode); 75 | // COPY CONSTRUCTOR 76 | MuscleForceDirection(const MuscleForceDirection& aObject); 77 | // DESTRUCTOR 78 | virtual ~MuscleForceDirection(); 79 | // CLONE 80 | virtual Object* copy() const; 81 | 82 | private: 83 | // ZERO DATA AND NULL POINTERS 84 | void setNull(); 85 | // SETUP PROPERTIES 86 | void setupProperties(); 87 | 88 | public: 89 | 90 | #ifndef SWIG 91 | //Assign this object to the values of another.@return Reference to this object. 92 | MuscleForceDirection& operator=(const MuscleForceDirection &aMuscleForceDirection); 93 | #endif 94 | 95 | //========================== Required Methods ============================= 96 | virtual void setModel(Model& aModel); 97 | // INTEGRATION 98 | virtual int begin(SimTK::State& s); 99 | virtual int step(const SimTK::State& s, int stepNumber); 100 | virtual int end(SimTK::State& s); 101 | // IO 102 | virtual int printResults(const std::string &aBaseName,const std::string &aDir="",double aDT=-1.0,const std::string &aExtension=".sto"); 103 | 104 | protected: 105 | //========================== Internal Methods ============================= 106 | int record(const SimTK::State& s); 107 | void constructDescription(); 108 | void constructColumnLabels(); 109 | void setupStorage(); 110 | 111 | // Utilities implemented by Luca Modenese (check on 15th March 2012). 112 | void constructDescriptionAttachments(); 113 | void setupStorageAttachments(); 114 | static Array getMusclesIndexForBody(Model* model, const Array& bodyNames); 115 | static bool isMuscleAttachedToBody(const OpenSim::Muscle& aMuscle, const std::string& aBodyName); 116 | static void getEffectiveAttachments(const Array& aPFDs, int& effecInsertProx, int& effecInsertDist); 117 | inline void NormalizeVec3(SimTK::Vec3 & v1, SimTK::Vec3 & rNormv1); 118 | 119 | }; // END of class MuscleForceDirection 120 | 121 | }; //namespace 122 | #endif // #ifndef __AnalysisPlugin_Template_h__ 123 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim3.3/lib/MuscleForceDirection/RegisterTypes_osimPlugin.cpp: -------------------------------------------------------------------------------- 1 | // RegisterTypes_osimPlugin.cpp 2 | /* -------------------------------------------------------------------------- * 3 | * OpenSim: RegisterTypes_osimPlugin.cpp * 4 | * -------------------------------------------------------------------------- * 5 | * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. * 6 | * See http://opensim.stanford.edu and the NOTICE file for more information. * 7 | * OpenSim is developed at Stanford University and supported by the US * 8 | * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA * 9 | * through the Warrior Web program. * 10 | * * 11 | * Copyright (c) 2005-2017 Stanford University and the Authors * 12 | * * 13 | * Licensed under the Apache License, Version 2.0 (the "License"); you may * 14 | * not use this file except in compliance with the License. You may obtain a * 15 | * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 16 | * * 17 | * Unless required by applicable law or agreed to in writing, software * 18 | * distributed under the License is distributed on an "AS IS" BASIS, * 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 20 | * See the License for the specific language governing permissions and * 21 | * limitations under the License. * 22 | * -------------------------------------------------------------------------- */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include "RegisterTypes_osimPlugin.h" 28 | //#include "MyAnalysis.h" 29 | #include "MuscleForceDirection.h" 30 | 31 | using namespace OpenSim; 32 | using namespace std; 33 | 34 | static dllObjectInstantiator instantiator; 35 | 36 | //_____________________________________________________________________________ 37 | /** 38 | * The purpose of this routine is to register all class types exported by 39 | * the Plugin library. 40 | */ 41 | OSIMPLUGIN_API void RegisterTypes_osimPlugin() 42 | { 43 | //Object::RegisterType( MyAnalysis() ); 44 | Object::RegisterType( MuscleForceDirection() ); 45 | } 46 | 47 | dllObjectInstantiator::dllObjectInstantiator() 48 | { 49 | registerDllClasses(); 50 | } 51 | 52 | void dllObjectInstantiator::registerDllClasses() 53 | { 54 | RegisterTypes_osimPlugin(); 55 | } 56 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim3.3/lib/MuscleForceDirection/RegisterTypes_osimPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef _RegisterTypes_OsimPlugin_h_ 2 | #define _RegisterTypes_OsimPlugin_h_ 3 | 4 | /* -------------------------------------------------------------------------- * 5 | * OpenSim: RegisterTypes_osimPlugin.h * 6 | * -------------------------------------------------------------------------- * 7 | * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. * 8 | * See http://opensim.stanford.edu and the NOTICE file for more information. * 9 | * OpenSim is developed at Stanford University and supported by the US * 10 | * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA * 11 | * through the Warrior Web program. * 12 | * * 13 | * Copyright (c) 2005-2017 Stanford University and the Authors * 14 | * * 15 | * Licensed under the Apache License, Version 2.0 (the "License"); you may * 16 | * not use this file except in compliance with the License. You may obtain a * 17 | * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 18 | * * 19 | * Unless required by applicable law or agreed to in writing, software * 20 | * distributed under the License is distributed on an "AS IS" BASIS, * 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 22 | * See the License for the specific language governing permissions and * 23 | * limitations under the License. * 24 | * -------------------------------------------------------------------------- */ 25 | 26 | #include "osimPluginDLL.h" 27 | 28 | //COMPATIBILE CON C: #ifndef: http://forum.html.it/forum/showthread/t-1335669.html 29 | extern "C" 30 | 31 | { 32 | OSIMPLUGIN_API void RegisterTypes_osimPlugin(); 33 | } 34 | 35 | class dllObjectInstantiator 36 | { 37 | public: 38 | dllObjectInstantiator(); 39 | private: 40 | void registerDllClasses(); 41 | }; 42 | 43 | #endif // _RegisterTypes_OsimPlugin_h_ 44 | 45 | 46 | -------------------------------------------------------------------------------- /CPP/legacy_code/OpenSim3.3/lib/MuscleForceDirection/osimPluginDLL.h: -------------------------------------------------------------------------------- 1 | // SUPPORT MATERIAL 2 | 3 | // #ifndef: http://forum.html.it/forum/showthread/t-1335669.html 4 | // #DEFINE: http://msdn.microsoft.com/en-us/library/teas0593%28v=vs.80%29.aspx 5 | 6 | #ifndef _osimPluginDLL_h_ 7 | #define _osimPluginDLL_h_ 8 | 9 | // UNIX PLATFORM 10 | #ifndef WIN32 11 | 12 | #define OSIMPLUGIN_API 13 | 14 | // WINDOWS PLATFORM 15 | #else 16 | // removes some headers from 17 | #define WIN32_LEAN_AND_MEAN //http://blogs.msdn.com/b/oldnewthing/archive/2009/11/30/9929944.aspx 18 | #define NOMINMAX //http://stackoverflow.com/questions/4913922/possible-problems-with-nominmax-on-visual-c 19 | #include 20 | 21 | #ifdef OSIMPLUGIN_EXPORTS 22 | #define OSIMPLUGIN_API __declspec(dllexport) 23 | #else 24 | #define OSIMPLUGIN_API __declspec(dllimport) 25 | #endif 26 | 27 | #endif // PLATFORM 28 | #endif // __osimPluginDLL_h__ 29 | -------------------------------------------------------------------------------- /CPP/legacy_code/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Code originally exported from svn repository set up at 4 | https://simtk.org/projects/force_direction. It was rearranged for 5 | this repository, which is the one currently supported. 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright [2020] [Luca Modenese] 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /MATLAB/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.asv 3 | /test_results/ -------------------------------------------------------------------------------- /MATLAB/TEST_plugin.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % Author: Luca Modenese % 4 | % email: l.modenese@imperial.ac.uk % 5 | % ----------------------------------------------------------------------- % 6 | 7 | %% TEST1: use model built on purpose to test 8 | 9 | % Load Library 10 | import org.opensim.modeling.*; 11 | 12 | % verification 13 | osimModel_name = '../tests/MFD_tests/testModel.osim'; 14 | IK_mot_file = '../tests/MFD_tests/testKinematics_file.mot'; 15 | MFD_sto_file = './test_results/test1.sto'; 16 | bodyOfInterest_name = 'MovingBody'; 17 | bodyExpressResultsIn_name = 'ground'; 18 | effec_att = 'false'; 19 | test_input = []; 20 | vis_on = 'false'; 21 | 22 | validated_results_folder = '../_test_data/MFD_tests/validated_res'; 23 | 24 | res_anatAttach_local = getMuscleForceDirection(osimModel_name,... 25 | IK_mot_file,... 26 | MFD_sto_file,... 27 | bodyOfInterest_name,... 28 | bodyExpressResultsIn_name,... 29 | effec_att,... 30 | vis_on,... 31 | []); 32 | 33 | % res_effectAttach_local = getMuscleForceDirection(osimModel_name,... 34 | % IK_mot_file,... 35 | % bodyOfInterest_name,... 36 | % bodyExpressResultsIn_name,... 37 | % 'true',... 38 | % vis_on,... 39 | % []); 40 | % 41 | % res_effectAttach_ground = getMuscleForceDirection(osimModel_name,... 42 | % IK_mot_file,... 43 | % bodyOfInterest_name,... 44 | % 'ground',... 45 | % 'true',... 46 | % vis_on,... 47 | % []); 48 | % 49 | % res_anatAttach_ground = getMuscleForceDirection(osimModel_name,... 50 | % IK_mot_file,... 51 | % bodyOfInterest_name,... 52 | % 'ground',... 53 | % 'false',... 54 | % vis_on,... 55 | % []); 56 | 57 | 58 | % res_anatAttach_local 59 | % res_anatAttach_ground 60 | % res_effectAttach_ground 61 | % res_effectAttach_local 62 | % 63 | % res_anatAttach_local_val = sto2Mat(fullfile(validated_results_folder,'LOCAL_ANATOM_MuscleForceDirection_vectors.sto')); 64 | % 65 | % res_anatAttach_ground.rowheaders 66 | % res_effectAttach_ground 67 | % res_effectAttach_local 68 | %-------------------------------------------------------------------------- 69 | %% TEST3: simple arm26 model 70 | osimModel_name = '../test_data/Arm26/arm26.osim'; 71 | IK_mot_file = '../test_data/Arm26/elbow_flexion.mot'; 72 | bodyOfInterest_name = 'r_humerus'; 73 | bodyExpressResultsIn_name = 'ground'; 74 | effective_attachm = 'false'; 75 | test_input = []; 76 | % 77 | % 78 | % N_frame_test = 5; 79 | muscleLinesOfActionStruct = getMuscleForceDirection(osimModel_name,... 80 | IK_mot_file,... 81 | bodyOfInterest_name,... 82 | bodyExpressResultsIn_name,... 83 | effective_attachm,... 84 | 'true',... 85 | []); 86 | 87 | %% TEST3: gait2392 model 88 | 89 | osimModel_name = '../tests/gait2392/subject01.osim'; 90 | IK_mot_file = '../tests/gait2392/subject01_walk1_ik.mot'; 91 | bodyOfInterest_name = 'femur_r'; 92 | bodyExpressResultsIn_name = []; 93 | effective_attachm = 'true'; 94 | test_input = []; 95 | N_frame_test = 5; 96 | muscleLinesOfActionStruct = getMuscleForceDirection(osimModel_name,... 97 | IK_mot_file,... 98 | bodyOfInterest_name,... 99 | bodyExpressResultsIn_name,... 100 | effective_attachm,... 101 | 'true',... 102 | []); -------------------------------------------------------------------------------- /MATLAB/_dev_deal_withMuscleWrap.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % Author: Luca Modenese % 4 | % email: l.modenese@imperial.ac.uk % 5 | % ----------------------------------------------------------------------- % 6 | 7 | clear;clc 8 | import org.opensim.modeling.* 9 | 10 | % TO DO: add the possibility of following states 11 | %%%%%%%%%%%%% SET UP %%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % General model 13 | ModelFile = 'arm26.osim'; 14 | % read model 15 | osimModel = Model(ModelFile); 16 | muscles = osimModel.getMuscles(); 17 | aOsimMuscleNameSet = 'all';%{'BRA'}; 18 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 19 | 20 | 21 | % setting which muscles will be followed 22 | muscleNames = ArrayStr; 23 | if strcmp(aOsimMuscleNameSet,'all') 24 | % getmuscles 25 | muscles.getNames(muscleNames); 26 | else 27 | % assign given muscle names to the set to be analyzed 28 | for n_mn = 1:length( aOsimMuscleNameSet ) 29 | muscleNames.append(aOsimMuscleNameSet{n_mn}) 30 | end 31 | end 32 | 33 | for n_mus = 0:muscleNames.getSize()-1 34 | 35 | % current muscle 36 | curr_muscle = muscles.get(muscleNames.getitem(n_mus)); 37 | 38 | % EXTRACTING THE WRAPPING POINTS 39 | si = osimModel.initSystem(); 40 | 41 | % get the geometry path for the current state 42 | PathpointArray = curr_muscle.getGeometryPath().getCurrentPath(si); 43 | 44 | % normal pathpoints attached to bodies 45 | ModelPathpoint = curr_muscle.getGeometryPath().getPathPointSet(); 46 | 47 | % check if there are wrapping points 48 | NrOfWrappingPoints = PathpointArray.getSize()-ModelPathpoint.getSize(); 49 | 50 | % header 51 | display(['Muscle ',char(curr_muscle.getName()), ' (',num2str(NrOfWrappingPoints),' wrapping points)']); 52 | 53 | for n_p = 0:PathpointArray.getSize()-1 54 | 55 | % get the coordinates of the current pathpoint 56 | curr_point_loc_OS = Vec3(PathpointArray.getitem(n_p).getLocation); 57 | curr_point_loc = [curr_point_loc_OS.get(0),curr_point_loc_OS.get(1),curr_point_loc_OS.get(2)]; 58 | 59 | % body where the body is attached to 60 | display(['Point ',num2str(n_p+1), ' attached to body ',char(PathpointArray.getitem(n_p).getBodyName())]); 61 | display([num2str(curr_point_loc_OS.get(0)),' ',num2str(curr_point_loc_OS.get(1)),' ',num2str(curr_point_loc_OS.get(2))]) 62 | 63 | end 64 | display('-----------------------------------'); 65 | end -------------------------------------------------------------------------------- /MATLAB/getMuscleForceDirection.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % This function replicates in MATLAB the functionalities of the 19 | % MuscleForceDirection OpenSim plugin available at 20 | % https://simtk.org/projects/force_direction 21 | % 22 | % Given an OpenSim model, a body of interest and a pre-computed kinematics 23 | % the script will return the lines of action of the muscles. 24 | % 25 | % The output a matrix with frames as rows 26 | % 27 | % TODO: comment 28 | % TODO: deal with joints 29 | % TODO: test script 30 | % 31 | % created: 32 | % 29 Nov 2018: created based on functions for other purposes and added to 33 | % MFD Matlab toolbox. 34 | % ------------------------------------------------------------------------% 35 | function [MFD, MFDSumStruct] = getMuscleForceDirection(osimModel_name,... 36 | IK_mot_file,... 37 | MFD_sto_file,... 38 | bodyOfInterest_name,... 39 | bodyExpressResultsIn_name,... 40 | effective_attachm,... 41 | visualise,... 42 | test_input) 43 | 44 | % Load Library 45 | import org.opensim.modeling.*; 46 | 47 | % read model 48 | osimModel = Model(osimModel_name); 49 | 50 | % import kinematics as mat structure 51 | IKStruct = sto2Mat(IK_mot_file); 52 | 53 | % check feasibility of the requested operation 54 | isBodyInModel(osimModel, bodyOfInterest_name); 55 | 56 | % TODO: deal with multiple body expressed in distinct reference systems by 57 | % creating a loop here and using cell arrays. 58 | 59 | % get body of interest 60 | bodyOfInterest = osimModel.getBodySet.get(bodyOfInterest_name); 61 | 62 | % get body where results will be expressed 63 | % (if different from body of interest) 64 | if strcmp(bodyExpressResultsIn_name, bodyOfInterest_name)==1 65 | bodyExpressResultsIn = bodyOfInterest; 66 | else 67 | if isempty(bodyExpressResultsIn_name)==1 68 | bodyExpressResultsIn_name = bodyOfInterest_name; 69 | bodyExpressResultsIn = bodyOfInterest; 70 | else 71 | isBodyInModel(osimModel, bodyExpressResultsIn_name) 72 | bodyExpressResultsIn = osimModel.getBodySet.get(bodyExpressResultsIn_name); 73 | end 74 | end 75 | 76 | % define muscles to include in the analysis 77 | % get muscles 78 | muscleSet = osimModel.getMuscles(); 79 | n_keep = 1; 80 | for n_m = 0:muscleSet.getSize()-1 81 | 82 | % extract muscle 83 | curr_mus = muscleSet.get(n_m); 84 | curr_mus_name = char(muscleSet.get(n_m).getName()); 85 | 86 | % check if muscle is attached (1) or not (0) to bone of interest 87 | % left in internal loop to handle conditional viapoints, if 88 | % necessary. They might be active only at certain states, therefore 89 | % it is risky to exclude muscles a priori. 90 | % NO! CANNOT CHANGE ORIGIN OR INSERTION 91 | musc_attach = isMuscleConnectedToBody(curr_mus, bodyOfInterest_name); 92 | 93 | if musc_attach == 1 94 | target_mus_names{n_keep} = curr_mus_name; 95 | 96 | % defining headers as well 97 | rowheaders{n_keep,1} = curr_mus_name; 98 | store_range = 1+3*(n_keep-1):3+3*(n_keep-1); 99 | colheaders_MFD_vec(store_range) = { [curr_mus_name,'_vx_in_',bodyExpressResultsIn_name],... 100 | [curr_mus_name,'_vy_in_',bodyExpressResultsIn_name],... 101 | [curr_mus_name,'_vz_in_',bodyExpressResultsIn_name]}; 102 | colheaders_MFD_attach(store_range) = { [curr_mus_name,'_px_in_',bodyExpressResultsIn_name],... 103 | [curr_mus_name,'_py_in_',bodyExpressResultsIn_name],... 104 | [curr_mus_name,'_pz_in_',bodyExpressResultsIn_name]}; 105 | n_keep = n_keep +1; 106 | end 107 | end 108 | 109 | N_target_muscles = length(target_mus_names); 110 | 111 | % current state. It will change according to kinematics 112 | if strcmp(visualise, 'true') 113 | osimModel.setUseVisualizer(true); 114 | end 115 | curr_state = osimModel.initSystem(); 116 | 117 | % number of frames 118 | N_frames = size(IKStruct.data,1); 119 | % this is a testing option to reduce processed kinematics frames when 120 | % developing related functions 121 | if ~isempty(test_input) 122 | N_frames = test_input; 123 | end 124 | 125 | % Variables could be preallocated for speed, but I didn't like to have all 126 | % zeros, which might be confused with actual values from the analysis. 127 | % mus_info_mat = zeros(muscleSet.getSize(),12, N_frames); 128 | for n_frame = 1:N_frames 129 | 130 | % realize kinematics 131 | state_new = realizeMatStructKinematics(osimModel, curr_state, IKStruct, n_frame); 132 | if strcmp(visualise, 'true') 133 | osimModel.updVisualizer().show(state_new); 134 | end 135 | 136 | % counter for muscles to be kept at each frame 137 | n_keep = 1; 138 | 139 | % display time progression 140 | %disp('--------------------'); 141 | disp(['FRAME: ',num2str(n_frame),'/',num2str(N_frames)]); 142 | %disp('--------------------'); 143 | 144 | for n_m = 0:N_target_muscles-1 145 | 146 | % extract muscle 147 | curr_mus_name = target_mus_names{n_m+1}; 148 | curr_mus = muscleSet.get(curr_mus_name); 149 | 150 | % loop through the points 151 | % this print is too fast to be useful apart from debugging 152 | % disp(['Processing muscle (',num2str(n_m+1),'/',num2str(N_target_muscles),'): ', curr_mus_name]); 153 | 154 | % make available info about the muscle pointSet (body names 155 | % and points coordinates) 156 | [mus_bodyset_list, mus_pointset_mat] = getCurrentMusclePathAsMat(curr_mus, state_new); 157 | 158 | % the vector allows 3 cases: 159 | % 1) muscle STARTS from bone if interest, 160 | % 2) muscle has via point through the bone of interest but no attachments 161 | % 3) muscle ENDS at the bone of interest 162 | % ALL VECTORS FROM BONE OUT! 163 | 164 | % vector of muscle attachments in the bone of interest 165 | attach_vec = strcmp(mus_bodyset_list, bodyOfInterest_name); 166 | ind_attachms = find(attach_vec); 167 | 168 | 169 | % proximal and distal attachments on body of interest 170 | % NB ASSUMPTION THAT THE MUSCLE POINTS ARE NUMBERED FROM 171 | % PROXIMAL TO DISTAL 172 | prox_attach = min(ind_attachms); 173 | dist_attach = max(ind_attachms); 174 | 175 | % setting for transform operation later on 176 | otherBodyAttach = Vec3(0); 177 | 178 | % CASE 1 179 | if attach_vec(1)==0 && attach_vec(end)==0 180 | % This case is for multi-articular muscles that jump the 181 | % body and can be attached with a viapoint. 182 | display(['Muscle has only viapoints (no bone attachments) on ',bodyOfInterest_name,'. Skipping...']); 183 | continue 184 | end 185 | 186 | % CASE 2: muscle that starts at bone of interest 187 | if attach_vec(1)==1 && attach_vec(end)==0 % muscle starts here 188 | ori = mus_pointset_mat(1, :); 189 | lastAttach = mus_pointset_mat(dist_attach, :); 190 | bone_attachment = ori; 191 | 192 | % first body outside the body of interest 193 | bodyFrom = osimModel.getBodySet.get(mus_bodyset_list{dist_attach+1}); 194 | 195 | % vector in bodyFrom ref system 196 | p = Vec3(mus_pointset_mat(dist_attach+1, 1),... 197 | mus_pointset_mat(dist_attach+1, 2),... 198 | mus_pointset_mat(dist_attach+1, 3)); 199 | 200 | end 201 | 202 | % CASE 3: muscle that ends at bone of interest 203 | if attach_vec(1)==0 && attach_vec(end)==1 % muscle starts here 204 | ins = mus_pointset_mat(end, :); 205 | lastAttach = mus_pointset_mat(prox_attach,:); 206 | bone_attachment = ins; 207 | 208 | % first body outside the body of interest 209 | bodyFrom = osimModel.getBodySet.get(mus_bodyset_list{prox_attach-1}); 210 | % vector in bodyFrom ref system 211 | p = Vec3( mus_pointset_mat(prox_attach-1, 1),... 212 | mus_pointset_mat(prox_attach-1, 2),... 213 | mus_pointset_mat(prox_attach-1, 3)); 214 | 215 | end 216 | 217 | % transformating everything in body of interest ref system 218 | osimModel.getSimbodyEngine.transformPosition(state_new, bodyFrom, p, bodyOfInterest, otherBodyAttach) 219 | otherBodyAttach_vec = [otherBodyAttach.get(0), otherBodyAttach.get(1), otherBodyAttach.get(2)]; 220 | 221 | % normalized force direction 222 | force_dir_norm = (otherBodyAttach_vec-lastAttach)/norm(otherBodyAttach_vec-lastAttach); 223 | 224 | % computing transport moment at bone attachment 225 | bone_to_lastAttach_vec = lastAttach-bone_attachment; 226 | transp_mom_norm = cross(force_dir_norm', bone_to_lastAttach_vec'); 227 | 228 | % transforming force directions in body where results should be 229 | % expressed 230 | transf_force_dir_norm = Vec3(0); 231 | force_dir_norm_Vec3 = Vec3(force_dir_norm(1), force_dir_norm(2), force_dir_norm(3)); 232 | osimModel.getSimbodyEngine.transform(state_new, bodyOfInterest, force_dir_norm_Vec3, bodyExpressResultsIn, transf_force_dir_norm); 233 | force_dir_res = [transf_force_dir_norm.get(0), transf_force_dir_norm.get(1), transf_force_dir_norm.get(2)]; 234 | 235 | % fill the matrix with the calculated values 236 | col_ind = 1+3*(n_keep-1):3+3*(n_keep-1); 237 | mus_info_mat(n_frame, col_ind, 1) = bone_attachment; 238 | mus_info_mat(n_frame, col_ind, 2) = lastAttach; 239 | mus_info_mat(n_frame, col_ind, 3) = force_dir_res; 240 | mus_info_mat(n_frame, col_ind, 4) = transp_mom_norm; 241 | 242 | n_keep = n_keep + 1; 243 | % clear variables to avoid surprises 244 | clear attachment force_dir_norm transp_mom_norm lastAttach otherBodyAttach_vec force_dir_res 245 | 246 | % end 247 | end 248 | end 249 | 250 | % time vector 251 | time_v = getMatStructColumn(IKStruct, 'time'); 252 | 253 | %----------- OUTPUT FILES ------------ 254 | % Output files are the same as the C++ plugin. 255 | % Names and descriptions are taken from the manual 256 | [p, n, e] = fileparts(MFD_sto_file); 257 | MFD_sto_file_att = fullfile(p, [n,'_MuscleForceDirection_attachments', e]); 258 | MFD_sto_file_vec = fullfile(p, [n,'_MuscleForceDirection_vectors', e]); 259 | 260 | %----------------------------------- 261 | % MuscleForceDirection_vectors.sto | 262 | %----------------------------------- 263 | % this file contains the normalized vectors representing the directions 264 | % of the muscle lines of action. The vector is always pointing from the 265 | % selected body where the attachment is located outwards. The body in whose 266 | % reference system the vector is expressed is always reported as the final 267 | % part of the column header of each muscle. 268 | MFD.vectors.colheaders = [{'time'} colheaders_MFD_vec]; 269 | MFD.vectors.data = [time_v, mus_info_mat(:, :, 3)]; 270 | MFD_vec_descr = ['the normalized muscle lines of action expressed in ',... 271 | bodyExpressResultsIn_name, ... 272 | ' reference system']; 273 | % write file 274 | Mat2sto(MFD.vectors, MFD_sto_file_vec, MFD_vec_descr) 275 | 276 | %--------------------------------------- 277 | % MuscleForceDirection_attachments.sto | 278 | %--------------------------------------- 279 | % this file is optional and prints the coordinates of the muscle 280 | % attachments. If the user choice is to express the anatomical muscle 281 | % attachments in the local reference system, the file will contain the 282 | % first and last muscle points specified for that muscle in the original model file. 283 | 284 | MFD.attach.colheaders = [{'time'}, colheaders_MFD_attach]; 285 | 286 | % check if anatomical or effective attachments are required 287 | if strcmp(effective_attachm, 'true') 288 | % effective attachment if required 289 | MFD.attach.data = [time_v, mus_info_mat(:, :, 2)]; 290 | descr = 'effective'; 291 | else 292 | % anatomical attachments by default 293 | MFD.attach.data = [time_v, mus_info_mat(:, :, 1)]; 294 | descr = 'amatomical'; 295 | end 296 | 297 | MFD_attach_descr = ['the ',descr ,' position of the muscle attachments expressed in ',... 298 | bodyExpressResultsIn_name, ... 299 | ' reference system']; 300 | Mat2sto(MFD.attach, MFD_sto_file_att, MFD_attach_descr) 301 | 302 | %---------------------------------------- 303 | % MuscleForceDirection_transp_moment.sto | 304 | %---------------------------------------- 305 | % this will write a sto file for transport moment. 306 | % MFD.transp_mom.colheaders = colheaders_MFD_vec; 307 | % MFD.transp_mom.data = mus_info_mat(:, :, 4); 308 | 309 | 310 | %-------------------------- 311 | % Advanced MATLAB summary | 312 | %-------------------------- 313 | % The idea is to have a matrix with frames as rows and in column bone 314 | % attachments, effective attachments, lines of action and transport 315 | % moments. 316 | colheaders = {'bone_attach_X', 'bone_attach_Y', 'bone_attach_Z', 'effect_attach_X', 'effect_attach_Y', 'effect_attach_Z', ... 317 | 'act_line_X', 'act_line_Y', 'act_line_Z', 'trans_mom_X', 'trans_mom_Y', 'trans_mom_Z'}; 318 | % this is an advanced summary for Matlab use 319 | MFDSumStruct.colheaders = colheaders; 320 | MFDSumStruct.rowheaders = rowheaders; 321 | MFDSumStruct.data = mus_info_mat; 322 | 323 | % free the memory 324 | osimModel.disownAllComponents(); 325 | 326 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.asv 3 | -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/MFD matlab tool v4.0 update notes (K. Song WUSTL).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/MATLAB/matlab_tool_v4.0/MFD matlab tool v4.0 update notes (K. Song WUSTL).pdf -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/TEST_plugin.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % Author: Luca Modenese % 4 | % email: l.modenese@imperial.ac.uk % 5 | % ----------------------------------------------------------------------- % 6 | % Load Library 7 | import org.opensim.modeling.*; 8 | 9 | % verification 10 | osimModel_name = '../_test_data/MFD_tests/testModel.osim'; 11 | IK_mot_file = '../_test_data/MFD_tests/testKinematics_file.mot'; 12 | results_directory = '../_test_data/MFD_tests'; 13 | bodyOfInterest_name = 'MovingBody'; 14 | bodyExpressResultsIn_name = []; 15 | effective_attachm = 'false'; 16 | print_attachm = 'true'; 17 | vis_on = 'true'; 18 | N_frame_test = 5; 19 | 20 | % validated_results_folder = '../_test_data/MFD_tests/validated_res'; 21 | 22 | res_anatAttach_local = getMuscleForceDirection(osimModel_name,... 23 | IK_mot_file,... 24 | results_directory,... 25 | bodyOfInterest_name,... 26 | bodyExpressResultsIn_name,... 27 | effective_attachm,... 28 | print_attachm,... 29 | vis_on,... 30 | N_frame_test); 31 | 32 | % res_effectAttach_local = getMuscleForceDirection(osimModel_name,... 33 | % IK_mot_file,... 34 | % results_directory,... 35 | % bodyOfInterest_name,... 36 | % bodyExpressResultsIn_name,... 37 | % 'true',... 38 | % print_attachm,... 39 | % vis_on,... 40 | % []); 41 | % 42 | % res_effectAttach_ground = getMuscleForceDirection(osimModel_name,... 43 | % IK_mot_file,... 44 | % results_directory,... 45 | % bodyOfInterest_name,... 46 | % 'ground',... 47 | % 'true',... 48 | % print_attachm,... 49 | % vis_on,... 50 | % []); 51 | % 52 | % res_anatAttach_ground = getMuscleForceDirection(osimModel_name,... 53 | % IK_mot_file,... 54 | % results_directory,... 55 | % bodyOfInterest_name,... 56 | % 'ground',... 57 | % 'false',... 58 | % print_attachm,... 59 | % vis_on,... 60 | % []); 61 | 62 | 63 | % res_anatAttach_local 64 | % res_anatAttach_ground 65 | % res_effectAttach_ground 66 | % res_effectAttach_local 67 | % 68 | % res_anatAttach_local_val = sto2Mat(fullfile(validated_results_folder,'LOCAL_ANATOM_MuscleForceDirection_vectors.sto')); 69 | % 70 | % res_anatAttach_ground.rowheaders 71 | % res_effectAttach_ground 72 | % res_effectAttach_local 73 | %-------------------------------------------------------------------------- 74 | % %% test 1: simple arm26 model 75 | % osimModel_name = '../_test_data/Arm26/arm26.osim'; 76 | % IK_mot_file = '../_test_data/Arm26/elbow_flexion.mot'; 77 | % results_directory = '../_test_data/Arm26'; 78 | % bodyOfInterest_name = 'r_humerus'; 79 | % bodyExpressResultsIn_name = []; 80 | % effective_attachm = 'true'; 81 | % print_attachm = 'true'; 82 | % vis_on = 'true'; 83 | % N_frame_test = 5; 84 | % 85 | % muscleLinesOfActionStruct = getMuscleForceDirection(osimModel_name,... 86 | % IK_mot_file,... 87 | % results_directory,... 88 | % bodyOfInterest_name,... 89 | % bodyExpressResultsIn_name,... 90 | % effective_attachm,... 91 | % print_attachm,... 92 | % vis_on,... 93 | % N_frame_test); 94 | % 95 | % 96 | %-------------------------------------------------------------------------- 97 | %% test 2: gait2392 model 98 | osimModel_name = '../_test_data/gait2392/subject01.osim'; 99 | IK_mot_file = '../_test_data/gait2392/subject01_walk1_ik.mot'; 100 | results_directory = '../_test_data/gait2392'; 101 | bodyOfInterest_name = 'femur_r'; 102 | bodyExpressResultsIn_name = []; 103 | effective_attachm = 'true'; 104 | print_attachm = 'true'; 105 | vis_on = 'true'; 106 | N_frame_test = 5; 107 | 108 | muscleLinesOfActionStruct = getMuscleForceDirection(osimModel_name,... 109 | IK_mot_file,... 110 | results_directory,... 111 | bodyOfInterest_name,... 112 | bodyExpressResultsIn_name,... 113 | effective_attachm,... 114 | print_attachm,... 115 | vis_on,... 116 | N_frame_test); -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/_dev_deal_withMuscleWrap.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % Author: Luca Modenese % 4 | % email: l.modenese@imperial.ac.uk % 5 | % ----------------------------------------------------------------------- % 6 | 7 | clear;clc 8 | import org.opensim.modeling.* 9 | 10 | % TO DO: add the possibility of following states 11 | %%%%%%%%%%%%% SET UP %%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % General model 13 | ModelFile = 'arm26.osim'; 14 | % read model 15 | osimModel = Model(ModelFile); 16 | muscles = osimModel.getMuscles(); 17 | aOsimMuscleNameSet = 'all';%{'BRA'}; 18 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 19 | 20 | 21 | % setting which muscles will be followed 22 | muscleNames = ArrayStr; 23 | if strcmp(aOsimMuscleNameSet,'all') 24 | % getmuscles 25 | muscles.getNames(muscleNames); 26 | else 27 | % assign given muscle names to the set to be analyzed 28 | for n_mn = 1:length( aOsimMuscleNameSet ) 29 | muscleNames.append(aOsimMuscleNameSet{n_mn}) 30 | end 31 | end 32 | 33 | for n_mus = 0:muscleNames.getSize()-1 34 | 35 | % current muscle 36 | curr_muscle = muscles.get(muscleNames.getitem(n_mus)); 37 | 38 | % EXTRACTING THE WRAPPING POINTS 39 | si = osimModel.initSystem(); 40 | 41 | % get the geometry path for the current state 42 | PathpointArray = curr_muscle.getGeometryPath().getCurrentPath(si); 43 | 44 | % normal pathpoints attached to bodies 45 | ModelPathpoint = curr_muscle.getGeometryPath().getPathPointSet(); 46 | 47 | % check if there are wrapping points 48 | NrOfWrappingPoints = PathpointArray.getSize()-ModelPathpoint.getSize(); 49 | 50 | % header 51 | display(['Muscle ',char(curr_muscle.getName()), ' (',num2str(NrOfWrappingPoints),' wrapping points)']); 52 | 53 | for n_p = 0:PathpointArray.getSize()-1 54 | 55 | % get the coordinates of the current pathpoint 56 | curr_point_loc_OS = Vec3(PathpointArray.getitem(n_p).getLocation); 57 | curr_point_loc = [curr_point_loc_OS.get(0),curr_point_loc_OS.get(1),curr_point_loc_OS.get(2)]; 58 | 59 | % body where the body is attached to 60 | display(['Point ',num2str(n_p+1), ' attached to body ',char(PathpointArray.getitem(n_p).getBodyName())]); 61 | display([num2str(curr_point_loc_OS.get(0)),' ',num2str(curr_point_loc_OS.get(1)),' ',num2str(curr_point_loc_OS.get(2))]) 62 | 63 | end 64 | display('-----------------------------------'); 65 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/getBodyorGround.m: -------------------------------------------------------------------------------- 1 | function Body = getBodyorGround(osimModel,BodyName) 2 | %-------------------------------------------------------------------------% 3 | % getBodyorGround gets a Body or Ground by name from an OpenSim model % 4 | % (version 4.0 and up). % 5 | % % 6 | % INPUTS: % 7 | % - osimModel: the OpenSim model object. % 8 | % - BodyName: name pf body to get, a character string. % 9 | % % 10 | % OUTPUTS: % 11 | % - Body: target PhysicalFrame object, either a Body or Ground. % 12 | % % 13 | % code edition log: % 14 | % 18 Sep 2019: created for OpenSim 4.0 model Body/Ground format (KS). % 15 | % ----------------------------------------------------------------------- % 16 | % Author: Ke Song (Washington University in St. Louis) % 17 | % E-mail: ksong23@wustl.edu % 18 | % ----------------------------------------------------------------------- % 19 | 20 | % load Library 21 | import org.opensim.modeling.*; 22 | 23 | % get name of Ground in model 24 | osimGroundName = char(osimModel.getGround.getName()); 25 | 26 | % get Ground or Body based on name 27 | if strcmp(BodyName,osimGroundName) 28 | Body = osimModel.getGround(); %Ground 29 | else 30 | Body = osimModel.getBodySet.get(BodyName); 31 | end 32 | 33 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/getCurrentMusclePathAsMat.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese, 2017 % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % Given a state, this script collects info about the path of a muscle. 19 | % Bodies of muscle attachments and point coordinates are made available as 20 | % a list and a matrix respectively. 21 | % 22 | % INPUTS: 23 | % - osimMuscle: an OpenSim model (API object). 24 | % - s: state, used to update the current muscle path and get 25 | % active conditional viapoints. 26 | % 27 | % OUTPUTS: 28 | % - mus_bodyset_list: matrix where each row is a muscle point and 29 | % columns are its [X Y Z] coordinates in the reference system of 30 | % the body they belong to (as in .osim file). 31 | % - mus_pointset_mat: cell array of body names, same length as 32 | % the PathPointSet, with the name of the Body for each point. 33 | % 34 | % 35 | % last modified: 36 | % 2017: created. 37 | % 26 Jun 2018: comments (LM) 38 | % 29 Nov 2018: renamed, recommented, modified, added to MFD Matlab version. 39 | % 18 Sep 2019: using getCurrentPath to recognize wrap points (KS). 40 | % ----------------------------------------------------------------------- % 41 | function [mus_bodyset_list, mus_pointset_mat] = getCurrentMusclePathAsMat(osimMuscle, s) 42 | 43 | % load libraries 44 | import org.opensim.modeling.*; 45 | 46 | % get geometry path point array (including wrap points) for current state 47 | curr_PathPointSet = osimMuscle.getGeometryPath().getCurrentPath(s); 48 | 49 | n_pp = 1; 50 | for n_p = 0:curr_PathPointSet.getSize-1 51 | 52 | % point under examination 53 | curr_point = curr_PathPointSet.get(n_p); 54 | attachBody = curr_point.getBodyName(); 55 | 56 | % if pathpoint is conditional, then check if it is active 57 | if strcmp(char(curr_point.getConcreteClassName), 'ConditionalPathPoint') 58 | cond_viapoint = ConditionalPathPoint.safeDownCast(curr_point); 59 | % is it active? 60 | if cond_viapoint.isActive(s) 61 | % if yes add it to point set 62 | mus_pointset_mat(n_pp, 1:3) = [curr_point.getLocation(s).get(0), curr_point.getLocation(s).get(1), curr_point.getLocation(s).get(2)]; %#ok<*AGROW> 63 | mus_bodyset_list(n_pp) = {char(attachBody)}; 64 | n_pp = n_pp+1; 65 | else 66 | continue 67 | end 68 | else 69 | % if not conditional add it 70 | mus_pointset_mat(n_pp, 1:3) = [curr_point.getLocation(s).get(0), curr_point.getLocation(s).get(1), curr_point.getLocation(s).get(2)]; 71 | mus_bodyset_list(n_pp) = {char(attachBody)}; 72 | n_pp = n_pp+1; 73 | end 74 | end 75 | 76 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/getMatStructColumn.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % 19 | % Function that allows to retrieve the value of a specified variable whose 20 | % name is specified in var_name. 21 | % 22 | % INPUTS 23 | % struct: is a structure with fields 'colheaders', the headers, and 'data' 24 | % that is a matrix of data. 25 | % var_name: the name of the variable to extract. 26 | % 27 | % OUTPUTS 28 | % var_value: the column of the matrix correspondent to the header specified 29 | % in input as var_name. 30 | % 31 | % 32 | % written: Luca Modenese, July 2014 33 | % last modified: 34 | % Header (February 2018, LM) 35 | % 29 Nov 2018: renamed, recommented, added to MFD Matlab version (LM). 36 | % ----------------------------------------------------------------------- % 37 | function var_value = getMatStructColumn(struct, var_name) 38 | 39 | % gets the index of the desired variable name in the colheaders of the 40 | % structure from where it will be extracted 41 | var_index = strncmp(struct.colheaders, var_name, length(var_name)); 42 | 43 | if sum(var_index) == 0 44 | %error(['getValueColumnForHeader.m','. No header in structure is matching the name ''',var_name,'''.']) 45 | display(['getValueColumnForHeader.m','. No header in structure is matching the name ''',var_name,'''']) 46 | var_value = []; 47 | return 48 | end 49 | 50 | % uses the index to retrieve the column of values for that variable. 51 | var_value = struct.data(:,var_index); 52 | 53 | end 54 | -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/isBodyInModel.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % This script checks if a body of interest is included in an OpenSim model. 19 | % 20 | % INPUTS: 21 | % - osimModel: an OpenSim model as API object. 22 | % - bone_of_interest: a string with the name of the body of interest. 23 | % 24 | % OUTPUT: 25 | % - out: a flag. Flag value 1 means test is passed, otherwise the 26 | % script throws an error. 27 | % 28 | % last modified: 29 | % 23 Jun 2017: comments (LM). 30 | % 16 Feb 2018: changed function name (LM). 31 | % 29 Nov 2018: changed name, recommented, included in MFD toolbox (LM). 32 | % 18 Sep 2019: modified for OpenSim 4.0 model Body/Ground format (KS). 33 | % ----------------------------------------------------------------------- % 34 | function out = isBodyInModel(osimModel, aBodyName) 35 | 36 | % load Library 37 | import org.opensim.modeling.*; 38 | 39 | % check if a body (or ground) with the specified name is part of model. 40 | if osimModel.getBodySet.getIndex(aBodyName)<0 && ~strcmp(aBodyName, char(osimModel.getGround.getName())) 41 | 42 | % throws error if body is not part of the model 43 | error(['isBodyInModel.m The body ',aBodyName,' is not included in the OpenSim model.']) 44 | 45 | else 46 | 47 | out = 1; 48 | return 49 | end 50 | 51 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/isKinMatchingModelCoords.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | function [out, missing_coords_list] = isKinMatchingModelCoords(osimModel, headers_in_struct) 19 | 20 | % OpenSim suggested settings 21 | import org.opensim.modeling.* 22 | OpenSimObject.setDebugLevel(3); 23 | 24 | % getting model coordinates and their number 25 | coordsModel = osimModel.updCoordinateSet(); 26 | N_coordsModel = coordsModel.getSize(); 27 | 28 | % check if coordinates are the same (sometimes time is also here) 29 | if any(strcmp('time', headers_in_struct)) 30 | coordsNames_in_struct = headers_in_struct(~strcmp('time', headers_in_struct)); 31 | else 32 | coordsNames_in_struct = headers_in_struct; 33 | end 34 | n_miss = 0; 35 | n_matched = 0; 36 | coordNames = {}; 37 | missing_coords_list = {}; 38 | 39 | for n = 0:N_coordsModel-1 40 | %extracting the column for the state variable of interest 41 | cur_coordName = char(coordsModel.get(n).getName()); 42 | if find(strcmp(cur_coordName, coordsNames_in_struct)) == n+1 43 | coordNames{n_matched+1} = cur_coordName; 44 | n_matched = n_matched+1; 45 | else 46 | missing_coords_list{n_miss+1} = cur_coordName; 47 | n_miss = n_miss+1; 48 | end 49 | end 50 | 51 | if length(coordNames) == length(coordsNames_in_struct) 52 | disp('Coordinate structure and model are properly matched (coordinates and their order).'); 53 | out = 1; 54 | return 55 | else 56 | out = 0; 57 | 58 | end 59 | 60 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/isMuscleConnectedToBody.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % Script checking if an OpenSim muscle and a given body in an MSK model 19 | % are connected, i.e. if the muscle path has at least one point attached 20 | % to that body. 21 | % Note that: 22 | % 1) osimMuscle is used to avoid passing in the model. That is the reason 23 | % why function isBodyInModel was not used (requires model). 24 | % 2) if a BodyName not belonging to the model if specified, flag will be 0. 25 | % 26 | % INPUTS: 27 | % -osimMuscle: a muscle from an OpenSim model (API object). 28 | % -osimBodyName: name of a body included in the OpenSim model. 29 | % 30 | % OUTPUT: 31 | % -flag: variable of value 1 or 0, depending if the muscle is 32 | % attached to the body (1) or not (0). 33 | % 34 | % 35 | % written: 2014 (Griffith University) 36 | % last modified: 37 | % 26 Jun 2017: comments (LM) 38 | % 29 Nov 2018: renamed, recommented, added to MFD Matlab tool (LM). 39 | % ----------------------------------------------------------------------- % 40 | function flag = isMuscleConnectedToBody(osimMuscle, osimBodyName) 41 | 42 | % initialise answ 43 | flag = 0; 44 | 45 | % check name 46 | if isjava(osimBodyName) 47 | osimBodyName = char(osimBodyName); 48 | end 49 | 50 | % extract muscle pathpointset 51 | muspathpointset = osimMuscle.getGeometryPath.getPathPointSet(); 52 | 53 | % looping through the pathpoints of a muscle to check if any of those is 54 | % attached to the body of interest 55 | for n_p = 0:muspathpointset.getSize-1 56 | % current attachment body of the muscle point 57 | curr_attach_body = char(muspathpointset.get(n_p).getBodyName); 58 | % check if this is the specified body 59 | if strcmp(curr_attach_body, osimBodyName) 60 | flag = 1; 61 | display(['Muscle ', char(osimMuscle.getName),' is attached to body ', osimBodyName]); 62 | return 63 | end 64 | end 65 | 66 | % give feedback also if muscle does not attached to specified body 67 | if flag == 0 68 | display(['Muscle ', char(osimMuscle.getName),' does NOT attach to body ', char(osimBodyName)]); 69 | end 70 | 71 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/printtoSTO.m: -------------------------------------------------------------------------------- 1 | function printtoSTO(varargin) 2 | %-------------------------------------------------------------------------% 3 | % printtoSTO prints structured results in OpenSim .sto text format. % 4 | % % 5 | % INPUTS: % 6 | % - structData: structure with 'data' and 'colheaders' arrays. % 7 | % - outFile: full path filename where output will be written in.% 8 | % - topheader (optional): header text at top row of sto file. % 9 | % - info (optional): informational text within sto file header. % 10 | % % 11 | % code edition log: % 12 | % 18 Sep 2019: created (KS). % 13 | % ----------------------------------------------------------------------- % 14 | % Author: Ke Song (Washington University in St. Louis) % 15 | % E-mail: ksong23@wustl.edu % 16 | % ----------------------------------------------------------------------- % 17 | 18 | % evaluate required & optional inputs; provide defaults for optional 19 | switch nargin 20 | case 2 21 | structData = varargin{1}; 22 | outFile = varargin{2}; 23 | topheader = ''; 24 | info = ''; 25 | case 3 26 | structData = varargin{1}; 27 | outFile = varargin{2}; 28 | topheader = varargin{3}; 29 | if isempty(topheader), topheader=''; end 30 | info = ''; 31 | case 4 32 | structData = varargin{1}; 33 | outFile = varargin{2}; 34 | topheader = varargin{3}; 35 | if isempty(topheader), topheader=''; end 36 | info = varargin{4}; 37 | % if isempty(info), info=''; end 38 | otherwise 39 | error('incorrect number of inputs to printMFDtoSTO.m.') 40 | end 41 | 42 | % find nRows and nColumns (for header) 43 | nrc = size(structData.data); 44 | 45 | % get directory; if do not exist, create one 46 | [outDir,~,~] = fileparts(outFile); 47 | if exist(outDir,'dir')~=7, mkdir(outDir); end 48 | 49 | % open sto file to write in (discard existing contents, if any) 50 | fid = fopen(outFile,'w'); 51 | 52 | % print headers 53 | fprintf(fid,'%s\r\n',topheader); 54 | fprintf(fid,'version=1\r\n'); % set version here 55 | fprintf(fid,'nRows=%d\r\n',nrc(1)); 56 | fprintf(fid,'nColumns=%d\r\n',nrc(2)); 57 | fprintf(fid,'inDegrees=no\r\n\r\n'); % set to 'yes' for angles in deg 58 | if ~isempty(info), fprintf(fid,'%s\r\n\r\n',info); end 59 | fprintf(fid,'Data in S.I. units (seconds, meters, Newtons, ...)\r\n'); 60 | fprintf(fid,'endheader\r\n'); 61 | 62 | % print array headers 63 | fmth = repmat('%s\t',1,length(structData.colheaders)); 64 | fmth = [fmth(1:end-2) , '\r\n']; 65 | fprintf(fid,fmth,structData.colheaders{:}); 66 | 67 | % print data 68 | % format: 8 digits after decimal point (spacing: field width = 16) 69 | fmtd = repmat('%16.8f\t',1,nrc(2)); 70 | fmtd = [fmtd(1:end-2) , '\r\n']; 71 | for i = 1 : nrc(1) 72 | fprintf(fid,fmtd,structData.data(i,:)); % print one row at a time 73 | end 74 | 75 | fclose(fid); 76 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/realizeMatStructKinematics.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % 19 | % A function to realize the kinematic state of a model. 20 | % 21 | % TODO: write comments 22 | % 23 | % written: 2014/2015 (Griffith University) 24 | % last modified: 25 | % February 2017 (comments) 26 | % 29/11/2018 renamed and added to MFD Matlab version. 27 | % 18/09/2019 added functionality to assign linear coupled coordinates (KS). 28 | % ----------------------------------------------------------------------- % 29 | function state = realizeMatStructKinematics(osimModel, state, KinColHeaders, KinRowData) 30 | % only a row of kinematic coordinates is passed in this function. columns 31 | % of data MUST match that of colheaders. 32 | 33 | % OpenSim suggested settings 34 | import org.opensim.modeling.* 35 | OpenSimObject.setDebugLevel(3); 36 | 37 | % getting model coordinates and their number 38 | coordsModel = osimModel.updCoordinateSet(); 39 | N_coordsModel = coordsModel.getSize(); 40 | 41 | % checking is kinematics matches coordinates order 42 | [out, missing_coords_list] = isKinMatchingModelCoords(osimModel, KinColHeaders); 43 | 44 | % correct if there are generalised coordinates not computed in IK (e.g. 45 | % models modified after running IK) 46 | if ~out 47 | for n_m = 1:length(missing_coords_list) 48 | coordName = missing_coords_list{n_m}; 49 | missing_coords_vals(n_m) = coordsModel.get(coordName).getDefaultValue; 50 | end 51 | else 52 | missing_coords_vals = []; 53 | end 54 | 55 | % account for time column in data structure 56 | % append missing coordinates at end of colheaders & data 57 | if any(strcmp('time', KinColHeaders)) 58 | kin_state_angles = [KinRowData(2:end), missing_coords_vals]; 59 | kin_state_colheaders = [KinColHeaders(2:end), missing_coords_list]; 60 | else 61 | kin_state_angles = [KinRowData, missing_coords_vals]; 62 | kin_state_colheaders = [KinColHeaders, missing_coords_list]; 63 | end 64 | 65 | % extract coordinate couplers in model (for coupled joints) 66 | ct_set = osimModel.getConstraintSet(); 67 | for n_ct = 0:ct_set.getSize()-1 68 | ct_class{n_ct+1} = char(ct_set.get(n_ct).getConcreteClassName()); 69 | % extract properties from CoordinateCouplerConstraint 70 | if ~strcmp(ct_class{n_ct+1},'CoordinateCouplerConstraint') 71 | ct{n_ct+1} = []; 72 | else 73 | ct{n_ct+1} = CoordinateCouplerConstraint.safeDownCast(ct_set.get(n_ct)); 74 | ct_dcn{n_ct+1} = char(ct{n_ct+1}.getDependentCoordinateName()); 75 | end 76 | end 77 | 78 | % looping thought coordinates to assign them a value 79 | for n_modelCoords = 0:N_coordsModel-1 80 | 81 | % Value of the state variable at that frame 82 | cur_coordValue = kin_state_angles(n_modelCoords+1); 83 | 84 | % assigning the coordinates depending on their motion type 85 | switch lower(char(coordsModel.get(n_modelCoords).getMotionType())) 86 | case 'rotational' 87 | % transform to radiant for angles 88 | coordsModel.get(n_modelCoords).setValue(state,cur_coordValue*pi/180); 89 | case 'translational' 90 | % not changing linear distances 91 | coordsModel.get(n_modelCoords).setValue(state,cur_coordValue); 92 | case 'coupled' 93 | % in case of coupled joint, search independent coordinate and 94 | % coupler function, then compute dependent angle 95 | % search current dependent in coupler definitions (must be unique) 96 | cctid=find(strcmp(char(coordsModel.get(n_modelCoords).getName()),ct_dcn)); 97 | if length(cctid)~=1 98 | error(['CoordinateCouplerConstraint for ',... 99 | char(coordsModel.get(n_modelCoords).getName()),... 100 | ' is not found, OR not uniquely defined, in model ',... 101 | char(osimModel.getName()),'.']) 102 | elseif ~strcmp(char(ct{cctid}.getFunction().getConcreteClassName()),'LinearFunction') 103 | % if coupler function is not linear, throw error 104 | % (edit to expand code compatibility to nonlinear functions) 105 | error('non-linear coordinate coupler function is not managed by realizeMatStructKinematics.m') 106 | else % unique dependent coupled with LinearFunction found: 107 | % for linear fn only 1 independent coord should be specified 108 | ct_icn = char(ct{cctid}.getIndependentCoordinateNames().get(0)); 109 | ct_fn = LinearFunction.safeDownCast(ct{cctid}.getFunction()); 110 | % compute dependent coordinate based on independent coord and coupler fn 111 | ct_icv = strcmp(kin_state_colheaders,ct_icn); 112 | cur_coordValue = ct_fn.getSlope() * kin_state_angles(ct_icv) + ct_fn.getIntercept(); 113 | % transform to radiant for angles 114 | coordsModel.get(n_modelCoords).setValue(state,cur_coordValue*pi/180); 115 | end 116 | otherwise 117 | error('motion type not recognized. Please check OpenSim model (maybe update error?)') 118 | end 119 | end 120 | 121 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/sto2Mat.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % This script converts a .sto file generated by OpenSim analyses in a 19 | % matlab structure with fields "colheaders" and "data". 20 | % This is a convenient script to robustly read OpenSim files. 21 | % 22 | % INPUTS: 23 | % - Storage_file: a .sto file, including path, e.g. from static 24 | % optimization or JointReaction analysis. 25 | % OUTPUTS: 26 | % -StorageMatStruc: matlab structure with the following fields: 27 | % a) StorageMatStruc.colheaders: cell array of headers of the 28 | % .sto file. 29 | % b) StorageMatStruc.data: matrix containing the data that 30 | % were stored in the input file. 31 | % 32 | % 33 | % written: 2014/2015 (Griffith University) 34 | % last modified: 35 | % 26 Jun 2017: comments (LM) 36 | % 29 Nov 2018: changed name - added to MFD Matlab version. 37 | % ----------------------------------------------------------------------- % 38 | function StorageMatStruc = sto2Mat(storage_file) 39 | 40 | % OpenSim suggested settings 41 | import org.opensim.modeling.* 42 | OpenSimObject.setDebugLevel(3); 43 | 44 | % read storage file 45 | openSimStorage = Storage(storage_file); 46 | 47 | % extract time column and place it in time array 48 | timeColumn = ArrayDouble(); 49 | openSimStorage.getTimeColumn(timeColumn); 50 | for n_t = 0:timeColumn.getSize-1 51 | time_vec(n_t+1,1) = timeColumn.getitem(n_t); 52 | end 53 | 54 | % converting labels 55 | OSLabelsArray = openSimStorage.getColumnLabels; 56 | for n_lab = 0:OSLabelsArray.getSize-1 57 | StorageMatStruc.colheaders{n_lab+1} = char(OSLabelsArray.get(n_lab)); 58 | end 59 | 60 | % converting data 61 | dataColumn = ArrayDouble(); 62 | ind = 0; 63 | while openSimStorage.getDataColumn(ind, dataColumn) 64 | for n_d = 0:dataColumn.getSize-1 65 | StorageData(n_d+1,ind+1) = dataColumn.getitem(n_d); 66 | end 67 | ind = ind+1; 68 | end 69 | StorageMatStruc.data = [time_vec, StorageData]; 70 | 71 | % checking that dimensionality of data and colheaders are consistent 72 | n_diff = size(StorageMatStruc.colheaders,2)-size(StorageMatStruc.data,2); 73 | 74 | % if not consistent let the user decide what to do 75 | if n_diff>0 76 | answ = menu(['In the conversion from storage to MATLAB structure ',num2str(n_diff),' more header(s) than data were found. Removing extra headers (y) or stop (n).'], 'Yes','No'); 77 | if answ == 1 78 | StorageMatStruc.colheaders = StorageMatStruc.colheaders(1:size(StorageMatStruc.data,2)); 79 | elseif answ == 2 80 | error('Please check your sto files manually.'); 81 | end 82 | end 83 | 84 | end -------------------------------------------------------------------------------- /MATLAB/matlab_tool_v4.0/transformVec.m: -------------------------------------------------------------------------------- 1 | function transVec = transformVec(osimModel,s,localVec,localBody,transBody) 2 | %-------------------------------------------------------------------------% 3 | % transformVec converts a 3D numerical vector from one specified frame to % 4 | % another, using transformPosition function from the Simbody engine. % 5 | % % 6 | % INPUTS: % 7 | % - osimModel: the OpenSim model object. % 8 | % - s: current OpenSim model state. % 9 | % - localVec: 3D numerical vector to transform. % 10 | % - localBody: current Body where localVec is expressed in. % 11 | % - transBody: target Body where localVec will be expreseed in. % 12 | % % 13 | % OUTPUTS: % 14 | % - transVec: 3D numerical vector converted from localVec, now % 15 | % expressed in transBody. % 16 | % % 17 | % code edition log: % 18 | % 18 Sep 2019: created (KS). % 19 | % ----------------------------------------------------------------------- % 20 | % Author: Ke Song (Washington University in St. Louis) % 21 | % E-mail: ksong23@wustl.edu % 22 | % ----------------------------------------------------------------------- % 23 | 24 | % load Library 25 | import org.opensim.modeling.*; 26 | 27 | % ensure localVec is 1x3 vector 28 | if all(size(localVec) == [3,1]) 29 | localVec = localVec'; 30 | elseif numel(localVec) ~= 3 31 | error('numerical vector for Simbody transformPosition must be in 3D.') 32 | end 33 | 34 | % Vec3 object to store localVec values 35 | localVec3 = Vec3(localVec(1),localVec(2),localVec(3)); 36 | 37 | % Vec3 object to store transVec values 38 | transVec3 = Vec3(0); 39 | 40 | % transformation using SimBody engine 41 | osimModel.getSimbodyEngine.transformPosition(... 42 | s, localBody, localVec3, transBody, transVec3); 43 | 44 | % extract transVec values back from Vec3 45 | transVec = [transVec3.get(0), transVec3.get(1), transVec3.get(2)]; 46 | 47 | end -------------------------------------------------------------------------------- /MATLAB/private/Mat2sto.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % This script writes an OpenSim storage file using a Matlab structure as 19 | % input. 20 | % 21 | % INPUTS: 22 | % - MatStruct: matlab structure with the following fields: 23 | % a) MatStruct.colheaders: cell array of headers of the 24 | % .sto file. 25 | % b) MatStruct.data: matrix containing the data that 26 | % will be printed in the .sto file. 27 | % 28 | % - sto_file: a string with the name (and path) of the .sto file to print. 29 | % 30 | % - str_data_description: a string that described the data. It will 31 | % be included in the file in a sentence starting with: 32 | % "This file contains..." 33 | % 34 | % OUTPUT: 35 | % - sto file at the specified path. 36 | % 37 | % ----------------------------------------------------------------------- % 38 | function Mat2sto(MatStruct, sto_file, str_data_description) 39 | 40 | % check on the data structure 41 | if ~isfield(MatStruct,'data') || ~isfield(MatStruct,'colheaders') 42 | error(['The function writeStorageFile needs as input a dataStruct with fields ''colheaders'' and ''data''.',... 43 | 'The number of columns of DataStruct.data has to equalize the number of headers.']); 44 | end 45 | 46 | % defines local variables and their size 47 | colheaders = MatStruct.colheaders; 48 | data = MatStruct.data; 49 | 50 | % sizes of data 51 | [N_rows, N_columns] = size(data); 52 | 53 | % check on consistency of the structure data 54 | if size(colheaders,2)~=N_columns 55 | error('The number of column headers is not consistent with the number of data rows.') 56 | end 57 | 58 | % file name 59 | [~,name,ext] = fileparts(sto_file); 60 | sto_file_name = [name,ext]; 61 | 62 | % open file 63 | fid = fopen(sto_file,'w'); 64 | 65 | % % Write Header 66 | fprintf(fid,'%s\n',sto_file_name); 67 | fprintf(fid,'%s\n','version=1'); 68 | fprintf(fid,'%s\n',['nRows=',num2str(N_rows)]); 69 | fprintf(fid,'%s\n',['nColumns=',num2str(N_columns)]); 70 | fprintf(fid,'%s\n','inDegrees=no'); 71 | fprintf(fid,'\n'); 72 | fprintf(fid,'%s\n',['This file contains ',str_data_description, '.']); 73 | fprintf(fid,'\n'); 74 | fprintf(fid,'%s\n','endheader'); 75 | 76 | % writing the column headers while generating the format for printing the 77 | % data 78 | format_string =''; 79 | for n_headers = 1:N_columns 80 | if n_headers == N_columns 81 | % prints header 82 | fprintf(fid,'%s\n',colheaders{N_columns}); 83 | % builds up format string 84 | format_string = [format_string,'%-14.14f\n']; %#ok<*AGROW> 85 | else 86 | fprintf(fid,'%s\t', colheaders{n_headers}); 87 | format_string = [format_string,'%-14.14f\t']; 88 | end 89 | end 90 | 91 | % writing the data in OpenSim format 92 | fprintf(fid, format_string, data'); 93 | fclose all; 94 | 95 | end -------------------------------------------------------------------------------- /MATLAB/private/getCurrentMusclePathAsMat.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese, 2017 % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % Given a state, this script collects info about the path of a muscle. 19 | % Bodies of muscle attachments and point coordinates are made available as 20 | % a list and a matrix respectively. 21 | % 22 | % INPUTS: 23 | % - osimMuscle: an OpenSim model (API object). 24 | % - s: state, used to update the current muscle path and get 25 | % active conditional viapoints. 26 | % 27 | % OUTPUTS: 28 | % - mus_bodyset_list: matrix where each row is a muscle point and 29 | % columns are its [X Y Z] coordinates in the reference system of 30 | % the body they belong to (as in .osim file). 31 | % - mus_pointset_mat: cell array of body names, same length as 32 | % the PathPointSet, with the name of the Body for each point. 33 | % 34 | % 35 | % last modified: 36 | % 2017: created. 37 | % 26 Jun 2018: comments (LM) 38 | % 29 Nov 2018: renamed, recommented, modified, added to MFD Matlab version. 39 | % ----------------------------------------------------------------------- % 40 | function [mus_bodyset_list, mus_pointset_mat] = getCurrentMusclePathAsMat(osimMuscle, s) 41 | 42 | % load libraries 43 | import org.opensim.modeling.*; 44 | 45 | % get pathpointset 46 | curr_PathPointSet = osimMuscle.getGeometryPath.getPathPointSet(); 47 | 48 | n_pp = 1; 49 | for n_p = 0:curr_PathPointSet.getSize-1 50 | 51 | % point under examination 52 | curr_point = curr_PathPointSet.get(n_p); 53 | attachBody = curr_point.getBodyName(); 54 | 55 | % if pathpoint is conditional, then check if it is active 56 | if strcmp(char(curr_point.getConcreteClassName), 'ConditionalPathPoint') 57 | cond_viapoint = ConditionalPathPoint.safeDownCast(curr_point); 58 | % is it active? 59 | if cond_viapoint.isActive(s) 60 | % if yes add it to point set 61 | mus_pointset_mat(n_pp, 1:3) = [curr_point.getLocation.get(0), curr_point.getLocation.get(1), curr_point.getLocation.get(2)]; %#ok<*AGROW> 62 | mus_bodyset_list(n_pp) = {char(attachBody)}; 63 | n_pp = n_pp+1; 64 | else 65 | continue 66 | end 67 | else 68 | % if not conditional add it 69 | mus_pointset_mat(n_pp, 1:3) = [curr_point.getLocation.get(0), curr_point.getLocation.get(1), curr_point.getLocation.get(2)]; 70 | mus_bodyset_list(n_pp) = {char(attachBody)}; 71 | n_pp = n_pp+1; 72 | end 73 | end 74 | 75 | end -------------------------------------------------------------------------------- /MATLAB/private/getMatStructColumn.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % 19 | % Function that allows to retrieve the value of a specified variable whose 20 | % name is specified in var_name. 21 | % 22 | % INPUTS 23 | % struct: is a structure with fields 'colheaders', the headers, and 'data' 24 | % that is a matrix of data. 25 | % var_name: the name of the variable to extract. 26 | % 27 | % OUTPUTS 28 | % var_value: the column of the matrix correspondent to the header specified 29 | % in input as var_name. 30 | % 31 | % 32 | % written: Luca Modenese, July 2014 33 | % last modified: 34 | % Header (February 2018, LM) 35 | % 29 Nov 2018: renamed, recommented, added to MFD Matlab version (LM). 36 | % ----------------------------------------------------------------------- % 37 | function var_value = getMatStructColumn(struct, var_name) 38 | 39 | % gets the index of the desired variable name in the colheaders of the 40 | % structure from where it will be extracted 41 | var_index = strncmp(struct.colheaders, var_name, length(var_name)); 42 | 43 | if sum(var_index) == 0 44 | %error(['getValueColumnForHeader.m','. No header in structure is matching the name ''',var_name,'''.']) 45 | display(['getValueColumnForHeader.m','. No header in structure is matching the name ''',var_name,'''']) 46 | var_value = []; 47 | return 48 | end 49 | 50 | % uses the index to retrieve the column of values for that variable. 51 | var_value = struct.data(:,var_index); 52 | 53 | end 54 | -------------------------------------------------------------------------------- /MATLAB/private/isBodyInModel.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % This script checks if a body of interest is included in an OpenSim model. 19 | % 20 | % INPUTS: 21 | % - osimModel: an OpenSim model as API object. 22 | % - bone_of_interest: a string with the name of the body of interest. 23 | % 24 | % OUTPUT: 25 | % - out: a flag. Flag value 1 means test is passed, otherwise the script 26 | % throws an error. 27 | % 28 | % last modified: 29 | % 23 Jun 2017: comments (LM). 30 | % 16 Feb 2018: changed function name (LM). 31 | % 29 Nov 2018: changed name, recommented, included in MFD toolbox (LM). 32 | % ----------------------------------------------------------------------- % 33 | function out = isBodyInModel(osimModel, aBodyName) 34 | 35 | % load Library 36 | import org.opensim.modeling.*; 37 | 38 | % check if a body with the specified name is part of model. 39 | if osimModel.getBodySet.getIndex(aBodyName)<0 40 | 41 | % throws error if body is not part of the model 42 | error(['isBodyInModel.m The body ',aBodyName,' is not included in the OpenSim model.']) 43 | 44 | else 45 | 46 | out = 1; 47 | return 48 | end 49 | 50 | end -------------------------------------------------------------------------------- /MATLAB/private/isKinMatchingModelCoords.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | function [out, missing_coords_list] = isKinMatchingModelCoords(osimModel, headers_in_struct) 19 | 20 | % OpenSim suggested settings 21 | import org.opensim.modeling.* 22 | OpenSimObject.setDebugLevel(3); 23 | 24 | % getting model coordinates and their number 25 | coordsModel = osimModel.updCoordinateSet(); 26 | N_coordsModel = coordsModel.getSize(); 27 | 28 | % check if coordinates are the same (sometimes time is also here) 29 | if any(strcmp('time', headers_in_struct)) 30 | coordsNames_in_struct = headers_in_struct(~strcmp('time', headers_in_struct)); 31 | else 32 | coordsNames_in_struct = headers_in_struct; 33 | end 34 | n_miss = 1; 35 | n_matched = 1; 36 | coordNames = {}; 37 | missing_coords_list = {}; 38 | 39 | for n = 0:N_coordsModel-1 40 | %extracting the column for the state variable of interest 41 | cur_coordName = char(coordsModel.get(n).getName()); 42 | if find(strcmp(cur_coordName, coordsNames_in_struct)) == n+1 43 | coordNames{n_matched} = cur_coordName; 44 | n_matched = n_matched+1; 45 | else 46 | missing_coords_list{n_miss} = cur_coordName; 47 | n_miss = n_miss+1; 48 | end 49 | end 50 | 51 | if length(coordNames) == length(coordsNames_in_struct) 52 | out = 1; 53 | return 54 | else 55 | warning('Coordinate structure and model are NOT properly matched (coordinates and their order).'); 56 | out = 0; 57 | 58 | end 59 | 60 | end -------------------------------------------------------------------------------- /MATLAB/private/isMuscleConnectedToBody.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % Script checking if an OpenSim muscle and a given body in an MSK model 19 | % are connected, i.e. if the muscle path has at least one point attached 20 | % to that body. 21 | % Note that: 22 | % 1) osimMuscle is used to avoid passing in the model. That is the reason 23 | % why function isBodyInModel was not used (requires model). 24 | % 2) if a BodyName not belonging to the model if specified, flag will be 0. 25 | % 26 | % INPUTS: 27 | % -osimMuscle: a muscle from an OpenSim model (API object). 28 | % -osimBodyName: name of a body included in the OpenSim model. 29 | % 30 | % OUTPUT: 31 | % -flag: variable of value 1 or 0, depending if the muscle is 32 | % attached to the body (1) or not (0). 33 | % 34 | % 35 | % written: 2014 (Griffith University) 36 | % last modified: 37 | % 26 Jun 2017: comments (LM) 38 | % 29 Nov 2018: renamed, recommented, added to MFD Matlab tool (LM). 39 | % ----------------------------------------------------------------------- % 40 | function flag = isMuscleConnectedToBody(osimMuscle, osimBodyName) 41 | 42 | % initialise answ 43 | flag = 0; 44 | 45 | % check name 46 | if isjava(osimBodyName) 47 | osimBodyName = char(osimBodyName); 48 | end 49 | 50 | % extract muscle pathpointset 51 | muspathpointset = osimMuscle.getGeometryPath.getPathPointSet(); 52 | 53 | % looping through the pathpoints of a muscle to check if any of those is 54 | % attached to the body of interest 55 | for n_p = 0:muspathpointset.getSize-1 56 | % current attachment body of the muscle point 57 | curr_attach_body = char(muspathpointset.get(n_p).getBodyName); 58 | % check if this is the specified body 59 | if strcmp(curr_attach_body, osimBodyName) 60 | flag = 1; 61 | display(['Muscle ', char(osimMuscle.getName),' is attached to body ', osimBodyName]); 62 | return 63 | end 64 | end 65 | 66 | % give feedback also if muscle does not attached to specified body 67 | if flag == 0 68 | display(['Muscle ', char(osimMuscle.getName),' does NOT attach to body ', char(osimBodyName)]); 69 | end 70 | 71 | end -------------------------------------------------------------------------------- /MATLAB/private/realizeMatStructKinematics.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % 19 | % A function to realize the kinematic state of a model. It is currently 20 | % slow but robust. 21 | % 22 | % TODO: write comments 23 | % 24 | % written: 2014/2015 (Griffith University) 25 | % last modified: 26 | % February 2017 (comments) 27 | % 29/11/2018 renamed and added to MFD Matlab version. 28 | % ----------------------------------------------------------------------- % 29 | function state = realizeMatStructKinematics(osimModel, state, kinStruct, n_frame) 30 | % TO DO 31 | % this function is slow. I should find a way of passing in only a row of 32 | % coordinates! That would eliminate the need of a n_frame as well. 33 | 34 | % OpenSim suggested settings 35 | import org.opensim.modeling.* 36 | OpenSimObject.setDebugLevel(3); 37 | 38 | % getting model coordinates and their number 39 | coordsModel = osimModel.updCoordinateSet(); 40 | N_coordsModel = coordsModel.getSize(); 41 | 42 | % checking is kinematics matches coordinates order 43 | [out, missing_coords_list] = isKinMatchingModelCoords(osimModel, kinStruct.colheaders); 44 | 45 | % correct if there are generalised coordinates not computed in IK (e.g. 46 | % models modified after running IK) 47 | if ~out 48 | for n_m = 1:length(missing_coords_list) 49 | coordName = missing_coords_list{n_m}; 50 | missing_coords_vals(n_m) = coordsModel.get(coordName).getDefaultValue; 51 | end 52 | else 53 | missing_coords_vals = []; 54 | end 55 | % if needed 56 | % kinStruct.colheader = [kinStruct.colheaders, missing_coords_list]; 57 | 58 | % account for time column in data structure 59 | if any(strcmp('time', kinStruct.colheaders)) 60 | kin_state_angles = [kinStruct.data(n_frame, 2:end), missing_coords_vals]; 61 | else 62 | kin_state_angles = [kinStruct.data(n_frame, :), missing_coords_vals]; 63 | end 64 | 65 | % looping thought coordinates to assign them a value 66 | for n_modelCoords = 0:N_coordsModel-1 67 | 68 | % Value of the state variable at that frame 69 | cur_coordValue = kin_state_angles(n_modelCoords+1); 70 | 71 | % assigning the coordinates depending on their motion type 72 | switch char(coordsModel.get(n_modelCoords).get_motion_type()) 73 | case 'rotational' 74 | % transform to radiant for angles 75 | coordsModel.get(n_modelCoords).setValue(state,cur_coordValue*pi/180); 76 | case 'translational' 77 | % not changing linear distances 78 | coordsModel.get(n_modelCoords).setValue(state,cur_coordValue); 79 | case 'coupled' 80 | error('motiontype ''coupled'' is not managed by realizeMatStructKinematics.m'); 81 | otherwise 82 | error('motion type not recognized. Please check OpenSim model (maybe update error?') 83 | end 84 | end 85 | 86 | end -------------------------------------------------------------------------------- /MATLAB/private/sto2Mat.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------% 2 | % Copyright (c) 2019 Modenese L. % 3 | % % 4 | % Licensed under the Apache License, Version 2.0 (the "License"); % 5 | % you may not use this file except in compliance with the License. % 6 | % You may obtain a copy of the License at % 7 | % http://www.apache.org/licenses/LICENSE-2.0. % 8 | % % 9 | % Unless required by applicable law or agreed to in writing, software % 10 | % distributed under the License is distributed on an "AS IS" BASIS, % 11 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 12 | % implied. See the License for the specific language governing % 13 | % permissions and limitations under the License. % 14 | % % 15 | % Author: Luca Modenese % 16 | % email: l.modenese@imperial.ac.uk % 17 | % ----------------------------------------------------------------------- % 18 | % This script converts a .sto file generated by OpenSim analyses in a 19 | % matlab structure "MatStruct" with fields "colheaders" and "data". 20 | % This is a convenient script to robustly read OpenSim files. 21 | % 22 | % INPUTS: 23 | % - Storage_file: a .sto file, including path, e.g. from static 24 | % optimization or JointReaction analysis. 25 | % OUTPUTS: 26 | % -MatStruct: matlab structure with the following fields: 27 | % a) MatStruct.colheaders: cell array of headers of the 28 | % .sto file. 29 | % b) MatStruct.data: matrix containing the data that 30 | % were stored in the input file. 31 | % 32 | % 33 | % written: 2014/2015 (Griffith University) 34 | % last modified: 35 | % 26 Jun 2017: comments (LM) 36 | % 29 Nov 2018: changed name - added to MFD Matlab version. 37 | % ----------------------------------------------------------------------- % 38 | function MatStruct = sto2Mat(storage_file) 39 | 40 | % OpenSim suggested settings 41 | import org.opensim.modeling.* 42 | OpenSimObject.setDebugLevel(3); 43 | 44 | % read storage file 45 | openSimStorage = Storage(storage_file); 46 | 47 | % extract time column and place it in time array 48 | timeColumn = ArrayDouble(); 49 | openSimStorage.getTimeColumn(timeColumn); 50 | for n_t = 0:timeColumn.getSize-1 51 | time_vec(n_t+1,1) = timeColumn.getitem(n_t); 52 | end 53 | 54 | % converting labels 55 | OSLabelsArray = openSimStorage.getColumnLabels; 56 | for n_lab = 0:OSLabelsArray.getSize-1 57 | MatStruct.colheaders{n_lab+1} = char(OSLabelsArray.get(n_lab)); 58 | end 59 | 60 | % converting data 61 | dataColumn = ArrayDouble(); 62 | ind = 0; 63 | while openSimStorage.getDataColumn(ind, dataColumn) 64 | for n_d = 0:dataColumn.getSize-1 65 | StorageData(n_d+1,ind+1) = dataColumn.getitem(n_d); 66 | end 67 | ind = ind+1; 68 | end 69 | MatStruct.data = [time_vec, StorageData]; 70 | 71 | % checking that dimensionality of data and colheaders are consistent 72 | n_diff = size(MatStruct.colheaders,2)-size(MatStruct.data,2); 73 | 74 | % if not consistent let the user decide what to do 75 | if n_diff>0 76 | answ = menu(['In the conversion from storage to MATLAB structure ',num2str(n_diff),' more header(s) than data were found. Removing extra headers (y) or stop (n).'], 'Yes','No'); 77 | if answ == 1 78 | MatStruct.colheaders = MatStruct.colheaders(1:size(MatStruct.data,2)); 79 | elseif answ == 2 80 | error('Please check your sto files manually.'); 81 | end 82 | end 83 | 84 | end -------------------------------------------------------------------------------- /MATLAB/runTests_MATLAB.m: -------------------------------------------------------------------------------- 1 | % TEST1 2 | % 3 | % 1) Load 4 | % 2) Runs from GUI 5 | % 3) Runs from GUI in a sequence of analyses 6 | % 4) Runs from GUI loading the setting from xml 7 | % 5) Runs from command line 8 | % 9 | % // Results 10 | % 11 | % 6) Runs with one body selected 12 | % 7) Runs with two bodies selected 13 | % 8) Runs with all. 14 | 15 | %-------------------------------------------------------------------------% 16 | % Copyright (c) 2018 Modenese L. % 17 | % % 18 | % Licensed under the Apache License, Version 2.0 (the "License"); % 19 | % you may not use this file except in compliance with the License. % 20 | % You may obtain a copy of the License at % 21 | % http://www.apache.org/licenses/LICENSE-2.0. % 22 | % % 23 | % Unless required by applicable law or agreed to in writing, software % 24 | % distributed under the License is distributed on an "AS IS" BASIS, % 25 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or % 26 | % implied. See the License for the specific language governing % 27 | % permissions and limitations under the License. % 28 | % % 29 | % Author: Luca Modenese, May 2019 % 30 | % email: l.modenese@imperial.ac.uk % 31 | % ----------------------------------------------------------------------- % 32 | % This script runs the test implemented in the test folder. 33 | % ----------------------------------------------------------------------- % 34 | clear 35 | runtests('TEST_plugin.m') -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![visitors](https://visitor-badge.laobi.icu/badge?page_id=modenaxe.muscleforcedirection) 2 | # Overview 3 | 4 | The Muscle Force Direction plugin extends the functionalities of [OpenSim](https://simtk.org/projects/opensim/) providing a straighforward interface to extract the muscle lines of action. 5 | The source code of the plugin is provided in the main repository and a dll that can be loaded through the main OpenSim user interface is available through the `Releases` tab. 6 | Leveraging the OpenSim Application Programming Interface (API), we also provide MATLAB scripts that replicate the plugin functionalities. 7 | 8 | # Background 9 | 10 | If you are using the internal forces estimated by musculoskeletal models as load sets in finite element models you find that you have few options to compute the direction of each force vector: 11 | 1. use a PointKinematics analysis on the points of interest of your line of action, compute the force versor for the kinematic frame of interest 12 | 2. use the PointForceDirection class and search for the segment of the muscle line of action that you are interested in. 13 | 14 | The `MuscleForceDirection plugin` (`MFD` plugin for short) tries to streamline this operations and make easier to extract muscle forces and apply them to finite element models. 15 | 16 | ![FE_workflow](https://github.com/modenaxe/MuscleForceDirection/blob/master/images/plugin_workflow.png) 17 | 18 | ## "Anatomical" versus "Effective" lines of action 19 | 20 | Anatomical muscle lines of actions are those whose attachments are on the bones. 21 | 22 | Effective muscle lines of actions are those determining the effective mechanical 23 | effect of the muscle action on the equilibrium of the bone when considering its 24 | free body diagram. 25 | 26 | A typical example is a muscle including _via points_ or _wrapping surface_, for 27 | example the gastronemius, that can alter the muscle lines of action 28 | substantially between the first segment of the muscle and the last segment 29 | attached to a certain bone. 30 | ![anat_vs_effect](https://github.com/modenaxe/MuscleForceDirection/blob/master/images/anatomical_vs_effective.png) 31 | 32 | A good explanation of this difference is available in section 5.4.3 of Yamaguchi's book `Dynamic Modeling of Musculoskeletal Motion: A Vectorized Approach for Biomechanical Analysis in Three Dimensions` entitled `EFFECTIVE ORIGIN AND INSERTION POINTS`. 33 | 34 | # Plugin options 35 | 36 | Using the plugin setup you can decide: 37 | 38 | 1. the body/bodies of interest on which to run the MFD analysis 39 | 2. the reference system in which you want to express the line of actions 40 | 3. choose if you want to extract the "anatomical" lines of action or the "effective" lines of action. 41 | 42 | # Installation 43 | * For compiling the C++ plugin, follow the instructions available on the [OpenSim Developers' Guide](https://simtk-confluence.stanford.edu/display/OpenSim/Developer%27s+Guide), where you can also find some examples. 44 | * For installing the MFD plugin for use in the OpenSim GUI follow the same procedure to install other plugins: 45 | * place the plugin in the `plugins` folder 46 | * restart OpenSim 47 | * For using the MATLAB scripts (OpenSim version ), you need to: 48 | * ensure that the OpenSim API are correctly installed. Please refer to the OpenSim [documentation](https://simtk-confluence.stanford.edu/display/OpenSim/Scripting+with+Matlab). 49 | * include the MATLAB folder in your path. 50 | * check the provided examples. 51 | 52 | # [WORK IN PROGRESS] Examples of use 53 | 54 | There will be examples of how to call the plugin from Matlab etc. 55 | 56 | 57 | # Publications 58 | 59 | The plugin was originally described in the Appendix of [this open access publication](https://github.com/modenaxe/MuscleForceDirection/blob/master/doc/papers/van%20Arkel%20et%20al.%20J%20Orthop%20Res%202013.pdf): 60 | 61 | ```bibtex 62 | @article{van2013hip, 63 | title={Hip abduction can prevent posterior edge loading of hip replacements}, 64 | author={van Arkel, Richard J and Modenese, Luca and Phillips, Andrew TM and Jeffers, Jonathan RT}, 65 | journal={Journal of Orthopaedic Research}, 66 | volume={31}, 67 | number={8}, 68 | pages={1172--1179}, 69 | year={2013}, 70 | publisher={Wiley Online Library} 71 | } 72 | ``` 73 | 74 | but a better example of use is provided in this other open access [paper](https://github.com/modenaxe/MuscleForceDirection/blob/master/doc/papers/Phillips%20et%20al.%20Inter%20Biomech%202015.pdf): 75 | 76 | ```bibtex 77 | @article{phillips2015femoral, 78 | title={Femoral bone mesoscale structural architecture prediction using musculoskeletal and finite element modelling}, 79 | author={Phillips, Andrew TM and Villette, Claire C and Modenese, Luca}, 80 | journal={International Biomechanics}, 81 | volume={2}, 82 | number={1}, 83 | pages={43--61}, 84 | year={2015}, 85 | publisher={Taylor \& Francis} 86 | } 87 | ``` 88 | 89 | # How to contribute 90 | 91 | Feel free of contributing as by standard [GitHub 92 | workflow](https://guides.github.com/activities/forking/): 93 | 94 | 1. forking this repository 95 | 2. creating your own branch, where you make your modifications and improvements 96 | 3. once you are happy with the new feature you have implemented create a pull 97 | request 98 | 99 | ## Resources for learning how to contribute 100 | * If you want to contribute but you are not familiar with [Git](https://git-scm.com/), the [Software Carpentry Lessons](https://swcarpentry.github.io/git-novice/) are a perfect place to start with Git and GitHub. 101 | * If you know how to use git but you are not familiar with GitHub, you can check resources like ["First Contributions"](https://github.com/firstcontributions/first-contributions) to learn how to contribute to existing projects. 102 | 103 | # Resource on combining finite element and musculoskeletal models 104 | * OpenSim Webinar: ["Interfacing Musculoskeletal and Finite Element Models to Study Bone Structure & Adaptation"](https://www.youtube.com/watch?v=0e6vQV_ioCI) 105 | 106 | # Contributors 107 | Several researchers have contributed to this package: 108 | * [Luca Modenese](https://github.com/modenaxe): C++, Matlab 109 | * [John J. Davis IV](https://github.com/johnjdavisiv): Plugin Matlab demo updated to OpenSim 4.2 110 | * [Ke Song](https://github.com/KSongGitHub): Matlab update to OpenSim 4.0 111 | * [Dimitar Stanev](https://github.com/mitkof6): C++ update to OpenSim 4.0 112 | * [Claudio Pizzolato](https://github.com/cpizzolato): C++ makefiles 113 | * [Friedl De Groote](https://github.com/FriedlDeGroote): C++ legacy [version](https://github.com/modenaxe/MuscleForceDirection/tree/master/CPP/legacy_code/OpenSim2.4_KULeuven) of v1.0 114 | * Alfred Thibon: C++ 115 | -------------------------------------------------------------------------------- /_simtk_releases/2012-05-08_MFD_osim2.4_v1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/_simtk_releases/2012-05-08_MFD_osim2.4_v1.0.zip -------------------------------------------------------------------------------- /_simtk_releases/2015-09-03_MFD_osim3.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/_simtk_releases/2015-09-03_MFD_osim3.3.zip -------------------------------------------------------------------------------- /_simtk_releases/2020-12-14_MFD_osim4.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/_simtk_releases/2020-12-14_MFD_osim4.1.zip -------------------------------------------------------------------------------- /_simtk_releases/README.md: -------------------------------------------------------------------------------- 1 | # Packages released on SimTK 2 | 3 | These packages were released in at https://simtk.org/projects/force_direction. 4 | 5 | # Content of packages 6 | 7 | Both packages include: 8 | 9 | 1. the compiled plugin (.dll) 10 | 2. a model used for example 11 | 3. the users' guide. 12 | 13 | # Supported OpenSim version 14 | 15 | * 2012 package supports OpenSim 2.4 16 | * 2015 package supports OpenSim 3.3 17 | -------------------------------------------------------------------------------- /doc/papers/Phillips et al. Inter Biomech 2015.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/papers/Phillips et al. Inter Biomech 2015.pdf -------------------------------------------------------------------------------- /doc/papers/van Arkel et al. J Orthop Res 2013.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/papers/van Arkel et al. J Orthop Res 2013.pdf -------------------------------------------------------------------------------- /doc/users_guide/MFD_users_guide_Aug2015.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/MFD_users_guide_Aug2015.pdf -------------------------------------------------------------------------------- /doc/users_guide/MFD_users_guide_Dec2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/MFD_users_guide_Dec2020.pdf -------------------------------------------------------------------------------- /doc/users_guide/MFD_users_guide_Sept2015.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/MFD_users_guide_Sept2015.pdf -------------------------------------------------------------------------------- /doc/users_guide/MuscleForceDirection UsersGuide_2012.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/MuscleForceDirection UsersGuide_2012.pdf -------------------------------------------------------------------------------- /doc/users_guide/example_Matlab/run_MuscleForceDirection.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/example_Matlab/run_MuscleForceDirection.m -------------------------------------------------------------------------------- /doc/users_guide/word/2-5-2012 MuscleForceDirection_release.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/word/2-5-2012 MuscleForceDirection_release.docx -------------------------------------------------------------------------------- /doc/users_guide/word/2-5-2012 MuscleForceDirection_release_updAugust2015.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/word/2-5-2012 MuscleForceDirection_release_updAugust2015.docx -------------------------------------------------------------------------------- /doc/users_guide/word/2020-12-14_MuscleForceDirection_doc.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/word/2020-12-14_MuscleForceDirection_doc.docx -------------------------------------------------------------------------------- /doc/users_guide/word/Images.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/doc/users_guide/word/Images.zip -------------------------------------------------------------------------------- /images/anatomical_vs_effective.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/images/anatomical_vs_effective.png -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/images/logo.png -------------------------------------------------------------------------------- /images/logo_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/images/logo_v2.png -------------------------------------------------------------------------------- /images/plugin_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/images/plugin_workflow.png -------------------------------------------------------------------------------- /tests/Arm26/MySetupFile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | arm26.osim 5 | . 6 | 12 7 | 0.00000000 8 | 1.00000000 9 | 10 | 11 | 12 | true 13 | 0.00000000 14 | 1.00000000 15 | 1 16 | true 17 | true 18 | false 19 | false 20 | all 21 | 22 | 23 | 24 | 25 | elbow_flexion.mot 26 | 6.0 27 | 28 | 29 | -------------------------------------------------------------------------------- /tests/Arm26/elbow_flexion.mot: -------------------------------------------------------------------------------- 1 | Results 2 | version=1 3 | nRows=121 4 | nColumns=3 5 | inDegrees=yes 6 | endheader 7 | time r_shoulder_elev r_elbow_flex 8 | 0 -0.03394423 -0.05440752 9 | 0.00833333 -0.03657365 0.01417949 10 | 0.01666667 -0.03908443 0.088157 11 | 0.025 -0.04126018 0.17357577 12 | 0.03333333 -0.04302262 0.27576038 13 | 0.04166667 -0.04431782 0.39945264 14 | 0.05 -0.04510954 0.54869991 15 | 0.05833333 -0.04537808 0.72677247 16 | 0.06666667 -0.04512001 0.93612489 17 | 0.075 -0.04434823 1.17840384 18 | 0.08333333 -0.04309148 1.45449954 19 | 0.09166667 -0.04139335 1.76463436 20 | 0.1 -0.03931062 2.10847927 21 | 0.10833333 -0.03691091 2.4852874 22 | 0.11666667 -0.03427009 2.8940335 23 | 0.125 -0.03146918 3.33354847 24 | 0.13333333 -0.02859119 3.80263942 25 | 0.14166667 -0.0257179 4.30018788 26 | 0.15 -0.02292668 4.82522141 27 | 0.15833333 -0.02028769 5.37695629 28 | 0.16666667 -0.01786127 5.95481213 29 | 0.175 -0.01569588 6.55840109 30 | 0.18333333 -0.01382651 7.18749683 31 | 0.19166667 -0.01227362 7.84198911 32 | 0.2 -0.01104271 8.52183068 33 | 0.20833333 -0.01063203 9.22680499 34 | 0.21666667 -0.01014548 9.95712408 35 | 0.225 -0.00994868 10.71250561 36 | 0.23333333 -0.00999836 11.49266577 37 | 0.24166667 -0.01024449 12.29720264 38 | 0.25 -0.01063082 13.12558584 39 | 0.25833333 -0.0110974 13.97716626 40 | 0.26666667 -0.01158331 14.85119468 41 | 0.275 -0.01202923 15.7468464 42 | 0.28333333 -0.01237995 16.66324846 43 | 0.29166667 -0.01258656 17.59950631 44 | 0.3 -0.01260837 18.55472747 45 | 0.30833333 -0.01241432 19.52804021 46 | 0.31666667 -0.01198399 20.51860647 47 | 0.325 -0.01058758 21.52207195 48 | 0.33333333 -0.00959073 22.54440307 49 | 0.34166667 -0.00836629 23.58174648 50 | 0.35 -0.00694125 24.63344306 51 | 0.35833333 -0.00534967 25.69885458 52 | 0.36666667 -0.00363212 26.77735633 53 | 0.375 -0.00183366 27.86832623 54 | 0.38333333 -0.00000136 28.97113454 55 | 0.39166667 0.001818 30.08513509 56 | 0.4 0.00358032 31.20965795 57 | 0.40833333 0.00428682 32.34819524 58 | 0.41666667 0.00590309 33.49117787 59 | 0.425 0.00738472 34.64241319 60 | 0.43333333 0.0087127 35.80113533 61 | 0.44166667 0.00987599 36.96654805 62 | 0.45 0.01087179 38.13783197 63 | 0.45833333 0.01170564 39.31414404 64 | 0.46666667 0.0123917 40.49461673 65 | 0.475 0.01295331 41.67835672 66 | 0.48333333 0.01327011 42.86586863 67 | 0.49166667 0.01377298 44.05247968 68 | 0.5 0.01343804 45.24176825 69 | 0.50833333 0.01425886 46.42911029 70 | 0.51666667 0.01516679 47.6140725 71 | 0.525 0.0157673 48.79835999 72 | 0.53333333 0.01655188 49.97933728 73 | 0.54166667 0.01756672 51.15600652 74 | 0.55 0.01883929 52.32746631 75 | 0.55833333 0.02037991 53.49290785 76 | 0.56666667 0.02218621 54.65157998 77 | 0.575 0.02424569 55.80276096 78 | 0.58333333 0.0265371 56.94574291 79 | 0.59166667 0.02903146 58.07982547 80 | 0.6 0.03169288 59.20431944 81 | 0.60833333 0.03447969 60.3185521 82 | 0.61666667 0.0373455 61.42186798 83 | 0.625 0.0402403 62.51362855 84 | 0.63333333 0.04311165 63.5932109 85 | 0.64166667 0.04589217 64.66132688 86 | 0.65 0.0485404 65.71428274 87 | 0.65833333 0.05102086 66.75336239 88 | 0.66666667 0.0532758 67.77793606 89 | 0.675 0.05525461 68.78735815 90 | 0.68333333 0.05691445 69.78095927 91 | 0.69166667 0.05811323 70.75864875 92 | 0.7 0.05876137 71.71835406 93 | 0.70833333 0.05918762 72.66006045 94 | 0.71666667 0.05930941 73.58300983 95 | 0.725 0.05907709 74.48642151 96 | 0.73333333 0.05846323 75.36950928 97 | 0.74166667 0.05746128 76.23150702 98 | 0.75 0.05608208 77.07169562 99 | 0.75833333 0.05434973 77.88942823 100 | 0.76666667 0.05229773 78.68415149 101 | 0.775 0.04996565 79.45542034 102 | 0.78333333 0.04739652 80.20290345 103 | 0.79166667 0.04463464 80.92637757 104 | 0.8 0.04172377 81.62570894 105 | 0.80833333 0.03870563 82.30082252 106 | 0.81666667 0.03561853 82.95165954 107 | 0.825 0.03249633 83.57812722 108 | 0.83333333 0.02936748 84.18004462 109 | 0.84166667 0.02625434 84.75709092 110 | 0.85 0.0232287 85.31019088 111 | 0.85833333 0.01999313 85.83566423 112 | 0.86666667 0.01687593 86.33409957 113 | 0.875 0.01384316 86.80436866 114 | 0.88333333 0.01087758 87.24519349 115 | 0.89166667 0.00795763 87.65522203 116 | 0.9 0.00505936 88.03313282 117 | 0.90833333 0.00215732 88.37776134 118 | 0.91666667 -0.00077423 88.68824068 119 | 0.925 -0.00376022 88.96414621 120 | 0.93333333 -0.00682352 89.2056338 121 | 0.94166667 -0.00998396 89.4135595 122 | 0.95 -0.01325729 89.58957023 123 | 0.95833333 -0.01665443 89.73615585 124 | 0.96666667 -0.02018099 89.8566562 125 | 0.975 -0.02383697 89.95521895 126 | 0.98333333 -0.02761671 90.03670904 127 | 0.99166667 -0.03150905 90.10657304 128 | 1 -0.03549721 90.17066638 129 | -------------------------------------------------------------------------------- /tests/MFD_tests/Wrapping2.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modenaxe/MuscleForceDirection/c37ee178e04eb34684878997ae1722d3a536d65d/tests/MFD_tests/Wrapping2.m -------------------------------------------------------------------------------- /tests/MFD_tests/dev1_Plugin_verification.m: -------------------------------------------------------------------------------- 1 | clear;clc; 2 | RotAngle = -90:2:90; 3 | 4 | GLOBAL_ANAT = importdata('GLOBAL_ANATOM_MuscleForceDirection_vectors.sto'); 5 | LOCAL_ANAT = importdata('LOCAL_ANATOM_MuscleForceDirection_vectors.sto'); 6 | GLOBAL_EFFECT = importdata('GLOBAL_EFFECT_MuscleForceDirection_vectors.sto'); 7 | LOCAL_EFFECT = importdata('LOCAL_EFFECT_MuscleForceDirection_vectors.sto'); 8 | 9 | %% Muscle 1: MuscleStraight 10 | %P1(0,0,0) in ground to P2(0.3, 0 ,0) in body1 11 | MUS1.v1_Global_Anat_Matlab = [cosd(RotAngle)', sind(RotAngle)',zeros(length(RotAngle),1)]; 12 | % in the sto file, v1 = data(:,2:4) and v2 = -v1 = data(:,5:7) 13 | MUS1.v1_Global_Anat_OpenSim =GLOBAL_ANAT.data(:,2:4); 14 | MUS1.DiffGlobalAnat = MUS1.v1_Global_Anat_Matlab-MUS1.v1_Global_Anat_OpenSim; 15 | 16 | %% Muscle 2: MuscleViaPoint 17 | % Effective: the effective attachments of muscle 2 are the same as muscle 1 18 | v1_Global_Effect_Matlab = MUS1.v1_Global_Anat_Matlab; 19 | % in the sto file, v1 = data(:,8:10) and v2 = -v1 = data(:,11:13) 20 | v1_Global_Effect_OpenSim = GLOBAL_EFFECT.data(:,8:10); 21 | DiffGlobalEffect = v1_Global_Effect_Matlab-v1_Global_Effect_OpenSim; 22 | 23 | %% Muscle 3: MuscleWrap 24 | %P1(0.30000, 0.0 ,0.0) in ground to P2(-0.30000, 0.0 ,0.0) 25 | P1 = [0.30000*ones(length(RotAngle),1), 0.0*ones(length(RotAngle),1) ,0.0*ones(length(RotAngle),1)]; 26 | P2 = -0.3*[cosd(RotAngle)', sind(RotAngle)',zeros(length(RotAngle),1)]; 27 | 28 | % [L,T1_glob,T2_glob,contact] = Wrapping2([0 0 0]',0.05,P1,P2,1,'on') 29 | 30 | count = 0; 31 | for k =1:length(P1) 32 | [L(k,:),T1_glob(k,:),T2_glob(k,:),contact(k,:)] = Wrapping2([0 0 ],0.05,P1(k,1:2),P2(k,1:2),1,'on'); 33 | v1(k,:) = (T1_glob(k,:)-P1(k,1:2))/norm(T1_glob(k,:)-P1(k,1:2)); 34 | end 35 | 36 | v1_GlobalAnat = [v1, zeros(length(P1),1)]; 37 | v1_GlobalAnat_OpenSim = GLOBAL_ANAT.data(:,14:16); 38 | v1_GlobalAnat-v1_GlobalAnat_OpenSim 39 | 40 | -------------------------------------------------------------------------------- /tests/MFD_tests/testKinematics_file.mot: -------------------------------------------------------------------------------- 1 | Results 2 | version=1 3 | nRows=91 4 | nColumns=2 5 | inDegrees=yes 6 | endheader 7 | time AngleRotation 8 | 0 -90 9 | 0.01 -88 10 | 0.02 -86 11 | 0.03 -84 12 | 0.04 -82 13 | 0.05 -80 14 | 0.06 -78 15 | 0.07 -76 16 | 0.08 -74 17 | 0.09 -72 18 | 0.1 -70 19 | 0.11 -68 20 | 0.12 -66 21 | 0.13 -64 22 | 0.14 -62 23 | 0.15 -60 24 | 0.16 -58 25 | 0.17 -56 26 | 0.18 -54 27 | 0.19 -52 28 | 0.2 -50 29 | 0.21 -48 30 | 0.22 -46 31 | 0.23 -44 32 | 0.24 -42 33 | 0.25 -40 34 | 0.26 -38 35 | 0.27 -36 36 | 0.28 -34 37 | 0.29 -32 38 | 0.3 -30 39 | 0.31 -28 40 | 0.32 -26 41 | 0.33 -24 42 | 0.34 -22 43 | 0.35 -20 44 | 0.36 -18 45 | 0.37 -16 46 | 0.38 -14 47 | 0.39 -12 48 | 0.4 -10 49 | 0.41 -8 50 | 0.42 -6 51 | 0.43 -4 52 | 0.44 -2 53 | 0.45 0 54 | 0.46 2 55 | 0.47 4 56 | 0.48 6 57 | 0.49 8 58 | 0.5 10 59 | 0.51 12 60 | 0.52 14 61 | 0.53 16 62 | 0.54 18 63 | 0.55 20 64 | 0.56 22 65 | 0.57 24 66 | 0.58 26 67 | 0.59 28 68 | 0.6 30 69 | 0.61 32 70 | 0.62 34 71 | 0.63 36 72 | 0.64 38 73 | 0.65 40 74 | 0.66 42 75 | 0.67 44 76 | 0.68 46 77 | 0.69 48 78 | 0.7 50 79 | 0.71 52 80 | 0.72 54 81 | 0.73 56 82 | 0.74 58 83 | 0.75 60 84 | 0.76 62 85 | 0.77 64 86 | 0.78 66 87 | 0.79 68 88 | 0.8 70 89 | 0.81 72 90 | 0.82 74 91 | 0.83 76 92 | 0.84 78 93 | 0.85 80 94 | 0.86 82 95 | 0.87 84 96 | 0.88 86 97 | 0.89 88 98 | 0.9 90 99 | -------------------------------------------------------------------------------- /tests/MFD_tests/testModel.osim: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Luca Modenese (l.modenese08@imperial.ac.uk) 6 | This is an example model distributed with the MuscleForceDirection plugin 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 0.00000000 0.000000000 0.00000000 15 | ground 16 | 17 | 18 | 0.300000000 0.00000000 0.00000000 19 | MovingBody 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -0.200000000 0.000000000 0.100000000 32 | ground 33 | 34 | 35 | -0.3000 0.000 0.100000 36 | ground 37 | 38 | 39 | -0.200000000 -0.2000 0.1000000000 40 | ground 41 | 42 | 43 | 0.00000000 0.000000000 0.100000000 44 | ground 45 | 46 | 47 | 0.300000000 0.000000000 0.100000000 48 | MovingBody 49 | 50 | 51 | 0.50000000 0.2000 0.1000000000 52 | MovingBody 53 | 54 | 55 | 0.7000 0.000 0.100000 56 | MovingBody 57 | 58 | 59 | 0.5000 0.000 0.100000 60 | MovingBody 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 0.300000000 0.000000000 0.2000000000 73 | ground 74 | 75 | 76 | -0.300000000 0.000000000 0.2000000000 77 | MovingBody 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | WRAP 86 | axial 87 | -1 -1 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | meters 98 | N 99 | 100 | 0.00000000 -9.80660000 0.00000000 101 | 102 | 103 | 104 | 105 | 0.00000000 106 | 0.00000000 0.00000000 0.00000000 107 | 0.00000000 108 | 0.00000000 109 | 0.00000000 110 | 0.00000000 111 | 0.00000000 112 | 0.00000000 113 | 114 | 115 | 116 | 118 | 119 | 120 | 121 | 122 | treadmill.vtp 123 | 124 | 1.00000000 1.00000000 1.00000000 125 | 126 | 127 | 129 | -0.00000000 0.00000000 -0.00000000 0.00000000 0.00000000 0.00000000 130 | 131 | 1.00000000 1.00000000 1.00000000 132 | 133 | 4 134 | 135 | 1.00000000 136 | 137 | 138 | 139 | 140 | 141 | 0.1500000000 0.1500000000 0.1500000000 142 | 144 | -0.00000000 0.00000000 -0.00000000 0.00000000 0.00000000 0.00000000 145 | 146 | false 147 | 149 | 4 150 | 151 | 152 | 153 | 0.0 154 | 0.00000000 0.0 0.00000000 155 | 0.00000000 156 | 0.00000000 157 | 0.00000000 158 | 0.00000000 159 | 0.00000000 160 | 0.00000000 161 | 162 | 163 | 164 | ground 165 | 0.00000000 0.00000000 0.00000000 166 | 0.00000000 0.00000000 0.00000000 167 | 0.00000000 0.00000000 0.00000000 168 | 0.00000000 0.00000000 0.00000000 169 | 170 | 171 | 172 | 173 | 175 | rotational 176 | 0.00000000 177 | 0.00000000 178 | -1.57079633 1.57079633 179 | false 180 | false 181 | 182 | 183 | 184 | 185 | 186 | false 187 | 188 | 189 | 190 | 191 | 192 | 1.00000000 0.00000000 193 | 194 | 195 | AngleRotation 196 | 0.0000000000 0.0000000000 1.0000000000 197 | 198 | 199 | 200 | 201 | 0.00000000 202 | 203 | 204 | 205 | 0.00000000 1.00000000 0.00000000 206 | 207 | 208 | 209 | 210 | 0.00000000 211 | 212 | 213 | 214 | 0.99826136 -0.00000000 0.05889802 215 | 216 | 217 | 218 | 219 | 220 | 0.00000000 221 | 222 | 223 | 224 | 1.00000000 0.00000000 0.00000000 225 | 226 | 227 | 228 | 229 | 0.00000000 230 | 231 | 232 | 233 | 0.00000000 1.00000000 0.00000000 234 | 235 | 236 | 237 | 238 | 0.00000000 239 | 240 | 241 | 242 | 0.00000000 0.00000000 1.00000000 243 | 244 | 245 | 246 | 247 | 248 | 250 | 251 | 252 | 253 | 254 | treadmill.vtp 255 | 256 | 1.00000000 1.00000000 1.00000000 257 | 258 | 259 | 261 | -0.00000000 0.00000000 -0.00000000 0.00000000 0.00000000 0.00000000 262 | 263 | 1.00000000 1.00000000 1.00000000 264 | 265 | 4 266 | 267 | 1.00000000 268 | 269 | 270 | 271 | 272 | 273 | 0.1500000000 0.1500000000 0.1500000000 274 | 276 | -0.00000000 0.00000000 -0.00000000 0.00000000 0.00000000 0.00000000 277 | 278 | false 279 | 281 | 4 282 | 283 | 284 | 285 | 286 | 0.00000000 0.00000000 0.00000000 287 | 0.00000000 0.00000000 0.200000000 288 | true 289 | Y 290 | 291 | 293 | 294 | 295 | 296 | 297 | 298 | 1.00000000 1.00000000 1.00000000 299 | 301 | 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.200000000 302 | 303 | false 304 | 306 | 4 307 | 308 | 0.05000000 309 | 0.05000000 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | -------------------------------------------------------------------------------- /tests/test_checklist.txt: -------------------------------------------------------------------------------- 1 | // Robustness 2 | 3 | 1) Load 4 | 2) Runs from GUI 5 | 3) Runs from GUI in a sequence of analyses 6 | 4) Runs from GUI loading the setting from xml 7 | 5) Runs from command line 8 | 9 | // Results 10 | 11 | 6) Runs with one body selected 12 | 7) Runs with two bodies selected 13 | 8) Runs with all. 14 | --------------------------------------------------------------------------------