Cannot lock the joint using Python API with Opensim 4.5

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
POST REPLY
User avatar
Hongyuan Chen
Posts: 3
Joined: Wed Mar 20, 2024 6:37 pm

Cannot lock the joint using Python API with Opensim 4.5

Post by Hongyuan Chen » Thu Jun 27, 2024 6:58 am

I attempted to use the Python API to achieve the functionality of locking certain values in the Coordinates section within OpenSim. The overall code is shown below. In Python, I first perform IK on the first 50 data points to obtain the mean values, then I lock the trunk coordinates (such as 'r_x', 't_x', etc.) in the model before performing IK again. I input these fixed trunk values obtained from Python into the Coordinates section of OpenSim and toggle the lock value. When I check the output .mot file, the locked joint values remain unchanged.

However, when I perform setValue and setLocked operations on the corresponding joints in Python and then perform IK on the entire dataset, the resulting .mot file shows that the joint values are not locked as expected. I am unsure why this is happening.

Additionally, I noticed that for setting angle parameters, the range in OpenSim is [-360, 360], but when using setValue in Python, the range should be [-2pi, 2pi]. This is evident from the getValue output because when setValue is set to 170, the getValue actually shows a value of 2*pi, indicating that the range is capped at the maximum value.

Code: Select all

import opensim as osim
import pandas as pd
import numpy as np
from decimal import Decimal

# Load the model
model = osim.Model('C:\\Users\\User\\Documents\\OpenSim\\4.5-2024-01-10-3b63585\\Models\\MobL_ARMS_unimanual\\4.1 Model with Millard-Schutte Matched Curves\\MOBL_ARMS_module5_scaleIK_try2Scaled.osim')
model.initSystem()

# Create an InverseKinematicsTool instance
ik_tool = osim.InverseKinematicsTool()
ik_tool.setModel(model)

# Set the marker data file
marker_data_file = 'C:\\Users\\User\\Documents\\OpenSim\\4.5-2024-01-10-3b63585\\Models\\MobL_ARMS_unimanual\\4.1 Model with Millard-Schutte Matched Curves\\InputFiles\\InputFiles_module5_scaleIK\\Take 2024-06-20 09.32.47 PM_modified.trc'
ik_tool.setMarkerDataFileName(marker_data_file)

# Set the IK task file
ik_task_set = osim.IKTaskSet('C:\\Users\\User\\Documents\\OpenSim\\4.5-2024-01-10-3b63585\\Models\\MobL_ARMS_unimanual\\4.1 Model with Millard-Schutte Matched Curves\\InputFiles\\InputFiles_module5_scaleIK\\MoBL_ARMS_module5_IK_Setup_try.xml')
ik_tool.set_IKTaskSet(ik_task_set)

# Temporary output file
temp_output_file = 'C:\\Users\\User\\Documents\\OpenSim\\4.5-2024-01-10-3b63585\\Models\\MobL_ARMS_unimanual\\4.1 Model with Millard-Schutte Matched Curves\\InputFiles\\InputFiles_module5_scaleIK\\outputFile\\temp_ik_output.mot'
ik_tool.setOutputMotionFileName(temp_output_file)

# Run the IK analysis using the first 50 rows of marker data
ik_tool.setStartTime(0.0)  # Assuming time starts at 0, adjust according to actual data
ik_tool.setEndTime(49 * 0.005)  # Assuming a sampling rate of 200Hz (0.005s per frame), first 50 rows of data
ik_tool.run()

# Read the temporary output file to get joint angle data
ik_output = pd.read_csv(temp_output_file, sep='\t', skiprows=10)  # Adjust skiprows according to file format
ik_output_first_50 = ik_output.iloc[:50]

# Calculate the average values of specific joints
target_fixed_joint_names = ['r_x', 'r_y', 'r_z', 't_x', 't_y', 't_z']  # Joints to calculate average values
average_values = {}
for joint in target_fixed_joint_names:
    average_values[joint] = ik_output_first_50[joint].mean()

for joint in target_fixed_joint_names[0:3]:
    average_values[joint] = average_values[joint] * np.pi / 180

# Set the locked values of the joints
state = model.initSystem()
coordinate_set = model.getCoordinateSet()

for joint, avg_value in average_values.items():
    coordinate_set.get(joint).setLocked(state, False)
    coordinate_set.get(joint).setValue(state, avg_value)
    coordinate_set.get(joint).setLocked(state, True)
model.assemble(state)

# Read and check the joint values and locked status
for joint in target_fixed_joint_names:
    coord = coordinate_set.get(joint)
    value = coord.getValue(state)
    is_locked = coord.getLocked(state)
    print(f"{joint}: value = {value}, locked = {is_locked}")

# Set the full output file
full_output_file = 'C:\\Users\\User\\Documents\\OpenSim\\4.5-2024-01-10-3b63585\\Models\\MobL_ARMS_unimanual\\4.1 Model with Millard-Schutte Matched Curves\\InputFiles\\InputFiles_module5_scaleIK\\outputFile\\full_ik_output.mot'
ik_tool.setOutputMotionFileName(full_output_file)

# Run the IK analysis using all the marker data
ik_tool.setStartTime(0.0)  # Adjust according to actual data
ik_tool.setEndTime(float(250 * Decimal('0.005')))  # Set to the last time point of the marker data
ik_tool.run()

# Read the full output file and extract the joint angle data
ik_full_output = pd.read_csv(full_output_file, sep='\t', skiprows=10)  # Adjust skiprows according to file format
target_joint_names = ['elv_angle', 'shoulder_elv', 'shoulder_rot', 'elbow_flexion', 'pro_sup', 'deviation', 'flexion']
result_data = ik_full_output[target_joint_names]

# Save the results to a file (optional)
result_data.to_csv('C:\\Users\\User\\Documents\\OpenSim\\4.5-2024-01-10-3b63585\\Models\\MobL_ARMS_unimanual\\4.1 Model with Millard-Schutte Matched Curves\\InputFiles\\InputFiles_module5_scaleIK\\outputFile\\result_joint_angles.csv', index=False)

print(f"The average values of the specific joints have been locked and the complete IK results have been generated.")


Tags:

User avatar
Mohammadreza Rezaie
Posts: 365
Joined: Fri Nov 24, 2017 12:48 am

Re: Cannot lock the joint using Python API with Opensim 4.5

Post by Mohammadreza Rezaie » Thu Jun 27, 2024 8:48 am

Hi, if I understand your problem correctly, you are trying to lock certain coordinates and set them in a specific pose. setValue() and setLocked() are likely changing the State here which is not used in your InverseKinematicsTool(). set_default_value() and set_locked() could directly change the corresponding properties in your model.

Hope this helps.

User avatar
Hongyuan Chen
Posts: 3
Joined: Wed Mar 20, 2024 6:37 pm

Re: Cannot lock the joint using Python API with Opensim 4.5

Post by Hongyuan Chen » Thu Jun 27, 2024 7:25 pm

Thank you very much for your response. As a first-time user of the OpenSim API, I'm not yet clear on all the differences. I tried what you suggested, and it turns out that setValue only changes the current state, having no effect in the InverseKinematicsTool(). However, using set_default_value() and set_locked() perfectly solved my problem. I appreciate your help!

POST REPLY