From 7b859d6a47397bc161c788043157c2839b89f7d0 Mon Sep 17 00:00:00 2001 From: Luca Modenese Date: Thu, 6 May 2021 18:50:51 +0100 Subject: [PATCH 1/8] upd to OS4 and maintain compatibility with 3.3 --- MATLAB_tool/MuscleParOptTool/getBodyJoint.m | 64 +++++++++++++++++++ .../MuscleParOptTool/getOpenSimVersion.m | 26 ++++++++ .../private/getJointsSpannedByMuscle.m | 43 ++++++------- .../private/sampleMuscleQuantities.m | 28 ++++---- 4 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 MATLAB_tool/MuscleParOptTool/getBodyJoint.m create mode 100644 MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m diff --git a/MATLAB_tool/MuscleParOptTool/getBodyJoint.m b/MATLAB_tool/MuscleParOptTool/getBodyJoint.m new file mode 100644 index 0000000..0f5ecb6 --- /dev/null +++ b/MATLAB_tool/MuscleParOptTool/getBodyJoint.m @@ -0,0 +1,64 @@ +%-------------------------------------------------------------------------% +% Copyright (c) 2021 Modenese L. % +% Author: Luca Modenese, 2021 % +% email: l.modenese@imperial.ac.uk % +% ----------------------------------------------------------------------- % +% Function replacing the old getJoint() method that we all loved in OpenSim +% 3.3 but currently non available in OpenSim 4.x. +% Returns the joint for which the specified body would be the child. +% ----------------------------------------------------------------------- % +function bodyJoint = getBodyJoint(osimModel, aBodyName, debug_printout) + +import org.opensim.modeling.*; + +if nargin<3; debug_printout=0; end + +% check if body is included in the model +if osimModel.getBodySet().getIndex(aBodyName)<0 + error(['getBodyJoint.m The specified body ', aBodyName,' is not included in the OpenSim model']) +end + +% get jointset +jointSet = osimModel.getJointSet(); + +% loop through jointset +nj = 1; + +for n_joint = 0:jointSet.getSize()-1 + + % get cur joint + cur_joint = jointSet.get(n_joint); + + % child frame from joint + child_frame = cur_joint.getChildFrame(); + + % link back to base frame: this could be a body + body_of_frame = child_frame.findBaseFrame(); + + % get base frame name + possible_body_name = char(body_of_frame.getName()); + + % if body with that name exist than the joint is that body's joint + if osimModel.getBodySet.getIndex(possible_body_name)>0 && strcmp(aBodyName, possible_body_name) + + % save the joints with the specified body as Child + jointName(nj) = {char(cur_joint.getName())}; + + if debug_printout + disp([aBodyName, ' is parent frame on joint: ',jointName{nj}]); + end + % update counter + nj = nj + 1; + continue + end +end + +% return a string if there is only one body +if numel(jointName)==1 + jointName = jointName{1}; + bodyJoint = osimModel.getJointSet.get(jointName); +else + error(['getBodyJoint.m More than one joint connected to body of interest', aBodyName,'. This function is design to work as getJoint() in OpenSim 3.3.']) +end + +end diff --git a/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m b/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m new file mode 100644 index 0000000..0645f02 --- /dev/null +++ b/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m @@ -0,0 +1,26 @@ +%-------------------------------------------------------------------------% +% Copyright (c) 2021 Modenese L. % +% Author: Luca Modenese, 2021 % +% email: l.modenese@imperial.ac.uk % +% ----------------------------------------------------------------------- % +% This script returns the OpenSim version for which the environmental +% variable OPENSIM_HOME has been set. +% ----------------------------------------------------------------------- % +function [osim_version_float, osim_version_string] = getOpenSimVersion() + +% read env variable +osimpath = getenv('OPENSIM_HOME'); + +% get the file separators, e.g. '\' in 'C:\Program files\OpenSim 4.1' +sep_set = strfind(osimpath, filesep); + +% use the last file separator to get the OpenSim installation folder name +version = osimpath(sep_set(end)+1:end); + +% get the string for the opensim version +osim_version_string = strtrim(strrep(lower(version),'opensim', '')); + +% transform in float +osim_version_float = str2num(osim_version_string); + +end \ No newline at end of file diff --git a/MATLAB_tool/MuscleParOptTool/private/getJointsSpannedByMuscle.m b/MATLAB_tool/MuscleParOptTool/private/getJointsSpannedByMuscle.m index bce75c1..b499cc5 100644 --- a/MATLAB_tool/MuscleParOptTool/private/getJointsSpannedByMuscle.m +++ b/MATLAB_tool/MuscleParOptTool/private/getJointsSpannedByMuscle.m @@ -42,10 +42,6 @@ BodySet = osimModel.getBodySet(); muscle = osimModel.getMuscles.get(OSMuscleName); -% additions BAK -% load a jointStrucute detailing bone and joint configurations -jointStructure = getModelJointDefinitions(osimModel); - % Extracting the PathPointSet via GeometryPath musclePath = muscle.getGeometryPath(); musclePathPointSet = musclePath.getPathPointSet(); @@ -90,22 +86,25 @@ jointNameSet = {}; while ~strcmp(bodyName,ProximalBodyName) - %spannedJoint = body.getJoint(); - %spannedJointName = char(spannedJoint.getName()); + if getOpenSimVersion()<4.0 + spannedJoint = body.getJoint(); + else + spannedJoint = getBodyJoint(osimModel, char(body.getName()), 0); + end + + spannedJointName = char(spannedJoint.getName()); - % BAK implementation - spannedJointName = getChildBodyJoint(jointStructure, body.getName()); - spannedJoint = osimModel.getJointSet().get(spannedJointName); - if strcmp(spannedJointName, spannedJointNameOld) - %body = spannedJoint.getParentBody(); - % BAK implementation - body = jointStructure.spannedJoint.parentBody; - + body = spannedJoint.getParentBody(); spannedJointNameOld = spannedJointName; else - %if spannedJoint.getCoordinateSet().getSize()~=0 - if spannedJoint.numCoordinates()~=0 + if getOpenSimVersion()<4.0 + nr_coords = spannedJoint.getCoordinateSet().getSize(); + else + nr_coords = spannedJoint.numCoordinates(); + end + if nr_coords~=0 + jointNameSet{n_spanJoint} = spannedJointName; n_spanJoint = n_spanJoint+1; else @@ -113,13 +112,13 @@ n_spanJointNoDof = n_spanJointNoDof+1; end spannedJointNameOld = spannedJointName; - %body = spannedJoint.getParentBody(); - bodyName = jointStructure.(char(spannedJointName)).parentBody; - body = osimModel.getBodySet().get(bodyName); - + if getOpenSimVersion()<4.0 + body = spannedJoint.getParentBody(); + else + body = spannedJoint.getParentFrame().findBaseFrame(); + end end - bodyName = body.getName(); - + bodyName = char(body.getName()); end if isempty(jointNameSet) diff --git a/MATLAB_tool/MuscleParOptTool/private/sampleMuscleQuantities.m b/MATLAB_tool/MuscleParOptTool/private/sampleMuscleQuantities.m index 8159d01..c75a3d2 100644 --- a/MATLAB_tool/MuscleParOptTool/private/sampleMuscleQuantities.m +++ b/MATLAB_tool/MuscleParOptTool/private/sampleMuscleQuantities.m @@ -56,10 +56,7 @@ % limit (1) or not (0) the discretization of the joint space sampling limit_discr = 0; % minimum angular discretization -%min_increm_in_deg = 2.5; -min_increm_in_deg = 1; - - +min_increm_in_deg = 2.5; %======================= % initialize the model @@ -68,7 +65,7 @@ % getting the joint crossed by a muscle muscleCrossedJointSet = getJointsSpannedByMuscle(osimModel, OSMuscle); -% index f+or effective dofs +% index for effective dofs n_dof = 1; DOF_Index = []; for n_joint = 1:size(muscleCrossedJointSet,2) @@ -77,12 +74,15 @@ curr_joint = muscleCrossedJointSet{n_joint}; % get CoordinateSet for the crossed joint - %curr_joint_CoordinateSet = osimModel.getJointSet().get(curr_joint).getCoordinateSet(); + if getOpenSimVersion()<4.0 + curr_joint_CoordinateSet = osimModel.getJointSet().get(curr_joint).getCoordinateSet(); + % Initial estimation of the nr of Dof of the CoordinateSet for that + % joint before checking for locked and constraint dofs. + nDOF = osimModel.getJointSet().get(curr_joint).getCoordinateSet().getSize(); + else + nDOF = osimModel.getJointSet().get(curr_joint).numCoordinates(); + end - % Initial estimation of the nr of Dof of the CoordinateSet for that - % joint before checking for locked and constraint dofs. - %nDOF = osimModel.getJointSet().get(curr_joint).getCoordinateSet().getSize(); - nDOF = osimModel.getJointSet().get(curr_joint).numCoordinates(); % skip welded joint and removes welded joint from muscleCrossedJointSet if nDOF == 0; continue; @@ -93,9 +93,11 @@ for n_coord = 0:nDOF-1 % get coordinate - %curr_coord = curr_joint_CoordinateSet.get(n_coord); - curr_coord = osimModel.getJointSet().get(curr_joint).get_coordinates(n_coord); - + if getOpenSimVersion()<4.0 + curr_coord = curr_joint_CoordinateSet.get(n_coord); + else + curr_coord = osimModel.getJointSet().get(curr_joint).get_coordinates(n_coord); + end curr_coord_name = char(curr_coord.getName()); % skip dof if locked From a5be866da632f0495883a5f566ac113553532c8e Mon Sep 17 00:00:00 2001 From: Luca Modenese Date: Thu, 6 May 2021 19:06:51 +0100 Subject: [PATCH 2/8] add default --- .../MuscleParOptTool/getChildBodyJoint.m | 27 ------------ .../getModelJointDefinitions.m | 42 ------------------- .../MuscleParOptTool/getOpenSimVersion.m | 7 ++++ 3 files changed, 7 insertions(+), 69 deletions(-) delete mode 100644 MATLAB_tool/MuscleParOptTool/getChildBodyJoint.m delete mode 100644 MATLAB_tool/MuscleParOptTool/getModelJointDefinitions.m diff --git a/MATLAB_tool/MuscleParOptTool/getChildBodyJoint.m b/MATLAB_tool/MuscleParOptTool/getChildBodyJoint.m deleted file mode 100644 index 161b732..0000000 --- a/MATLAB_tool/MuscleParOptTool/getChildBodyJoint.m +++ /dev/null @@ -1,27 +0,0 @@ -% functon to return the name of the joint from a specified model and joint -% structure ( generatate using getModelJointDefinitions.m ) , where the -% specified body is the child body - -% Written by Bryce Killen bryce.killen@kuleuven.be as part of an extension -% of work by Luca Modenese in the parameterisation of muscle tendon -% properties - - -% Input: OpenSim model objects -% Output: jointName - the joint where the specified body is the child - -function jointName = getChildBodyJoint(jointStructure, bodyName) - - % return a list of the joints - allJoints = fieldnames(jointStructure); - - % loop through joints to check the child body entry and return if true - % NOTE: inefficient but will work temp. - - for j = 1:length(allJoints) - if strcmp(jointStructure.(char(allJoints(j))).childBody , bodyName) - jointName = char(allJoints(j)); - return - end - end -end \ No newline at end of file diff --git a/MATLAB_tool/MuscleParOptTool/getModelJointDefinitions.m b/MATLAB_tool/MuscleParOptTool/getModelJointDefinitions.m deleted file mode 100644 index 23fbab1..0000000 --- a/MATLAB_tool/MuscleParOptTool/getModelJointDefinitions.m +++ /dev/null @@ -1,42 +0,0 @@ -% functon to retun a strcuture for a specifc model, returning a list of the -% joints present in the model and their associated frames and subsequently -% the bodies which make up these joints - operating under the assumption -% that frames are written using the bodyName_offset as naming convention - -% Written by Bryce Killen bryce.killen@kuleuven.be as part of an extension -% of work by Luca Modenese in the parameterisation of muscle tendon -% properties - - -% Input: OpenSim model objects -% Output structure where each joint is listed followed by the parent and -% child frames / body names - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -function jointStructure = getModelJointDefinitions(osimModel) - -% first get the associated jointset -modelJointSet = osimModel.getJointSet(); -% return the number of joints -numJoints = modelJointSet().getSize(); - -% create an empty structure to hold the data -jointStructure=struct(); - -for j = 0:numJoints-1 - tempJoint = modelJointSet.get(j); - % add the name to the structure - jointStructure.(char(tempJoint.getName())) = struct(); - % add the parent frame name - jointStructure.(char(tempJoint.getName())).parentFrame = char(tempJoint.getPropertyByName('socket_parent_frame')); - % add the child frame name - jointStructure.(char(tempJoint.getName())).childFrame = char(tempJoint.getPropertyByName('socket_child_frame')); - % add the parent body - jointStructure.(char(tempJoint.getName())).parentBody = regexprep(char(tempJoint.getPropertyByName('socket_parent_frame')), '_offset',''); - % add the child body - jointStructure.(char(tempJoint.getName())).childBody = regexprep(char(tempJoint.getPropertyByName('socket_child_frame')), '_offset',''); -end - -end \ No newline at end of file diff --git a/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m b/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m index 0645f02..1089a67 100644 --- a/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m +++ b/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m @@ -11,6 +11,13 @@ % read env variable osimpath = getenv('OPENSIM_HOME'); +% let's assume it's the latest version in case there is no path variable +if isempty(osimpath) + osim_version_float = 4.1; + osim_version_string = '4.1'; + return +end + % get the file separators, e.g. '\' in 'C:\Program files\OpenSim 4.1' sep_set = strfind(osimpath, filesep); From 9931ed4e22a2708541a898644957c33d32b0edcb Mon Sep 17 00:00:00 2001 From: Luca Modenese Date: Thu, 6 May 2021 19:13:24 +0100 Subject: [PATCH 3/8] (test) add test for OS4.x. NOTE that loss function is ~0.01 - requires new expected model --- tests/TESTS_MusOptTool.m | 11 +- tests/models/test2_expected_v4.osim | 2101 +++++++++++++++++++++++++++ 2 files changed, 2110 insertions(+), 2 deletions(-) create mode 100644 tests/models/test2_expected_v4.osim diff --git a/tests/TESTS_MusOptTool.m b/tests/TESTS_MusOptTool.m index 4f519e5..8f37a55 100644 --- a/tests/TESTS_MusOptTool.m +++ b/tests/TESTS_MusOptTool.m @@ -36,8 +36,15 @@ % optimize [osimModel_opt, SimsInfo] = optimMuscleParams(reference_model, target_model, N_eval, log_folder); -% test -expected_model = './models/test2_expected.osim'; +% test: note that from OpenSim 3.3 to 4.x results are slightly different +% if compared to 'test2_expected.osim', a model optimized with OpenSim 4 +% would have a loss function ~ 0.001. +if getOpenSimVersion()<4 + expected_model = './models/test2_expected.osim'; +else + expected_model = './models/test2_expected_v4.osim'; +end + osimExp = Model(expected_model); % load muscles exp_mus = osimExp.getMuscles(); diff --git a/tests/models/test2_expected_v4.osim b/tests/models/test2_expected_v4.osim new file mode 100644 index 0000000..4961855 --- /dev/null +++ b/tests/models/test2_expected_v4.osim @@ -0,0 +1,2101 @@ + + + + + + true + true + -1 + 1 + false + false + + + + 100 + 20 + + + + Unassigned + + 300 + + + + + + 0 0 0 + + false + + -1 -0 -0 + + true + + 1000 + + + + Unassigned + + Unassigned + + true + + -1 -0 -0 + + 1 + + + + + + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 546 + + 0.053499999999999999 + + 0.078 + + 0 + + 10 + + 0.033000000000000002 + + 0.59999999999999998 + + 0.5 + + 4 + + 0.29999999999999999 + + 1.8 + + 0.01 + + 0.040000000000000001 + + + + false + + 1 1 1 + + -1 + + -1 + + false false false + + 1 1 1 + + 1 1 1 + + 1 1 1 + + 0 0 0 + + 0 0 0 + + 0 0 0 + + + + 0 + + + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + + + + + + + + + 0 -9.8066499999999994 0 + + Luca Modenese for the building the model. The LHDL consortium (Istituto Ortopedico Rizzoli and the Université Libre de Bruxelles) for providing the data. + + Unassigned + + meters + + N + + + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + + + + .. + + 0.001 0.001 0.001 + + + + 1 + + 1 1 1 + + + S032_C_B000_CTA_Sacrum.vtp + + + + .. + + 0.001 0.001 0.001 + + + + 1 + + 1 1 1 + + + S032_L_B000_CTA_Iliac.vtp + + + + .. + + 0.001 0.001 0.001 + + + + 1 + + 1 1 1 + + + S032_R_B000_CTA_Iliac.vtp + + + + + + + + + 956260 + + 0.23888599999999999 0.26692500000000002 -0.37103199999999997 + + 0.0029646799999999999 0.0029257699999999998 0.00152181 1.14283e-05 8.9783699999999999e-05 -1.88789e-05 + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + + + + .. + + 0.001 0.001 0.001 + + + + 1 + + 1 1 1 + + + S032_R_B000_CTA_Femur.vtp + + + + .. + + 0.001 0.001 0.001 + + + + 1 + + 1 1 1 + + + S032_R_B000_CTA_Patella.vtp + + + + + + + + + 546967 + + 0.119785 0.25196600000000002 -0.73336599999999996 + + 0.0127838 0.012810500000000001 0.000283792 -1.39135e-05 -0.000103368 -0.00064032 + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + + + + .. + + 0.001 0.001 0.001 + + + + 1 + + 1 1 1 + + + S032_R_B000_CTA_Tibia.vtp + + + + .. + + 0.001 0.001 0.001 + + + + 1 + + 1 1 1 + + + S032_R_B000_CTA_Fibula.vtp + + + + + + + + + 410386 + + 0.109108 0.30802400000000002 -1.0197099999999999 + + 0.0059605999999999999 0.0059738999999999999 0.00012472899999999999 9.3379000000000008e-06 -0.00014791699999999999 -0.00029031400000000001 + + + + + + + + + + ground_offset + + pelvis_offset + + + + + 0 + + -0.78539816339744795 0.78539816339744795 + + true + + false + + + + 0 + + -0.78539816339744795 0.78539816339744795 + + true + + false + + + + 0 + + -0.78539816339744795 0.78539816339744795 + + true + + false + + + + 0 + + -0.5 0.5 + + true + + false + + + + 0 + + -0.5 0.5 + + true + + false + + + + 0 + + -0.5 0.5 + + true + + false + + + + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + /ground + + 0 0 0 + + 0 0 0 + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + /bodyset/pelvis + + 0.23885500000000001 0.180177 -0.35760500000000001 + + -2.77372 -1.56193 1.8084899999999999 + + + + + + + + xRotation + + 1 0 0 + + + 1 0 + + + + + yRotation + + 0 1 0 + + + 1 0 + + + + + zRotation + + 0 0 1 + + + 1 0 + + + + + + xTranslation + + 1 0 0 + + + 1 0 + + + + + yTranslation + + 0 1 0 + + + 1 0 + + + + + zTranslation + + 0 0 1 + + + 1 0 + + + + + + + pelvis_offset + + femur_r_offset + + + + + -0.34906585000000001 0.78539999999999999 + + false + + + + -0.34906585000000001 0.34906585000000001 + + false + + + + -0.34906585000000001 0.34906585000000001 + + false + + + + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + /bodyset/pelvis + + 0.14347799999999999 0.24343899999999999 -0.43267 + + -2.77372 -1.56193 1.8084899999999999 + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + /bodyset/femur_r + + 0.14347799999999999 0.24343899999999999 -0.43266900000000003 + + -0.80667299999999997 -1.45075 -2.47682 + + + + + + + + hip_flexion + + 0 0 1 + + + 1 0 + + + + + hip_adduction + + 1 0 0 + + + 1 0 + + + + + hip_rotation + + 0 1 0 + + + 1 0 + + + + + + + + 1 0 0 + + + 0 + + + + + + + 0 1 0 + + + 0 + + + + + + + 0 0 1 + + + 0 + + + + + + + femur_r_offset + + tibia_r_offset + + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + /bodyset/femur_r + + 0.123249 0.28328700000000001 -0.82717300000000005 + + -0.80667299999999997 -1.45075 -2.47682 + + + + + + .. + + 0.20000000000000001 0.20000000000000001 0.20000000000000001 + + + /bodyset/tibia_r + + 0.123249 0.28328700000000001 -0.82717300000000005 + + -0.80667299999999997 -1.45075 -2.47682 + + + + + + + + + + + + + + + + + + + + + + + + + + + /bodyset/pelvis + + 0.221275 0.21334 -0.46980699999999997 + + + + /bodyset/femur_r + + 0.114304 0.27501599999999998 -0.55340500000000004 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.11992430045068711 + + 0.025372474411508389 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.21154600000000001 0.205317 -0.45968799999999999 + + + + /bodyset/femur_r + + 0.120119 0.26865600000000001 -0.62543499999999996 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.10634268337868293 + + 0.085971560796656021 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.20805199999999999 0.242784 -0.486043 + + + + /bodyset/femur_r + + 0.11373800000000001 0.27320499999999998 -0.60933999999999999 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.17613000885453134 + + 0.029781635522797764 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.194053 0.26411299999999999 -0.49095299999999997 + + + + /bodyset/femur_r + + 0.118267 0.27175100000000002 -0.67729700000000004 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.1983895261914102 + + 0.04731472486860229 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.16995299999999999 0.29092499999999999 -0.48738500000000001 + + + + /bodyset/femur_r + + 0.15732399999999999 0.290987 -0.812338 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.16950869751967992 + + 0.19497019210249691 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.15243399999999999 0.29252499999999998 -0.465138 + + + + /bodyset/femur_r + + 0.088550799999999999 0.32029299999999999 -0.82017099999999998 + + + + /bodyset/femur_r + + 0.080872100000000002 0.31590299999999999 -0.86924900000000005 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.088678789611170594 + + 0.32934348302434951 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.14795800000000001 0.29195700000000002 -0.44450200000000001 + + + + /bodyset/femur_r + + 0.102091 0.254527 -0.43299399999999999 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.02175768888145687 + + 0.039117780626889677 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.18101300000000001 0.305122 -0.33890799999999999 + + + + /bodyset/pelvis + + 0.129634 0.31848599999999999 -0.38734099999999999 + + + + /bodyset/femur_r + + 0.106585 0.305176 -0.445413 + + + + /bodyset/femur_r + + 0.098969399999999999 0.28409499999999999 -0.47715299999999999 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.17244779040110744 + + 0.015009573990436599 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.20041400000000001 0.32826100000000002 -0.37271100000000001 + + + + /bodyset/pelvis + + 0.14990200000000001 0.33267799999999997 -0.44741199999999998 + + + + /bodyset/femur_r + + 0.12745799999999999 0.319156 -0.491282 + + + + /bodyset/femur_r + + 0.106324 0.28216799999999997 -0.51803600000000005 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.20393040580638594 + + 0.0093333615714745778 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.220357 0.34368300000000002 -0.40957700000000002 + + + + /bodyset/pelvis + + 0.18218400000000001 0.34247499999999997 -0.46408300000000002 + + + + /bodyset/femur_r + + 0.14128199999999999 0.31172100000000003 -0.53973800000000005 + + + + /bodyset/femur_r + + 0.109044 0.276974 -0.562365 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.20178108184924071 + + 0.028191850611823912 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.108919 0.23350199999999999 -0.32053900000000002 + + + + /bodyset/femur_r + + 0.084383799999999995 0.26570300000000002 -0.43667099999999998 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.074181621605747858 + + 0.061503824060018496 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.15024199999999999 0.268038 -0.30354500000000001 + + + + /bodyset/femur_r + + 0.087016700000000002 0.26813900000000002 -0.43116399999999999 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.074050185929829149 + + 0.079786994958114157 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.16067200000000001 0.27905600000000003 -0.341617 + + + + /bodyset/femur_r + + 0.090207099999999998 0.276586 -0.43028499999999997 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.071866876210905165 + + 0.053686412334317042 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.119296 0.20614199999999999 -0.358404 + + + + /bodyset/femur_r + + 0.087871199999999997 0.25098900000000002 -0.44503900000000002 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.065426236682896335 + + 0.038994987454095978 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.122324 0.23303599999999999 -0.35264400000000001 + + + + /bodyset/femur_r + + 0.088438900000000001 0.25039299999999998 -0.43540000000000001 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.056730062898310889 + + 0.035490483729974792 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.140817 0.25397500000000001 -0.34620000000000001 + + + + /bodyset/femur_r + + 0.095188099999999998 0.25052200000000002 -0.429533 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.035294681933095672 + + 0.062231160806453245 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.223275 0.229847 -0.47895599999999999 + + + + /bodyset/femur_r + + 0.155776 0.31160500000000002 -0.84045999999999998 + + + + /bodyset/femur_r + + 0.15332699999999999 0.29226999999999997 -0.88132500000000003 + + + + /bodyset/femur_r + + 0.13839099999999999 0.27671800000000002 -0.89171800000000001 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.3353498340697148 + + 0.044879422156697622 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.14685300000000001 0.23707800000000001 -0.33537899999999998 + + + + /bodyset/pelvis + + 0.15498300000000001 0.20807800000000001 -0.40079900000000002 + + + + /bodyset/pelvis + + 0.15565799999999999 0.21330499999999999 -0.43623299999999998 + + + + /bodyset/femur_r + + 0.14746100000000001 0.23730599999999999 -0.46383000000000002 + + + + /bodyset/femur_r + + 0.131991 0.26460600000000001 -0.48124699999999998 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.071146962985994655 + + 0.10412702433333536 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.198628 0.203233 -0.44589200000000001 + + + + /bodyset/femur_r + + 0.122782 0.27279100000000001 -0.51151500000000005 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.14995308742441518 + + 0.0010024680919688811 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.20945800000000001 0.308865 -0.37295800000000001 + + + + /bodyset/pelvis + + 0.16093199999999999 0.30033300000000002 -0.384824 + + + + /bodyset/femur_r + + 0.10152700000000001 0.26933000000000001 -0.42594700000000002 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.031164979815327301 + + 0.10799186740603994 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.20921899999999999 0.27892499999999998 -0.26406800000000002 + + + + /bodyset/pelvis + + 0.16753100000000001 0.213529 -0.41176299999999999 + + + + /bodyset/pelvis + + 0.16140499999999999 0.21620700000000001 -0.44633499999999998 + + + + /bodyset/femur_r + + 0.15029100000000001 0.23986299999999999 -0.46228799999999998 + + /jointset/hip_r/hip_flexion + + -0.34906599999999999 0.61086499999999999 + + + + /bodyset/femur_r + + 0.136742 0.274754 -0.47996499999999997 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.12278290624687217 + + 0.13583063310235469 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.17091000000000001 0.28068700000000002 -0.47572799999999998 + + + + /bodyset/femur_r + + 0.10959199999999999 0.28714099999999998 -0.45269399999999999 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.034482142266161808 + + 0.035651108506639294 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.13422700000000001 0.20704400000000001 -0.39937099999999998 + + + + /bodyset/femur_r + + 0.124376 0.228268 -0.80344300000000002 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.072277066338319276 + + 0.3392247320710074 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.116993 0.18304000000000001 -0.36308099999999999 + + + + /bodyset/femur_r + + 0.16433300000000001 0.293352 -0.771648 + + + + /bodyset/femur_r + + 0.16449 0.30541800000000002 -0.82913099999999995 + + + + /bodyset/femur_r + + 0.16200400000000001 0.29277199999999998 -0.84989300000000001 + + + + /bodyset/femur_r + + 0.132211 0.27272999999999997 -0.89967399999999997 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.47660543627184482 + + 0.014028263744273945 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.15790799999999999 0.284022 -0.47032299999999999 + + + + /bodyset/femur_r + + 0.137962 0.323403 -0.83540599999999998 + + + + /bodyset/femur_r + + 0.14652999999999999 0.30752099999999999 -0.86734599999999995 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.06308078778525332 + + 0.37088039793512018 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.154138 0.29170000000000001 -0.467831 + + + + /bodyset/femur_r + + 0.14290900000000001 0.32874399999999998 -0.78715100000000005 + + + + /bodyset/femur_r + + 0.15002299999999999 0.31997300000000001 -0.84063600000000005 + + + + /bodyset/femur_r + + 0.152619 0.30602400000000002 -0.89074399999999998 + + + + /bodyset/femur_r + + 0.13677600000000001 0.27762700000000001 -0.89960899999999999 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.16442580906937779 + + 0.28029374967376491 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.10994900000000001 0.19059799999999999 -0.348852 + + + + /bodyset/femur_r + + 0.090409799999999998 0.23835000000000001 -0.55857800000000002 + + + + /bodyset/femur_r + + 0.086015599999999998 0.26825399999999999 -0.779748 + + + + /bodyset/femur_r + + 0.080546099999999995 0.27647100000000002 -0.87193100000000001 + + + + + + + + + + + + + 0.80000000000000004 0.10000000000000001 0.10000000000000001 + + + + 1000 + + 0.091694408807440786 + + 0.43900494868391432 + + 0 + + 10 + + + + + + + + + + /bodyset/pelvis + + 0.360151 0.181173 -0.35642000000000001 + + false + + + + /bodyset/pelvis + + 0.117559 0.17918100000000001 -0.35879 + + false + + + + /bodyset/pelvis + + 0.23885500000000001 0.180177 -0.35760500000000001 + + false + + + + /bodyset/pelvis + + 0.23915400000000001 0.32203100000000001 -0.33903299999999997 + + false + + + + /bodyset/pelvis + + 0.19858500000000001 0.32090800000000003 -0.33729799999999999 + + false + + + + /bodyset/pelvis + + 0.279723 0.323154 -0.34076800000000002 + + false + + + + /bodyset/femur_r + + 0.163134 0.27981400000000001 -0.83050199999999996 + + false + + + + /bodyset/femur_r + + 0.083364199999999999 0.28676099999999999 -0.82384400000000002 + + false + + + + /bodyset/femur_r + + 0.123249 0.28328700000000001 -0.82717300000000005 + + false + + + + /bodyset/femur_r + + 0.14347799999999999 0.24343899999999999 -0.43267 + + false + + + + + + + + + + + + + + + + + + + + + From 63280062a72504eaac28869eb356e9fd504270b8 Mon Sep 17 00:00:00 2001 From: Luca Modenese Date: Thu, 6 May 2021 19:20:55 +0100 Subject: [PATCH 4/8] upd readme --- README.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 12670a0..f72abc2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ +# Table of Contents +- [Introduction](#introduction) +- [Requirements](#requirements) +- [Contents from the paper](#contents-from-the-paper) + - [Algorithm description](#algorithm-description) + - [Considered Cases](#considered-cases) +- [Versions of the tool](#versions-of-the-tool) + - [MATLAB version](#matlab-version) + - [Python tool (currently under revision)](#python-tool-currently-under-revision) + - [OpenSim C++ plugin and User Interface Menu](#opensim-c-plugin-and-user-interface-menu) +- [Notes on upgrading to OpenSim 4.0 and backward compatibility](#notes-on-upgrading-to-opensim-40-and-backward-compatibility) +- [Contributors](#contributors) +- [References](#references) + # Introduction This repository contains a MATLAB package implementing an algorithm for optimizing the parameters of Hill-type muscle models defined by adimensional force-lenght-velocity curves, as described by _Zajac (1989)_. @@ -56,7 +70,7 @@ __Please note__ that reproducing the sensitivity study can be time-consuming, de ## Python tool (currently under revision) -A Python version of the tool has been written and kindly shared by @eravera. It is currently **under assessment** although tested and working. +A Python version of the tool has been written and kindly shared by @eravera. ## OpenSim C++ plugin and User Interface Menu @@ -66,6 +80,15 @@ A generic tool to optimize musculotendon parameters in musculoskeletal models is * as menu extension of the OpenSim GUI (graphical user interface). Please refer directly to the repository and to the nice documentation available at [this website](http://muscleoptimizer.github.io/MuscleOptimizer/). +# Notes on upgrading to OpenSim 4.0 and backward compatibility + +The tool can be used with both OpenSim 3.3 and 4.0 without modifications. + +Please be aware that the results provided by the two versions are slightly different, as noticed when running our tests. + +To investigate further please consult the tests folder and scripts. + + # Contributors Special thanks to: From 8ad1355e9362545900444064db18e29828746dd1 Mon Sep 17 00:00:00 2001 From: Luca Modenese Date: Tue, 11 May 2021 12:17:06 +0100 Subject: [PATCH 5/8] FIX - handle ground and indices bug --- MATLAB_tool/MuscleParOptTool/getBodyJoint.m | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/MATLAB_tool/MuscleParOptTool/getBodyJoint.m b/MATLAB_tool/MuscleParOptTool/getBodyJoint.m index 0f5ecb6..678b73d 100644 --- a/MATLAB_tool/MuscleParOptTool/getBodyJoint.m +++ b/MATLAB_tool/MuscleParOptTool/getBodyJoint.m @@ -13,6 +13,13 @@ if nargin<3; debug_printout=0; end +% default +bodyJoint = []; + +if strcmp(aBodyName, 'ground') + return +end + % check if body is included in the model if osimModel.getBodySet().getIndex(aBodyName)<0 error(['getBodyJoint.m The specified body ', aBodyName,' is not included in the OpenSim model']) @@ -37,9 +44,9 @@ % get base frame name possible_body_name = char(body_of_frame.getName()); - + % if body with that name exist than the joint is that body's joint - if osimModel.getBodySet.getIndex(possible_body_name)>0 && strcmp(aBodyName, possible_body_name) + if osimModel.getBodySet.getIndex(possible_body_name)>=0 && strcmp(aBodyName, possible_body_name) % save the joints with the specified body as Child jointName(nj) = {char(cur_joint.getName())}; From 0c1e3725aa08a60a850826abbe5d25a7699215c9 Mon Sep 17 00:00:00 2001 From: Luca Modenese Date: Tue, 11 May 2021 12:18:04 +0100 Subject: [PATCH 6/8] CAUTION: handle muscle paths not directed proximally only --- .../MuscleParOptTool/private/getJointsSpannedByMuscle.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MATLAB_tool/MuscleParOptTool/private/getJointsSpannedByMuscle.m b/MATLAB_tool/MuscleParOptTool/private/getJointsSpannedByMuscle.m index b499cc5..3c52634 100644 --- a/MATLAB_tool/MuscleParOptTool/private/getJointsSpannedByMuscle.m +++ b/MATLAB_tool/MuscleParOptTool/private/getJointsSpannedByMuscle.m @@ -84,6 +84,7 @@ n_spanJointNoDof = 1; NoDofjointNameSet = {}; jointNameSet = {}; +disp([' spanned joints: ']) while ~strcmp(bodyName,ProximalBodyName) if getOpenSimVersion()<4.0 @@ -92,7 +93,14 @@ spannedJoint = getBodyJoint(osimModel, char(body.getName()), 0); end + % check if spannedJoint is empty (meaning it is "ground") + if isempty(spannedJoint) + warndlg(['The path of muscle ',OSMuscleName,' has reached ground without finding its origin, meaning that its path is not going proximal only. This case is not supported. Please check the logs and assess if the computations are acceptable for your case.']) + return + end + spannedJointName = char(spannedJoint.getName()); + disp([' * ', spannedJointName]); if strcmp(spannedJointName, spannedJointNameOld) body = spannedJoint.getParentBody(); From e477e601924ae4b46b17a60b080b05c5e6828369 Mon Sep 17 00:00:00 2001 From: Luca Modenese Date: Tue, 11 May 2021 12:18:28 +0100 Subject: [PATCH 7/8] upd based on Forum post (Ayman suggestion) --- .../MuscleParOptTool/getOpenSimVersion.m | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m b/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m index 1089a67..3c69ba6 100644 --- a/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m +++ b/MATLAB_tool/MuscleParOptTool/getOpenSimVersion.m @@ -3,31 +3,34 @@ % Author: Luca Modenese, 2021 % % email: l.modenese@imperial.ac.uk % % ----------------------------------------------------------------------- % -% This script returns the OpenSim version for which the environmental -% variable OPENSIM_HOME has been set. +% This script returns the OpenSim version % ----------------------------------------------------------------------- % function [osim_version_float, osim_version_string] = getOpenSimVersion() -% read env variable -osimpath = getenv('OPENSIM_HOME'); +import org.opensim.modeling.* -% let's assume it's the latest version in case there is no path variable -if isempty(osimpath) - osim_version_float = 4.1; - osim_version_string = '4.1'; +% read env variable +try + % method available only from 4.x + os_version = char(opensimCommonJNI.GetVersion()); + + % get the field separators, e.g. '- + sep_set = strfind(os_version, '-'); + + % use the last file separator to get the OpenSim installation folder name + version = os_version(1:sep_set(1)); + + % get the string for the opensim version + osim_version_string = strtrim(strrep(lower(version),'opensim', '')); + + % transform in float + osim_version_float = str2double(osim_version_string); + +catch + + % GetVersion is not available in earlier OpenSim versions + osim_version_float = 3.3; + osim_version_string = '3.3'; return end - -% get the file separators, e.g. '\' in 'C:\Program files\OpenSim 4.1' -sep_set = strfind(osimpath, filesep); - -% use the last file separator to get the OpenSim installation folder name -version = osimpath(sep_set(end)+1:end); - -% get the string for the opensim version -osim_version_string = strtrim(strrep(lower(version),'opensim', '')); - -% transform in float -osim_version_float = str2num(osim_version_string); - end \ No newline at end of file From 28e5560bb49a15ad7a73956170ae5a6ef6fad8ee Mon Sep 17 00:00:00 2001 From: Luca Modenese Date: Tue, 11 May 2021 12:24:06 +0100 Subject: [PATCH 8/8] add @darios93 to contributors --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f72abc2..9223a72 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ Special thanks to: * **Bryce Killen** from KU Leuven, Belgium, for updating the code for OpenSim 4.1! * **Emiliano Ravera** from Instituto de Investigación y Desarrollo en Bioingenieria y Bioinformática, IBB (CONICET-UNER), Argentina. +* **Dario Sciacca** from KU Leuven, Belgium, for his feedback on version 4.x. # References * Zajac, F.E. Muscle and tendon: properties, models, scaling, and application to biomechanics and motor control. Critical Reviews in Biomedical Engineering. 17: 359-411, 1989. [LINK](https://www.ncbi.nlm.nih.gov/pubmed/2676342)