forked from stanfordnmbl/opencap-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutilsPostProcessing.py
151 lines (120 loc) · 5.57 KB
/
utilsPostProcessing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# -*- coding: utf-8 -*-
"""
Created on Wed May 4 21:57:35 2022
@author: suhlr
"""
import utilsAuth
import opensim
import utils
import os
import glob
import numpy as np
import scipy.interpolate as interpolate
def downloadKinematics(session_id,folder=None,trialNames=None):
# Login to access opencap data from server.
utilsAuth.getToken()
if folder is None:
folder = os.getcwd()
os.makedirs(folder,exist_ok=True)
sessionJson = utils.getSessionJson(session_id)
# Get scaled model
neutral_id = utils.getNeutralTrialID(session_id)
utils.getMotionData(neutral_id,folder,simplePath=True)
utils.getModelAndMetadata(session_id,folder,simplePath =True)
# get session trial names
sessionTrialNames = [t['name'] for t in sessionJson['trials']]
# Check if trialnames they asked for are in sessionTrialNames
if trialNames != None:
[print(t + ' not in session trial names.') for t in trialNames if t not in sessionTrialNames]
loadedTrialNames = []
for trialDict in sessionJson['trials']:
if trialNames is not None and trialDict['name'] not in trialNames:
continue
trial_id = trialDict['id']
utils.getMotionData(trial_id,folder,simplePath=True)
loadedTrialNames.append(trialDict['name'])
return loadedTrialNames
def calcCenterOfMassTrajectory(folder,trialNames=None,coordinateFilterFreq=-1,COMFilterFreq=-1):
modelPath = glob.glob(os.path.join(folder,'OpenSimData','Model','*.osim'))[0]
kinematicPaths = glob.glob(os.path.join(folder,'OpenSimData','Kinematics','*.mot'))
modProc = opensim.ModelProcessor(os.path.abspath(modelPath))
modProc.append(opensim.ModOpRemoveMuscles())
model = modProc.process()
state = model.initSystem()
kinematicsCOM = []
for kinematicPath in kinematicPaths:
kinematicPath = os.path.abspath(kinematicPath)
kinematicRoot,fileName = os.path.split(kinematicPath)
trialName,_ = os.path.splitext(fileName)
if trialNames is not None:
if trialName not in trialNames:
continue
# get states from motion
statesTable = writeStatesFromMotion(kinematicPath,model,filtFreq=coordinateFilterFreq)
# Load states trajectory
tableProc = opensim.TableProcessor(statesTable)
statesTable = tableProc.processAndConvertToRadians(model)
statesTraj = opensim.StatesTrajectory.createFromStatesTable(model, statesTable)
# initialize output dict
nSteps = statesTraj.getSize()
inputDict = {'name':trialName}
inputDict['fields'] = ['time']
params = ['pos','vel','acc']
dirs = ['x','y','z']
[inputDict['fields'].append(p+'_'+d) for p in params for d in dirs]
inputDict['data'] = np.ndarray((nSteps,len(inputDict['fields'])))
# Compute COM position and velocity
for iTime in range(statesTraj.getSize()):
state = statesTraj[iTime]
model.realizeAcceleration(state)
inputDict['data'][iTime,0] = state.getTime()
inputDict['data'][iTime,1:4] = model.calcMassCenterPosition(state).to_numpy()
inputDict['data'][iTime,4:7] = model.calcMassCenterVelocity(state).to_numpy()
# dSpline/dt differences for accelerations because opensim calculation
# realizes to dynamics, so you need ground forces
for i in range(4,7,1):
spline = interpolate.InterpolatedUnivariateSpline(
inputDict['data'][:,0],
inputDict['data'][:,i], k=3)
inputDict['data'][:,i] = spline(
inputDict['data'][:,0])
splineD1 = spline.derivative(n=1)
inputDict['data'][:,i+3] = splineD1(
inputDict['data'][:,0])
# Filter the positions, velocities and accelerations
if COMFilterFreq >0:
inputDict['data'] = utils.lowpassFilter(inputDict['data'],
filtFreq=COMFilterFreq)
kinematicsCOM.append(inputDict)
return kinematicsCOM
def writeStatesFromMotion(filePath,model,filtFreq=-1):
kinematicPath = os.path.abspath(filePath)
kinematicRoot,fileName = os.path.split(kinematicPath)
trialName,_ = os.path.splitext(fileName)
# create states from motion - this is a hack to use Moco conveniences
track = opensim.MocoTrack()
track.setName(trialName)
modProc = opensim.ModelProcessor(model)
modProc.append(opensim.ModOpRemoveMuscles())
track.setModel(modProc)
table = opensim.TimeSeriesTable(kinematicPath)
time = table.getIndependentColumn()
t_initial = time[0]
t_final = time[-1]
tabProc = opensim.TableProcessor(table)
tabProc.append(opensim.TabOpLowPassFilter(filtFreq))
tabProc.append(opensim.TabOpUseAbsoluteStateNames())
track.setStatesReference(tabProc)
track.set_track_reference_position_derivatives(True)
track.initialize()
# move and rename file
oldFilePath = trialName + '_tracked_states.sto'
newFilePath = os.path.join(kinematicRoot,trialName + '_states.sto')
if filtFreq < 0:
table = opensim.TimeSeriesTable(newFilePath)
else:
table = opensim.TimeSeriesTable(oldFilePath)
table.trim(t_initial,t_final)
opensim.STOFileAdapter().write(table,newFilePath)
os.remove(oldFilePath)
return table