MocoTrack可以使用采集到的标记点数据作为追踪目标,MocoInverse使用预设的关节角度坐标运动值数据。两者都可以配置选择使用关节扭矩作为控制量,还是肌肉作为控制量,如果使用肌肉,就需要对肌肉进行相应的一些配置。
用到的几个数据文件进行说明:
subject_walk_scaled.osim:肌肉骨骼模型文件
grf_walk.xml:地反力的配置文件,内部包含了grf_walk.mot的数据文件
marker_trajectories.trc:运动学数据,标记点的数据,里面包含了各个mark标记点的名称
高级用法的例子中
subject_walk_scaled_FunctionBasedPathSet.xml:每一条肌肉长度路径多项式函数的系数参数
coordinates.sto:也可以使用关节坐标数据作为,追踪的目标的运动学数据
# 第一个例子,基本用法,没有使用肌肉,使用关节扭矩追踪采集到的标记点的轨迹
# 第二个例子,更高级的功能,配置肌肉的参数,跟踪关节坐标问题,使用coordinates.sto
import os
import opensim as osim
def torqueDrivenMarkerTracking():
# MocoTrack实例化
track = osim.MocoTrack()
# 配置对象名字
track.setName("torque_driven_marker_tracking")
# 使用ModelProcessor加载.osim肌肉骨骼模型
modelProcessor = osim.ModelProcessor("subject_walk_scaled.osim")
# 将地反力数据添加到模型中
modelProcessor.append(osim.ModOpAddExternalLoads("grf_walk.xml"))
# 移除模型ForceSet中的所有肌肉
modelProcessor.append(osim.ModOpRemoveMuscles())
# 将坐标执行器(CoordinateActuators)添加到模型的自由度上
# 骨盆坐标已有坐标执行器(CoordinateActuators),本操作忽略骨盆坐标
modelProcessor.append(osim.ModOpAddReserves(250.0, 1.0))
# 将配置完成的模型选项给到MocoTrack的实例中
track.setModel(modelProcessor)
# 将TRC文件中的采集的mark点作为参考轨迹,mark点数据6Hz低通滤波,原文件mm单位将转换成米
track.setMarkersReferenceFromTRC("marker_trajectories.trc")
# trc中包含手臂的手臂标记点,而模型中没有,设置以避免报错。
track.set_allow_unused_references(True)
# 增加全局标记点的权重到10,修改MocoMarkerTrackingCost参数
# global_tracking是那些点,可查看源代码
track.set_markers_global_tracking_weight(10)
# 增加骨标志位上的mark标记点的跟踪权重
markerWeights = osim.MocoWeightSet()
markerWeights.cloneAndAppend(osim.MocoWeight("R.ASIS", 20))
markerWeights.cloneAndAppend(osim.MocoWeight("L.ASIS", 20))
markerWeights.cloneAndAppend(osim.MocoWeight("R.PSIS", 20))
markerWeights.cloneAndAppend(osim.MocoWeight("L.PSIS", 20))
markerWeights.cloneAndAppend(osim.MocoWeight("R.Knee", 10))
markerWeights.cloneAndAppend(osim.MocoWeight("R.Ankle", 10))
markerWeights.cloneAndAppend(osim.MocoWeight("R.Heel", 10))
markerWeights.cloneAndAppend(osim.MocoWeight("R.MT5", 5))
markerWeights.cloneAndAppend(osim.MocoWeight("R.Toe", 2))
markerWeights.cloneAndAppend(osim.MocoWeight("L.Knee", 10))
markerWeights.cloneAndAppend(osim.MocoWeight("L.Ankle", 10))
markerWeights.cloneAndAppend(osim.MocoWeight("L.Heel", 10))
markerWeights.cloneAndAppend(osim.MocoWeight("L.MT5", 5))
markerWeights.cloneAndAppend(osim.MocoWeight("L.Toe", 2))
track.set_markers_weight_set(markerWeights)
# 设置起始时间,终点时间和时间间隔,单位为秒
track.set_initial_time(0.48)
track.set_final_time(1.61)
track.set_mesh_interval(0.02)
# 使用solveAndVisualize函数求解并显示仿真界面
solution = track.solveAndVisualize()
def muscleDrivenStateTracking():
# MocoTrack 实例化
track = osim.MocoTrack()
# 设置对象名称 muscle_driven_state_tracking
track.setName("muscle_driven_state_tracking")
# 构造一个ModelProcessor并加载模型
modelProcessor = osim.ModelProcessor("subject_walk_scaled.osim")
# 将地反力数据添加到模型中
modelProcessor.append(osim.ModOpAddExternalLoads("grf_walk.xml"))
# 关闭模型中所有肌肉的肌腱顺应性,替换成DeGrooteFregly2016Muscles的类型
modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
# 只有DeGrooteFregly2016Muscles类型的肌肉,才需要忽略 passiveFiberForce
modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
# 只有DeGrooteFregly2016Muscles,
modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))
# 对肌肉路径使用基于函数的表示,有助于加速收敛,如果使用原始的肌肉路径,模型中设置基于function的路径
# 给出关节坐标角度值的变化与肌肉长度的关系
# 定义输入关节坐标角度为自变量,以多元多项式函数求出因变量肌肉长度,一个自由度对应一个自变量
# 参考例子:examplePolynomialPathFitter.py
# 基于函数的肌肉路径添加到模型中
modelProcessor.append(osim.ModOpReplacePathsWithFunctionBasedPaths(
"subject_walk_scaled_FunctionBasedPathSet.xml"))
track.setModel(modelProcessor)
# 构造一个TableProcessor,并加载关节坐标数据,TableProcessors可以添加TableOperators来配置和更改
track.setStatesReference(osim.TableProcessor("coordinates.sto"))
# 默认情况下,运动学数据包含额外的列,Moco会报错。
# 在这里,告诉Moco允许(并忽略)这些额外的列。
track.set_allow_unused_references(True)
# 由于.sto文件中只有坐标位置数据,因此启用此设置可以使用位置的导数作为坐标速度数据。
track.set_track_reference_position_derivatives(True)
# 初始时间0.48s,终止时间1.61s,间隔为0.02s.
track.set_initial_time(0.48)
track.set_final_time(1.61)
track.set_mesh_interval(0.02)
# 使用initialize()函数,获取一个MocoStudy对象,然后对MocoStudy对象进行自定义。
study = track.initialize()
# 默认情况下,参考的MocoControlCost自动添加到每个MocoTrack问题中
problem = study.updProblem()
# 将出力大小设置为控制成本之一,权重系数为0.1,
effort = osim.MocoControlGoal.safeDownCast(problem.updGoal("control_effort"))
effort.setWeight(0.1)
# 将很大的权重设置给骨盆坐标执行器,它作为残余力或“上帝之手”,我们希望尽可能地减小这些力。
model = modelProcessor.process()
model.initSystem()
forceSet = model.getForceSet()
for i in range(forceSet.getSize()):
forcePath = forceSet.get(i).getAbsolutePathString()
if 'pelvis' in str(forcePath):
effort.setWeightForControl(forcePath, 10)
# 设置约束,初始时间点的肌肉激活,等于初始的肌肉兴奋值
problem.addGoal(osim.MocoInitialActivationGoal('initial_activation'))
# 更新求解器的误差tolerance
solver = osim.MocoCasADiSolver.safeDownCast(study.updSolver())
solver.set_optim_convergence_tolerance(1e-3)
solver.set_optim_constraint_tolerance(1e-4)
# 求解并可视化
solution = study.solve()
study.visualize(solution)
# 求解扭矩驱动的标记追踪问题
# 移除模型ForceSet中的所有肌肉,使用自由度的执行器用来替换
torqueDrivenMarkerTracking()
# 求解肌肉驱动的标记追踪问题
# 使用DeGrooteFregly2016Muscles肌肉,设置肌肉长度路径等参数
muscleDrivenStateTracking()