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
Ejemplo n.º 2
0
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)

# External Force
externalForce = externalLoads.get(0)
externalForce.setName('Force')
externalForce.setAppliedToBodyName('ground')
externalForce.setForceExpressedInBodyName('ground')
externalForce.setPointExpressedInBodyName('ground')
externalForce.setForceIdentifier('force_v')
externalForce.setPointIdentifier('force_p')
externalLoads.printToXML(
    XML_External_Load_ID_file
)  # Create a subject specific external loads xml and print it
def perform_jra(model_file,
                ik_file,
                grf_file,
                grf_xml,
                reserve_actuators,
                muscle_forces_file,
                results_dir,
                prefix=''):
    """Performs Static Optimization using OpenSim.

    Parameters
    ----------
    model_file: str
        OpenSim model (.osim)
    ik_file: str
        kinematics calculated from Inverse Kinematics
    grf_file: str
        the ground reaction forces
    grf_xml: str
        xml description containing how to apply the GRF forces
    reserve_actuators: str
        path to the reserve actuator .xml file
    muscle_forces_file: str
        path to the file containing the muscle forces from SO
    results_dir: str
        directory to store the results
    prefix: str
        prefix of the resultant joint reaction loads
    """
    # model
    model = opensim.Model(model_file)

    # prepare external forces xml file
    name = os.path.basename(grf_file)[:-8]
    external_loads = opensim.ExternalLoads(model, grf_xml)
    external_loads.setExternalLoadsModelKinematicsFileName(ik_file)
    external_loads.setDataFileName(grf_file)
    external_loads.setLowpassCutoffFrequencyForLoadKinematics(6)
    external_loads.printToXML(results_dir + name + '.xml')

    # TODO this may not be needed
    # add reserve actuators (must not be appended when performing JRA)
    # force_set = opensim.ForceSet(model, reserve_actuators)
    # force_set.setMemoryOwner(False)  # model will be the owner
    # for i in range(0, force_set.getSize()):
    #     model.updForceSet().append(force_set.get(i))
    #     # model.addForce(force_set.get(i))

    # construct joint reaction analysis
    motion = opensim.Storage(ik_file)
    joint_reaction = opensim.JointReaction(model)
    joint_reaction.setName('JointReaction')
    joint_reaction.setStartTime(motion.getFirstTime())
    joint_reaction.setEndTime(motion.getLastTime())
    joint_reaction.setForcesFileName(muscle_forces_file)
    model.addAnalysis(joint_reaction)
    model.initSystem()

    # analysis
    analysis = opensim.AnalyzeTool(model)
    analysis.setName(prefix + name)
    analysis.setModel(model)
    analysis.setModelFilename(model_file)
    analysis.setInitialTime(motion.getFirstTime())
    analysis.setFinalTime(motion.getLastTime())
    analysis.setLowpassCutoffFrequency(6)
    analysis.setCoordinatesFileName(ik_file)
    analysis.setExternalLoadsFileName(results_dir + name + '.xml')
    analysis.setLoadModelAndInput(True)
    analysis.setResultsDir(results_dir)
    analysis.run()
    jra_file = results_dir + name + '_JointReaction_ReactionLoads.sto'
    return jra_file
def perform_so(model_file, ik_file, grf_file, grf_xml, reserve_actuators,
               results_dir):
    """Performs Static Optimization using OpenSim.

    Parameters
    ----------
    model_file: str
        OpenSim model (.osim)
    ik_file: str
        kinematics calculated from Inverse Kinematics
    grf_file: str
        the ground reaction forces
    grf_xml: str
        xml description containing how to apply the GRF forces
    reserve_actuators: str
        path to the reserve actuator .xml file
    results_dir: str
        directory to store the results
    """
    # model
    model = opensim.Model(model_file)

    # prepare external forces xml file
    name = os.path.basename(grf_file)[:-8]
    external_loads = opensim.ExternalLoads(model, grf_xml)
    external_loads.setExternalLoadsModelKinematicsFileName(ik_file)
    external_loads.setDataFileName(grf_file)
    external_loads.setLowpassCutoffFrequencyForLoadKinematics(6)
    external_loads.printToXML(results_dir + name + '.xml')

    # add reserve actuators
    force_set = opensim.ForceSet(model, reserve_actuators)
    force_set.setMemoryOwner(False)  # model will be the owner
    for i in range(0, force_set.getSize()):
        model.updForceSet().append(force_set.get(i))

    # construct static optimization
    motion = opensim.Storage(ik_file)
    static_optimization = opensim.StaticOptimization()
    static_optimization.setStartTime(motion.getFirstTime())
    static_optimization.setEndTime(motion.getLastTime())
    static_optimization.setUseModelForceSet(True)
    static_optimization.setUseMusclePhysiology(True)
    static_optimization.setActivationExponent(2)
    static_optimization.setConvergenceCriterion(0.0001)
    static_optimization.setMaxIterations(100)
    model.addAnalysis(static_optimization)

    # analysis
    analysis = opensim.AnalyzeTool(model)
    analysis.setName(name)
    analysis.setModel(model)
    analysis.setInitialTime(motion.getFirstTime())
    analysis.setFinalTime(motion.getLastTime())
    analysis.setLowpassCutoffFrequency(6)
    analysis.setCoordinatesFileName(ik_file)
    analysis.setExternalLoadsFileName(results_dir + name + '.xml')
    analysis.setLoadModelAndInput(True)
    analysis.setResultsDir(results_dir)
    analysis.run()
    so_force_file = results_dir + name + '_StaticOptimization_force.sto'
    so_activations_file = results_dir + name + \
                          '_StaticOptimization_activation.sto'
    return (so_force_file, so_activations_file)
Ejemplo n.º 5
0
    def run_analyze_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}")

            # model
            model = osim.Model(self.model_input) if isinstance(self.model_input, str) is True else self.model_input
            model.initSystem()

            # get starting and ending time
            motion = osim.Storage(f"{trial.resolve()}")
            first_time = motion.getFirstTime()
            last_time = motion.getLastTime()

            # prepare external forces xml file
            if self.xml_forces:
                external_loads = osim.ExternalLoads(self.xml_forces, True)
                if self.prefix:
                    external_loads.setDataFileName(
                        f"{Path(self.ext_forces_dir, trial.stem.replace(f'{self.prefix}_', '')).resolve()}.sto"
                    )
                else:
                    external_loads.setDataFileName(
                        f"{Path(self.ext_forces_dir, trial.stem).resolve()}.sto"
                    )
                external_loads.setExternalLoadsModelKinematicsFileName(
                    f"{trial.resolve()}"
                )
                if self.low_pass:
                    external_loads.setLowpassCutoffFrequencyForLoadKinematics(
                        self.low_pass
                    )
                temp_xml = Path(f"{trial.stem}_temp.xml")
                external_loads.printToXML(f"{temp_xml.resolve()}")  # temporary xml file

            current_class = self.get_class_name()
            params = self.parse_analyze_set_xml(self.xml_input, node=current_class)
            solve_for_equilibrium = False
            if current_class == "StaticOptimization":
                analysis = osim.StaticOptimization(model)
                analysis.setUseModelForceSet(params["use_model_force_set"])
                analysis.setActivationExponent(params["activation_exponent"])
                analysis.setUseMusclePhysiology(params["use_muscle_physiology"])
                analysis.setConvergenceCriterion(
                    params["optimizer_convergence_criterion"]
                )
                analysis.setMaxIterations(int(params["optimizer_max_iterations"]))
            elif current_class == "MuscleAnalysis":
                solve_for_equilibrium = True
                analysis = osim.MuscleAnalysis(model)
                coord = osim.ArrayStr()
                for c in params["moment_arm_coordinate_list"]:
                    coord.append(c)
                analysis.setCoordinates(coord)

                mus = osim.ArrayStr()
                for m in params["muscle_list"]:
                    mus.append(m)
                analysis.setMuscles(mus)
                # analysis.setComputeMoments(params["compute_moments"])
            elif current_class == "JointReaction":
                # construct joint reaction analysis
                analysis = osim.JointReaction(model)
                if params["forces_file"] or self.forces_file:
                    force_file = self.forces_file if self.forces_file else params["forces_file"]
                    analysis.setForcesFileName(force_file)

                joint = osim.ArrayStr()
                for j in params["joint_names"]:
                    joint.append(j)
                analysis.setJointNames(joint)

                body = osim.ArrayStr()
                for b in params["apply_on_bodies"]:
                    body.append(b)
                analysis.setOnBody(body)

                frame = osim.ArrayStr()
                for f in params["express_in_frame"]:
                    frame.append(f)
                analysis.setInFrame(frame)
            else:
                raise ValueError("AnalyzeTool must be called from a child class")
            analysis.setModel(model)
            analysis.setName(current_class)
            analysis.setOn(params["on"])
            analysis.setStepInterval(int(params["step_interval"]))
            analysis.setInDegrees(params["in_degrees"])
            analysis.setStartTime(first_time)
            analysis.setEndTime(last_time)
            model.addAnalysis(analysis)

            if self.print_to_xml is True:
                analysis.printToXML(f"{self.xml_output}/{current_class}_analysis.xml")

            # analysis tool
            analyze_tool = osim.AnalyzeTool(model)
            analyze_tool.setName(trial.stem)
            analyze_tool.setModel(model)
            analyze_tool.setModelFilename(Path(model.toString()).stem)
            analyze_tool.setSolveForEquilibrium(solve_for_equilibrium)

            if self.xml_actuators:
                force_set = osim.ArrayStr()
                force_set.append(self.xml_actuators)
                analyze_tool.setForceSetFiles(force_set)
                analyze_tool.updateModelForces(model, self.xml_actuators)

            analyze_tool.setInitialTime(first_time)
            analyze_tool.setFinalTime(last_time)

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

            analyze_tool.setCoordinatesFileName(f"{trial.resolve()}")
            if self.xml_forces:
                analyze_tool.setExternalLoadsFileName(f"{temp_xml}")
            analyze_tool.setLoadModelAndInput(True)
            analyze_tool.setResultsDir(f"{self.sto_output}")

            analyze_tool.run()

            if self.xml_forces:
                temp_xml.unlink()  # delete temporary xml file

            if self.remove_empty_files:
                self._remove_empty_files(directory=self.sto_output)

            if self.contains:
                self._subset_output(directory=self.sto_output, contains=self.contains)
Ejemplo n.º 6
0
    def run_analyze_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}')

            # model
            model = osim.Model(self.model_input)
            model.initSystem()

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

            # prepare external forces xml file
            if self.xml_forces:
                external_loads = osim.ExternalLoads(model, self.xml_forces)
                if self.prefix:
                    external_loads.setDataFileName(
                        f"{Path(self.ext_forces_dir, trial.stem.replace(f'{self.prefix}_', '')).resolve()}.sto"
                    )
                else:
                    external_loads.setDataFileName(
                        f"{Path(self.ext_forces_dir, trial.stem).resolve()}.sto"
                    )
                external_loads.setExternalLoadsModelKinematicsFileName(f'{trial.resolve()}')
                if self.low_pass:
                    external_loads.setLowpassCutoffFrequencyForLoadKinematics(self.low_pass)
                temp_xml = Path(f'{trial.stem}_temp.xml')
                external_loads.printToXML(f'{temp_xml.resolve()}')  # temporary xml file

            current_class = self.get_class_name()
            params = self.parse_analyze_set_xml(self.xml_input, node=current_class)
            if current_class == 'StaticOptimization':
                analysis = osim.StaticOptimization(model)
                analysis.setUseModelForceSet(params['use_model_force_set'])
                analysis.setActivationExponent(params['activation_exponent'])
                analysis.setUseMusclePhysiology(params['use_muscle_physiology'])
                analysis.setConvergenceCriterion(params['optimizer_convergence_criterion'])
                analysis.setMaxIterations(int(params['optimizer_max_iterations']))
            elif current_class == 'MuscleAnalysis':
                analysis = osim.MuscleAnalysis(model)
                analysis.setComputeMoments(params['compute_moments'])
            elif current_class == 'JointReaction':
                # construct joint reaction analysis
                analysis = osim.JointReaction(model)
                # analysis.setForcesFileName(
                #     f"{Path(self.muscle_forces_dir, trial.stem).resolve()}_StaticOptimization_force.sto"
                # )

                joint = osim.ArrayStr()
                joint.append(params['joint_names'].replace(' ', ''))
                analysis.setJointNames(joint)

                body = osim.ArrayStr()
                body.append(params['apply_on_bodies'].replace(' ', ''))
                analysis.setOnBody(body)

                frame = osim.ArrayStr()
                frame.append(params['express_in_frame'].replace(' ', ''))
                analysis.setInFrame(frame)
            else:
                raise ValueError('AnalyzeTool must be called from a child class')
            analysis.setModel(model)
            analysis.setName(current_class)
            analysis.setOn(params['on'])
            analysis.setStepInterval(int(params['step_interval']))
            analysis.setInDegrees(params['in_degrees'])
            analysis.setStartTime(first_time)
            analysis.setEndTime(last_time)
            model.addAnalysis(analysis)

            # analysis tool
            analyze_tool = osim.AnalyzeTool(model)
            analyze_tool.setName(trial.stem)
            analyze_tool.setModel(model)
            analyze_tool.setModelFilename(Path(self.model_input).stem)

            if self.xml_actuators:
                force_set = osim.ArrayStr()
                force_set.append(self.xml_actuators)
                analyze_tool.setForceSetFiles(force_set)
                analyze_tool.updateModelForces(model, self.xml_actuators)

            analyze_tool.setInitialTime(first_time)
            analyze_tool.setFinalTime(last_time)

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

            analyze_tool.setCoordinatesFileName(f'{trial.resolve()}')
            analyze_tool.setExternalLoadsFileName(f'{temp_xml}')
            analyze_tool.setLoadModelAndInput(True)
            analyze_tool.setResultsDir(f'{self.sto_output}')

            analyze_tool.run()

            if self.xml_forces:
                temp_xml.unlink()  # delete temporary xml file

            if self.remove_empty_files:
                self._remove_empty_files(directory=self.sto_output)
Ejemplo n.º 7
0
def setup_load_xml(trial: str, model: str, directory: str,
                   cut_off_freq: np.float64):
    '''
	Takes the external loads xml file specified by load_filename, and sets the .mot files to those specified
	by trial, and writes to a new file of the two strings combined, i.e., "Walk1ExternalLoads.xml"

	Inputs: load_filename: full filename for the template external load setup xml file
			trial: trial name, e.g.,  "_12Mar_ss_12ms_01"
			model: model name, e.g., "AB08"
			directory: output directory name
			cuf_off_frequency: low pass cut-off frequency

	'''

    # Create external loads object
    external_loads = osim.ExternalLoads()

    # Set name
    external_loads.setName(model)

    # Set motion file
    mot_string = directory + "\\" + model + "\\" + trial + "\\" + trial + ".mot"
    external_loads.setDataFileName(mot_string)

    # Set cut-off frequency, NOTE: Must be a double (np.float64)
    external_loads.setLowpassCutoffFrequencyForLoadKinematics(
        np.float64(cut_off_freq))
    ''' Add external forces '''

    # Left side
    external_force_left = osim.ExternalForce()

    external_force_left.setName("left")

    external_force_left.set_applied_to_body("calcn_l")
    external_force_left.set_force_expressed_in_body("ground")
    external_force_left.set_point_expressed_in_body("ground")

    external_force_left.set_force_identifier("1_ground_force_v")
    external_force_left.set_point_identifier("1_ground_force_p")
    external_force_left.set_torque_identifier("1_ground_torque_")

    # Adopt and append is causing code to stop after printing to XML. Unsure why.
    external_loads.cloneAndAppend(external_force_left)

    # Right side
    external_force_right = osim.ExternalForce()

    external_force_right.setName("right")

    external_force_right.set_applied_to_body("calcn_r")
    external_force_right.set_force_expressed_in_body("ground")
    external_force_right.set_point_expressed_in_body("ground")

    external_force_right.set_force_identifier("ground_force_v")
    external_force_right.set_point_identifier("ground_force_p")
    external_force_right.set_torque_identifier("ground_torque_")

    external_loads.cloneAndAppend(external_force_right)
    ''' Write new file '''

    new_filename = directory + "\\" + model + "\\" + trial + "\\" + trial + "ExternalLoads.xml"

    external_loads.printToXML(new_filename)
Ejemplo n.º 8
0
 for qq in range(nrow):
     row = osim.ArrayDouble()
     for jj in range(ncol):
         row.append(forceData[qq,jj])
     #Add data to storage
     forcesStorage.append(tf[qq], row)
     
 #Set name for storage object
 forcesStorage.setName(dynamicFiles[tt].split('.')[0]+'_grf')
 
 #Print to file
 forcesStorage.printResult(forcesStorage, dynamicFiles[tt].split('.')[0]+'_grf',
                           os.getcwd(), 1/fs, '.mot')
 
 #Create external forces .xml file
 forceXML = osim.ExternalLoads()
 
 #Create and append the right GRF external force
 rightGRF = osim.ExternalForce()
 rightGRF.setName('RightGRF')
 rightGRF.setAppliedToBodyName('calcn_r')
 rightGRF.setForceExpressedInBodyName('ground')
 rightGRF.setPointExpressedInBodyName('ground')
 rightGRF.setForceIdentifier('ground_force_r_v')
 rightGRF.setPointIdentifier('ground_force_r_p')
 rightGRF.setTorqueIdentifier('ground_torque_r_')
 forceXML.cloneAndAppend(rightGRF)
 
 #Create and append the left GRF external force
 leftGRF = osim.ExternalForce()
 leftGRF.setName('LeftGRF')
Ejemplo n.º 9
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 ()
Ejemplo n.º 10
0
model.printToXML(os.path.join(location_motion_data, scaled_model_filename))

#Perform IK
ik_tool = opensim.InverseKinematicsTool(os.path.join(location_XMLs, ik_file))
ik_tool.setModel(model)
ik_tool.setName(marker_data_filenames)
ik_tool.setMarkerDataFileName(
    os.path.join(location_motion_data, marker_data_filenames))
ik_tool.setStartTime(ik_start_time)
ik_tool.setEndTime(ik_end_time)
ik_tool.setOutputMotionFileName(
    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)