Page 1 of 1

Remove/delete wrap objects causes MATLAB to crash

Posted: Wed Apr 24, 2024 9:06 am
by oedemuth
Hi everyone,

I am trying to simplify a model in OpenSim 4.5 by combining and/or deleting some muscles. In the process I want to remove wrap objects that are still in the model but no longer used, as the muscles, which used to referenced them, got deleted. Rather than deleting them manually in a text editor from the osim file I was hoping to do this automatically in Matlab. However, when I call model.finalizeConnections() in order to write the file MATLAB simply crashes without any warning or error message. I am at a loss to why this is happening.

I assume that it is probably related to the way how I remove the wrap objects (i.e., wrapSet.remove(wrapObj); ; see below), which causes finalizeConnections to fail. But I am not sure how else to delete them from the model.

I have appended the relevant sections of my script below.

Code: Select all

modelFilePath = '/Users/itz/Documents/OpenSim/4.5-2024-01-10-3b63585/Models/';
modelFileName = 'TestModel';

import org.opensim.modeling.*;

% load model
model = Model(append(modelFilePath,modelFileName,'.osim'));

bodySet = model.getBodySet;
muscles = model.getMuscles;
numMusc = muscles.getSize;

% cylce through bodies
for i = 0:bodySet.getSize-1

    body = bodySet.get(i); % get body
    wrapSet = WrapObjectSet.safeDownCast(body.upd_WrapObjectSet()); % get wrap set

    wrapNames = strings(1,wrapSet.getSize); % preallocate variable for names
    
    % store all wrap object names to use later
    for j = 0:wrapSet.getSize-1
        wrapNames(j+1) = wrapSet.get(j).getName.string;
    end
    
    % cycle through all wrap objects
    for j = 0:wrapSet.getSize-1

        wrapLogic = false(numMusc,1); % preallocate logic array
        
        % get current wrap object (Can't use indices directly as previous 
        % wrap objects might have been removed, bumping it down)
        wrapObj = WrapObject.safeDownCast(wrapSet.get(wrapNames(j+1))); 
        
        % cycle through muscles and check if wrap object is referenced
        for k = 0:numMusc-1
                
            % get the muscle's geometry path
            geomPath = muscles.get(k).updGeometryPath(); 

            % get wrap objects from geometry path
            muscWrapSet = geomPath.getWrapSet;
            wrapObjectNames = strings(1,muscWrapSet.getSize);

            % cycle through muscle wrap objects and get their names
            for l = 0:muscWrapSet.getSize-1
                wrapObjectNames(l+1) = muscWrapSet.get(l).get_wrap_object.string;
            end

            % check if the body's current wrap object appears in the muscle's path wrap set
            wrapLogic(k+1) = any(strcmp(wrapObjectNames,wrapObj.getName.string));
        end

        if ~any(wrapLogic) % check if wrap object is used by any muscle
            % wrap object not used > remove it from wrapset
            disp(append('Remove ',wrapObj.getName.string,' from ',body.getName.string,' as it is no longer in use.', newline));

            wrapSet.remove(wrapObj); % removes it from wrap set
        end
    end
end

model.finalizeConnections(); % THIS WILL CRASH MATLAB!!
Many thanks for your help!

Best regards,
Oliver

Re: Remove/delete wrap objects causes MATLAB to crash

Posted: Mon May 13, 2024 12:30 pm
by ongcf
I was able to recreate the issue with a minimal example in MATLAB, though it does not crash in C++. I created a GitHub issue with more details: https://github.com/opensim-org/opensim-core/issues/3785

It will take a little more investigation to figure out a fix. I can't think of a good workaround using the OpenSim MATLAB API unfortunately. Since it is an XML file, you could use some MATLAB tools directly: https://www.mathworks.com/matlabcentral ... nal-format

Re: Remove/delete wrap objects causes MATLAB to crash

Posted: Fri May 24, 2024 4:21 pm
by ongcf
A couple of extra ideas:

1. One workaround in MATLAB is to use model.initSystem() instead of model.finalizeConnections(). Note that this will only work in scripting languages like MATLAB and not in C++. This is due to a bug, however, and it's possible that this could be patched such that you can't use remove() in a later version of OpenSim.
2. Since removing objects from a Set is problematic, one other workaround is to create a new model without any wrap objects and only add the wrap objects that you need (rather than removing them). This is more work, but might be more robust if the API changes down the road.