Page 1 of 1

Clone and move wrap object in Matlab API

Posted: Fri Dec 03, 2021 7:22 am
by delyle
I have models with muscles and wrap objects on the right side, and I want to write a MATLAB script to mirror them onto the left side.

I've managed to mirror the muscles but I can't figure out how to do this for the wrap objects.

Using the Arm26 model as an example, let's say I wanted to clone the TRIlonghh WrapEllipsoid attached to the r_humerus body and attach it to the r_ulna_radius_hand body at an arbitrary location.

I can access the Wrap Set for r_humerus with the following script, but then I can't seem to get individual wrap objects. Since wrapSet is an Abstract Property I probably need to safeDownCast, but to what derived class?

Code: Select all

clear
import org.opensim.modeling.*
model = Model('arm26.osim');
bodySet = model.getBodySet();
body = bodySet.getPropertyByIndex(0).getValueAsObject(1);
bodyName = cell2mat(body.getName.string);
wrapSet = body.updPropertyByName('WrapObjectSet');
Unfortunately I'm restricted to using 3.3 for these models. I'm using Matlab 2020b in Windows 10.

Thanks for your help!

Re: Clone and move wrap object in Matlab API

Posted: Tue Dec 07, 2021 5:26 am
by delyle
I've managed to duplicate the wrap object of interest and attach it to a new body.

It seems the key is to safeDownCast the wrap object from the WrapEllipsoid derived class.

But I can't figure out how to move the wrap object in the script! I can access the translation and transform properties, but I can't update them. Help?

Code: Select all

clear; clc
import org.opensim.modeling.*
model = Model('arm26.osim');
model.setName('arm26_newWrap')

% get the r_humerus Body
bodySet = model.getBodySet();
r_humerus = Body().safeDownCast(bodySet.getPropertyByIndex(0).getValueAsObject(1)); % gets the 

% get the TRIlonghh wrap object
wrapSet = r_humerus.updPropertyByName('WrapObjectSet'); % possibly getWrapObjectSet() instead?
wrapSetObj = wrapSet.getValueAsObject(0);
wrapSetArray = wrapSetObj.updPropertyByIndex(0);
wrapObj = WrapEllipsoid().safeDownCast(wrapSetArray.updValueAsObject(0)); % gets first wrap object
wrapObj2 = wrapObj.clone();% duplicate wrap object
nameOld = wrapObj.getName.string;
nameNew = ['new',nameOld{1}(1:end)];
wrapObj2.setName(nameNew); % give it a new name

% get translation and transform. How to edit?
T = wrapObj2.updPropertyByName('translation');
transform = wrapObj2.getTransform();

% add new wrap object to the r_ulna_radius_hand Body.
r_ulna_radius_hand = Body().safeDownCast(bodySet.updPropertyByIndex(0).updValueAsObject(2));
r_ulna_radius_hand.addWrapObject(wrapObj2);

model.initSystem(); % check model consistency

model.print('arm26_newWrap.osim');

Re: Clone and move wrap object in Matlab API

Posted: Tue Dec 07, 2021 11:50 pm
by akoussou
Hi Delyle,

Below is a snippet of a code I use on MatLab, with OpenSim 4.1, to modify translation and rotation of a wrapping object. I hope it will help you and you will find a way to adapt it to OpenSim 3.3.

Code: Select all

% body of interest
cur_body = osimModel.getBodySet().get(aSegmentName);

% current wrapping surfaces
curr_wrap = cur_body.getWrapObject(cur_body.getWrapObjectSet.get(n_wrap_surfaces).getName);
   
% current wrapping translation
wrapSurfLocVec3 =  curr_wrap.get_translation();
wrapSurfLocCoords = [wrapSurfLocVec3.get(0),wrapSurfLocVec3.get(1),wrapSurfLocVec3.get(2)];

%I do some modifications to wrapSurfLocCoords (not in this snippet). Then, I can compute new wrap surfaces translation. 

% compute/define new wrap surfaces translation
new_wrapSurfLocCoords =[X X X];

% setting the wrap surfaces translation as Vec3 
new_wrapSurfLocCoords_v3 = Vec3(new_wrapSurfLocCoords(1), new_wrapSurfLocCoords(2), new_wrapSurfLocCoords(3));

curr_wrap.set_translation(new_wrapSurfLocCoords_v3);
    
% current wrapping rotation
wrapSurfRotVec3 =  curr_wrap.get_xyz_body_rotation();
wrapSurfRotCoords = [wrapSurfRotVec3.get(0),wrapSurfRotVec3.get(1),wrapSurfRotVec3.get(2)];

%I do some modifications to wrapSurfRotCoords (not in this snippet). Then, I can compute new wrap surfaces rotation. 

% compute/define new wrap surfaces orientation
new_Orientation =[X X X];
new_wrapSurfRot = Vec3(new_Orientation(1), new_Orientation(2), new_Orientation(3));
    
% setting the wrap surfaces rotation as Vec3
curr_wrap.set_xyz_body_rotation(new_wrapSurfRot);

Regards

Re: Clone and move wrap object in Matlab API

Posted: Wed Dec 08, 2021 4:37 am
by delyle
Thanks for looking into this, Axel! That code looks great for v4.

OpenSim 4 added some functionality that the v3.3 API doesn't seem to have.

There is no set_translation or set_xyz_body_rotation function in the WrapObject class for v3.3. I can get the translation and rotation via getTransform.T and getTransform.R respectively. But there doesn't seem to be a way to set or update the transform of the wrap object.

Re: Clone and move wrap object in Matlab API

Posted: Wed Dec 08, 2021 6:26 pm
by aymanh
Hi Delyle,

Not sure the complete list of features that were available to version 3.3 (few years ago) but there's always a PropertyHelper class that would allow you to exploit the "Properties" interface to set/get values on AbstractProperty if you know the concrete type. This mechanism has always been used by the GUI to make changes/edits to models. If you look up the documentation of PropertyHelper in version 3.3 you maybe able to do what you want, alternatively you can upgrade to version 4.0+

Hope this helps,
-Ayman

Re: Clone and move wrap object in Matlab API

Posted: Fri Dec 10, 2021 8:30 am
by delyle
Brilliant, that worked! Thanks Ayman.