def perform_id(events_file, model_file, ik_file, grf_file, grf_xml_file,
               results_dir, opensimtools_dir, opensimplugin_dir, settings_dir):
    """Performs Inverse dynamics using Opensim."""

    # model

    model = opensim.Model(model_file)

    trial = os.path.basename(grf_file).strip('_GRF.mot')
    #    external_loads = opensim.ExternalLoads(model, grf_xml_file)
    #    external_loads.setExternalLoadsModelKinematicsFileName(ik_file)
    #    external_loads.setDataFileName(grf_file)
    #    external_loads.setLowpassCutoffFrequencyForLoadKinematics(6)
    #    external_loads.printToXML(settings_dir + name + 'ExternalLoads.xml')

    # create the setuo file
    model.initSystem()
    id_tool = opensim.InverseDynamicsTool()
    id_tool.setName(trial)
    id_tool.setModel(model)
    id_tool.setExternalLoadsFileName(grf_xml_file)
    id_tool.setResultsDir(results_dir)
    id_tool.setStartTime(events_file.InitialContactTime.iloc[0])
    id_tool.setEndTime(events_file.TimeLowestCOMX.iloc[1])
    id_tool.setCoordinatesFileName(ik_file)
    id_tool.setOutputGenForceFileName(trial + '_ID.sto')
    id_tool.setLowpassCutoffFrequency(6)
    id_xml = settings_dir + trial + '_Setup_ID.xml'
    id_tool.printToXML(id_xml)
    id_tool.run()
    id_file = results_dir + trial + '_ID.sto'
    return id_file
    def run_id_tool(self, trial):
        if self.prefix and not trial.stem.startswith(self.prefix):
            # skip file if user specified a prefix and prefix is not present in current file
            pass
        else:
            print(f'\t{trial.stem}')

            # initialize inverse dynamic tool from setup file
            model = osim.Model(self.model_input)
            id_tool = osim.InverseDynamicsTool(self.xml_input)
            id_tool.setModel(model)

            # get starting and ending time
            motion = osim.Storage(f'{trial.resolve()}')
            start = motion.getFirstTime()
            end = motion.getLastTime()

            # inverse dynamics tool
            id_tool.setStartTime(start)
            id_tool.setEndTime(end)
            id_tool.setCoordinatesFileName(f'{trial.resolve()}')

            if self.low_pass:
                id_tool.setLowpassCutoffFrequency(self.low_pass)

            # set name of input (mot) file and output (sto)
            filename = f'{trial.stem}'
            id_tool.setName(filename)
            id_tool.setOutputGenForceFileName('inverse_dynamic_output.sto')
            id_tool.setResultsDir(f'{self.sto_output}')

            # external loads file
            if self.forces_dir:
                loads = osim.ExternalLoads(self.xml_forces, True)
                if self.prefix:
                    loads.setDataFileName(
                        f"{Path(self.forces_dir, trial.stem.replace(f'{self.prefix}_', '')).resolve()}.sto"
                    )
                else:
                    loads.setDataFileName(
                        f"{Path(self.forces_dir, trial.stem).resolve()}.sto")
                loads.setExternalLoadsModelKinematicsFileName(
                    f'{trial.resolve()}')

                temp_xml = Path(f'{trial.stem}_temp.xml')
                loads.printToXML(f'{temp_xml.resolve()}')  # temporary xml file
                id_tool.setExternalLoadsFileName(f'{temp_xml}')
            else:
                id_tool.setExternalLoadsFileName(self.xml_forces)
            id_tool.printToXML(self.xml_output)
            id_tool.run()

            if self.forces_dir:
                temp_xml.unlink()  # delete temporary xml file
Пример #3
0
def setup_ID_xml(trial: str, model: str, directory: str, time_range: list,
                 cut_off_freq: np.float64):
    '''
	Rewrites the ID setup xml file for a new trial
	
	Inputs:	trial: trial name, e.g.,  "_12Mar_ss_12ms_01"
			model: model name, e.g., "AB08"
			directory: output directory name
			time_range: start and end times
			cuf_off_frequency: low pass cut-off frequency

	'''

    # Create an instance of the inverse dynamics tool
    ID_tool = osim.InverseDynamicsTool()

    # Set tool name
    ID_tool.setName(model)

    # Set the opensim model name
    ID_tool.setModelFileName(directory + "\\" + model + "\\" + model + ".osim")

    # Set excluded forces
    excluded_forces = osim.ArrayStr()
    excluded_forces.setitem(0, 'Muscles')
    ID_tool.setExcludedForces(excluded_forces)

    # Set low pass cut-off frequency, NOTE: Must be a double (np.float64)
    ID_tool.setLowpassCutoffFrequency(np.float64(cut_off_freq))

    # Set the input and results directory
    ID_tool.setResultsDir(directory + "\\" + model + "\\" + trial)
    ID_tool.setInputsDir(directory + "\\" + model + "\\" + trial)

    # Set the time range, NOTE: Must be a double (np.float64)
    ID_tool.setStartTime(np.float64(time_range[0]))
    ID_tool.setEndTime(np.float64(time_range[-1]))

    # Set the external loads file
    external_loads_file = directory + "\\" + model + "\\" + trial + "\\" + trial + 'ExternalLoads.xml'
    ID_tool.setExternalLoadsFileName(external_loads_file)

    # Set the coordinates file
    coordindate_file = directory + "\\" + model + "\\" + trial + "\\" + trial + 'IKResults.mot'
    ID_tool.setCoordinatesFileName(coordindate_file)

    # Set the output file
    output_file_name = trial + "IDResults.sto"
    ID_tool.setOutputGenForceFileName(output_file_name)
    ''' Write changes to an XML setup file '''

    xml_setup_path = directory + "\\" + model + "\\" + trial + "\\" + trial + "IDSetup.xml"
    ID_tool.printToXML(xml_setup_path)
Пример #4
0
def calc_net_generalized_forces(model, motion):
    model.initSystem()

    net_joint_moments = None
    import tempfile
    with tempfile.TemporaryDirectory() as tmpdirname:
        id_tool = osim.InverseDynamicsTool()
        modelID = osim.Model(model)
        id_tool.setModel(modelID)
        if type(motion) == osim.Storage:
            id_tool.setLowpassCutoffFrequency(6)
            storage = motion
        else:
            table = motion.exportToStatesTable()
            labels = list(table.getColumnLabels())
            import re
            for ilabel in range(len(labels)):
                labels[ilabel] = labels[ilabel].replace('/value', '')
                labels[ilabel] = re.sub('/jointset/(.*?)/', '', labels[ilabel])
            table.setColumnLabels(labels)
            storage = osim.convertTableToStorage(table)
            # TODO: There's a bug in converting column labels in
            # convertTableToStorage().
            stolabels = osim.ArrayStr()
            stolabels.append('time')
            for label in labels:
                stolabels.append(label)
            storage.setColumnLabels(stolabels)
        id_tool.setCoordinateValues(storage)
        # id_tool.setExternalLoadsFileName(extloads_fpath)
        excludedForces = osim.ArrayStr()
        excludedForces.append('ACTUATORS')
        id_tool.setExcludedForces(excludedForces)
        id_result = 'joint_moment_breakdown_residuals.sto'
        id_tool.setResultsDir(tmpdirname)
        id_tool.setOutputGenForceFileName(id_result)
        # TODO: Remove muscles from the model?
        id_tool.run()

        net_joint_moments = osim.TimeSeriesTable(
            os.path.join(tmpdirname, id_result))
    return net_joint_moments
Пример #5
0
PFF_MOT_file = PFF_MOT_files[0]

path, filename = os.path.split(MOT_file)
filename, ext = os.path.splitext(filename)

STO_file = filename + '.sto'  # Path to the output .MOT file that will be created and contain the IK results
XML_ID_file = dir_path + 'XML\\' + filename + '_ID.xml'  # Path to the ID XML file that will be created
XML_External_Load_ID_file = dir_path + 'XML\\' + filename + '_External_Load_ID.xml'  # Path to the External Load ID XML file that will be created

# Mot Data
motData = osim.Storage(MOT_file)
initial_time = motData.getFirstTime()
final_time = motData.getLastTime()

# ID tool
idTool = osim.InverseDynamicsTool(XML_generic_ID_path)
idTool.setResultsDir(dir_path + '\\STO\\')
idTool.setName(filename)
idTool.setModel(osimModel)
idTool.setCoordinatesFileName(MOT_file)
idTool.setStartTime(initial_time)
idTool.setEndTime(final_time)
idTool.setOutputGenForceFileName(STO_file)

# External Load File
externalLoads = osim.ExternalLoads(osimModel,
                                   XML_generic_External_Load_ID_path)
externalLoads.setName(filename)
externalLoads.setDataFileName(PFF_MOT_file)  # Set the PFF MOT filename
externalLoads.setLowpassCutoffFrequencyForLoadKinematics(4)
Пример #6
0
def plot_passive_joint_moments(model, coord_table,
                               coord_paths, muscle_paths=None):
    model.initSystem()
    # for muscle in model.getMuscleList():
    #     muscle.set_ignore_tendon_compliance(True)
    # model.initSystem()

    num_coords = len(coord_paths)

    if not muscle_paths:
        muscle_paths = list()
        for muscle in model.getMuscleList():
            muscle_paths.append(muscle.getAbsolutePathString())
    num_muscles = len(muscle_paths)

    labels = list(coord_table.getColumnLabels())
    import re
    for ilabel in range(len(labels)):
        labels[ilabel] = labels[ilabel].replace('/value', '')
        labels[ilabel] = re.sub('/jointset/(.*?)/', '', labels[ilabel])
    coord_table.setColumnLabels(labels)
    storage = osim.convertTableToStorage(coord_table)
    # TODO: There's a bug in converting column labels in
    # convertTableToStorage().
    stolabels = osim.ArrayStr()
    stolabels.append('time')
    for label in labels:
        stolabels.append(label)
    storage.setColumnLabels(stolabels)

    net_joint_moments = None
    import tempfile
    with tempfile.TemporaryDirectory() as tmpdirname:
        id_tool = osim.InverseDynamicsTool()
        modelID = osim.Model(model)
        id_tool.setModel(modelID)
        id_tool.setCoordinateValues(storage)
        id_tool.setLowpassCutoffFrequency(6)
        # id_tool.setExternalLoadsFileName(extloads_fpath)
        excludedForces = osim.ArrayStr()
        excludedForces.append('ACTUATORS')
        id_tool.setExcludedForces(excludedForces)
        id_result = 'joint_moment_breakdown_residuals.sto'
        id_tool.setResultsDir(tmpdirname)
        id_tool.setOutputGenForceFileName(id_result)
        # TODO: Remove muscles from the model?
        id_tool.run()

        net_joint_moments = osim.TimeSeriesTable(
            os.path.join(tmpdirname, id_result))

    time = coord_table.getIndependentColumn()

    states_traj = osim.StatesTrajectory.createFromStatesStorage(model, storage,
                                                                True, True,
                                                                True)

    # TODO for models without activation dynamics, we must prescribeControlsToModel().

    fig = pl.figure(figsize=(8.5, 11))
    tendon_forces = np.empty((len(time), num_muscles))
    for imusc, muscle_path in enumerate(muscle_paths):
        muscle = model.getComponent(muscle_path)
        for itime in range(len(time)):
            state = states_traj.get(itime)
            state.updU().setToZero()
            muscle.setActivation(state, 0.01)
            model.realizeVelocity(state)
            muscle.computeEquilibrium(state)
            model.realizeDynamics(state)
            tendon_forces[itime, imusc] = muscle.getTendonForce(state)

    for icoord, coord_path in enumerate(coord_paths):
        coord = model.getComponent(coord_path)

        label = os.path.split(coord_path)[-1] + '_moment'
        net_moment = toarray(net_joint_moments.getDependentColumn(label))

        moment_arms = np.empty((len(time), num_muscles))
        for imusc, muscle_path in enumerate(muscle_paths):
            muscle = model.getComponent(muscle_path)
            for itime in range(len(time)):
                state = states_traj.get(itime)
                moment_arms[itime, imusc] = \
                    muscle.computeMomentArm(state, coord)

        ax = fig.add_subplot(num_coords, 1, icoord + 1)
        # net_integ = np.trapz(np.abs(net_moment), x=time)
        sum_actuators_shown = np.zeros_like(time)
        for imusc, muscle_path in enumerate(muscle_paths):
            if np.any(moment_arms[:, imusc]) > 0.00001:
                this_moment = tendon_forces[:, imusc] * moment_arms[:, imusc]
                mom_integ = np.trapz(np.abs(this_moment), time)
                if mom_integ > 0.5:
                    ax.plot(time, this_moment, label=muscle_path)

                    sum_actuators_shown += this_moment

        ax.plot(time, sum_actuators_shown,
                label='sum actuators shown', color='gray', linewidth=2)

        time_net = np.array(net_joint_moments.getIndependentColumn())
        filter = (time_net > time[0]) & (time_net < time[-1])
        # ax.plot(time_net[filter], net_moment[filter],
        #         label='net', color='black', linewidth=2)

        ax.set_title(coord_path)
        ax.set_ylabel('moment (N-m)')
        ax.legend(frameon=False, bbox_to_anchor=(1, 1),
                  loc='upper left', ncol=2)
        ax.tick_params(axis='both')
        ax.set_xlim([time[0], time[-1]])
    ax.set_xlabel('time (% gait cycle)')

    fig.tight_layout()
    return fig
Пример #7
0
 
 # #Set output filename
 # ikTool[ii-startInd][tt].set_output_motion_file(dynamicFiles[tt].split('.')[0]+'_ik.mot')
 
 # #Print and run tool
 # ikTool[ii-startInd][tt].printToXML(dynamicFiles[tt].split('.')[0]+'_setupIK.xml')
 # ikTool[ii-startInd][tt].run()
 
 # #Rename marker errors file
 # shutil.move('_ik_marker_errors.sto',dynamicFiles[tt].split('.')[0]+'_ik_marker_errors.sto')
 
 # #Print confirmation
 # print('IK complete for '+dynamicFiles[tt].split('.')[0])
 
 #Initialise ID tool
 idTool[ii-startInd].append(osim.InverseDynamicsTool())
 
 #Set the model
 idTool[ii-startInd][tt].setModelFileName(subList[ii]+'_scaledModelAdjusted_sensors.osim')
 
 #Set times
 idTool[ii-startInd][tt].setStartTime(startTime)
 idTool[ii-startInd][tt].setEndTime(endTime)
 
 #Set external loads file
 idTool[ii-startInd][tt].setExternalLoadsFileName(dynamicFiles[tt].split('.')[0]+'_grf'+'.xml')
 
 #Set kinematics
 idTool[ii-startInd][tt].setCoordinatesFileName(dynamicFiles[tt].split('.')[0]+'_ik.mot')
 
 #Set lowpass filter frequency for kinematics (10Hz)
Пример #8
0
def inverseDynamics():
    import os
    import re
    import shutil
    import opensim as osim
    import directories

    allDir = list(directories.main(directories))
    parentDir = allDir[0]
    paramsDir = allDir[1]
    subID = allDir[4]
    subResultsDir = allDir[5]
    ikResultsDir = allDir[6]
    idResultsDir = allDir[7]

    # Clear Inverse Dynamics Folder
    if os.path.exists(idResultsDir):
        shutil.rmtree(idResultsDir, ignore_errors=True)
    if not os.path.exists(idResultsDir):
        os.mkdir(idResultsDir)

    # Input data files
    genericExtLoads = paramsDir + "/externalLoads.xml"
    motData = parentDir + "/data/osDemo/subject01_walk1_grf.mot"
    motFileName = "subject01_walk1_grf.mot"
    # saveDir = subResultsDir + "/" + subID + "motionFile.mot"
    ikFileName = "subject01_walk1_ik.mot"
    ikFile = ikResultsDir + "/" + ikFileName

    # Copy GRF File over to Current Directory
    shutil.copy(motData, idResultsDir + "/" + motFileName)

    # Load Inverse Kinematics Model
    aModel = osim.Model(subResultsDir + "/" + subID + ".osim")

    # initialize system
    aModel.initSystem()

    # Initialize External Loads File from Generic File
    extLoads = osim.ExternalLoads(aModel, genericExtLoads)

    # Initialize idTool
    idTool = osim.InverseDynamicsTool()
    idTool.setLowpassCutoffFrequency(6.0)
    idTool.setInputsDir(idResultsDir)
    idTool.setResultsDir(idResultsDir)
    idTool.setModel(aModel)
    idTool.setModelFileName(subResultsDir + "/" + subID + ".osim")
    # Get .mot data to determine time range
    motCoordsData = osim.Storage(ikFile)
    # Get initial and final time
    initial_time = motCoordsData.getFirstTime()
    final_time = motCoordsData.getLastTime()

    # Creat output ID
    idFileName = re.sub('ik.mot', 'id.sto', ikFileName)
    # Customize and save external loads ile
    extLoads.setName(motFileName)
    extLoads.setDataFileName(motData)
    extLoads.setExternalLoadsModelKinematicsFileName(ikFile)
    extLoads.printToXML(idResultsDir + "/" +
                        re.sub('ik.mot', 'extLoads.xml', ikFileName))

    # Setup idTool
    idTool.setName(motFileName)
    idTool.setCoordinatesFileName(ikFile)
    idTool.setStartTime(initial_time)
    idTool.setEndTime(final_time)
    # Must be relative to output directory, not full path!
    idTool.setOutputGenForceFileName(idFileName)
    idTool.setExternalLoadsFileName(
        idResultsDir + "/" + re.sub('ik.mot', 'extLoads.xml', ikFileName))
    # Can comment out if not needed in GUI
    idTool.printToXML(idResultsDir + "/" +
                      re.sub('ik.mot', 'setupID.xml', ikFileName))

    # Run idTool
    idTool.run()
    os.system('cls' if os.name == 'nt' else 'clear')
    return ()
Пример #9
0
    os.path.join(location_motion_data, save_ik_name))
ik_tool.run()

#Build external loads file and save to disk - this will be loaded in for IK and SO
external_loads = opensim.ExternalLoads(
    os.path.join(location_XMLs, external_loads_xml), True)
external_loads.setLowpassCutoffFrequencyForLoadKinematics(
    kinematic_filter_frequency)
external_loads.setDataFileName(
    os.path.join(location_motion_data, pedal_data_filenames))
external_loads.setName('both_pedal_forces')
external_loads.printToXML(
    os.path.join(location_motion_data, save_external_loads_name))

#perform ID
id_tool = opensim.InverseDynamicsTool()
id_tool.setModel(model)
# id_tool.setModelFileName()
id_tool.setCoordinatesFileName(os.path.join(location_motion_data,
                                            save_ik_name))
id_tool.setLowpassCutoffFrequency(kinematic_filter_frequency)
id_tool.setResultsDir(location_motion_data)
id_tool.setOutputGenForceFileName(save_id_name)
id_tool.setStartTime(id_start_time)
id_tool.setEndTime(id_end_time)

excludedForces = opensim.ArrayStr()
excludedForces.append('Muscles')
id_tool.setExcludedForces(excludedForces)
id_tool.setExternalLoadsFileName(
    os.path.join(location_motion_data, save_external_loads_name))