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
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)
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)
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)
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)
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')
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 ()
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)