예제 #1
0
def solveMocoInverse():

    # Construct the MocoInverse tool.
    inverse = osim.MocoInverse()

    # Construct a ModelProcessor and set it on the tool. The default
    # muscles in the model are replaced with optimization-friendly
    # DeGrooteFregly2016Muscles, and adjustments are made to the default muscle
    # parameters.
    modelProcessor = osim.ModelProcessor('subject_walk_armless.osim')
    modelProcessor.append(osim.ModOpAddExternalLoads('grf_walk.xml'))
    modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
    modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
    # Only valid for DeGrooteFregly2016Muscles.
    modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
    # Only valid for DeGrooteFregly2016Muscles.
    modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))
    modelProcessor.append(osim.ModOpAddReserves(1.0))
    inverse.setModel(modelProcessor)

    # Construct a TableProcessor of the coordinate data and pass it to the
    # inverse tool. TableProcessors can be used in the same way as
    # ModelProcessors by appending TableOperators to modify the base table.
    # A TableProcessor with no operators, as we have here, simply returns the
    # base table.
    inverse.setKinematics(osim.TableProcessor('coordinates.sto'))

    # Initial time, final time, and mesh interval.
    inverse.set_initial_time(0.81)
    inverse.set_final_time(1.79)
    inverse.set_mesh_interval(0.02)

    # By default, Moco gives an error if the kinematics contains extra columns.
    # Here, we tell Moco to allow (and ignore) those extra columns.
    inverse.set_kinematics_allow_extra_columns(True)

    # Solve the problem and write the solution to a Storage file.
    solution = inverse.solve()
    solution.getMocoSolution().write(
        'example3DWalking_MocoInverse_solution.sto')

    # Generate a PDF with plots for the solution trajectory.
    model = modelProcessor.process()
    report = osim.report.Report(model,
                                'example3DWalking_MocoInverse_solution.sto',
                                bilateral=True)
    # The PDF is saved to the working directory.
    report.generate()
def getWalkingModel():

    # Load the 19 DOF, 18 muscle model from file.
    model = osim.Model('subject_walk_armless_18musc.osim');

    # Add actuators representing the pelvis residual actuators and lumbar
    # torques. These actuators are only as strong as they need to be for the
    # problem to converge.
    addCoordinateActuator(model, 'pelvis_tx', 60)
    addCoordinateActuator(model, 'pelvis_ty', 300)
    addCoordinateActuator(model, 'pelvis_tz', 35)
    addCoordinateActuator(model, 'pelvis_tilt', 60)
    addCoordinateActuator(model, 'pelvis_list', 35)
    addCoordinateActuator(model, 'pelvis_rotation', 25)
    addCoordinateActuator(model, 'lumbar_bending', 40)
    addCoordinateActuator(model, 'lumbar_extension', 40)
    addCoordinateActuator(model, 'lumbar_rotation', 25)

    # We need additional actuators for hip rotation and hip adduction since the
    # existing muscle act primarily in the sagittal plane.
    addCoordinateActuator(model, 'hip_rotation_r', 100)
    addCoordinateActuator(model, 'hip_rotation_l', 100)
    addCoordinateActuator(model, 'hip_adduction_r', 100)
    addCoordinateActuator(model, 'hip_adduction_l', 100)

    # Create a ModelProcessor to make additional modifications to the model.
    modelProcessor = osim.ModelProcessor(model)
    # Weld the subtalar and toe joints.
    jointsToWeld = osim.StdVectorString()
    jointsToWeld.append('subtalar_r')
    jointsToWeld.append('subtalar_l')
    jointsToWeld.append('mtp_r')
    jointsToWeld.append('mtp_l')
    modelProcessor.append(osim.ModOpReplaceJointsWithWelds(jointsToWeld))
    # Apply the ground reaction forces to the model.
    modelProcessor.append(osim.ModOpAddExternalLoads('external_loads.xml'))
    # Update the muscles: ignore tendon compliance and passive forces, replace
    # muscle types with the DeGrooteFregly2016Muscle type, and scale the width
    # of the active force length curve.
    modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
    modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
    modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
    modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))
    # Add a set a weak reserves to the sagittal-plane joints in the model.
    modelProcessor.append(osim.ModOpAddReserves(1.0))

    return modelProcessor
예제 #3
0
def solveMocoInverseMuscle():

    #Construct the MocoInverse tool.
    inverse = osim.MocoInverse()
    inverse.setName('inverseMuscleTracking')

    #Construct a ModelProcessor and set it on the tool.
    #Currently the coordinate actuators for the pelvis, along with the reserve
    #actuators are fairly generally set, and not weighted at all in cost function.
    #These actuators could be more carefully considered to generate an appropriate
    #muscle driven simulation. For example, if they max and min control to 1 - the 
    #pelvis actuators may not produce enough torque.
    modelProcessor = osim.ModelProcessor('scaledModelMuscle.osim')
    modelProcessor.append(osim.ModOpAddExternalLoads('Jog05_grf.xml'))
    modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
    modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
    # Only valid for DeGrooteFregly2016Muscles.
    # modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
    # Only valid for DeGrooteFregly2016Muscles.
    modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))
    modelProcessor.append(osim.ModOpAddReserves(2))
    inverse.setModel(modelProcessor)
    
    #Construct a TableProcessor of the coordinate data and pass it to the
    #inverse tool. TableProcessors can be used in the same way as
    #ModelProcessors by appending TableOperators to modify the base table.
    #A TableProcessor with no operators, as we have here, simply returns the
    #base table.
    inverse.setKinematics(osim.TableProcessor('ikResults_states.sto'))

    #Initial time, final time, and mesh interval.
    inverse.set_initial_time(osim.Storage('ikResults_states.sto').getFirstTime())
    inverse.set_final_time(osim.Storage('ikResults_states.sto').getLastTime())
    inverse.set_mesh_interval(0.02)

    # By default, Moco gives an error if the kinematics contains extra columns.
    # Here, we tell Moco to allow (and ignore) those extra columns.
    inverse.set_kinematics_allow_extra_columns(True)

    # Solve the problem and write the solution to a Storage file.
    solution = inverse.solve()
    
    #Return the solution as an object that we can use
    return solution
예제 #4
0
def muscleDrivenStateTracking():

    # Create and name an instance of the MocoTrack tool.
    track = osim.MocoTrack()
    track.setName("muscle_driven_state_tracking")

    # Construct a ModelProcessor and set it on the tool. The default
    # muscles in the model are replaced with optimization-friendly
    # DeGrooteFregly2016Muscles, and adjustments are made to the default muscle
    # parameters.
    modelProcessor = osim.ModelProcessor("subject_walk_armless.osim")
    modelProcessor.append(osim.ModOpAddExternalLoads("grf_walk.xml"))
    modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
    modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
    # Only valid for DeGrooteFregly2016Muscles.
    modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
    # Only valid for DeGrooteFregly2016Muscles.
    modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))
    track.setModel(modelProcessor)

    # Construct a TableProcessor of the coordinate data and pass it to the
    # tracking tool. TableProcessors can be used in the same way as
    # ModelProcessors by appending TableOperators to modify the base table.
    # A TableProcessor with no operators, as we have here, simply returns the
    # base table.
    track.setStatesReference(osim.TableProcessor("coordinates.sto"))
    track.set_states_global_tracking_weight(10)

    # This setting allows extra data columns contained in the states
    # reference that don't correspond to model coordinates.
    track.set_allow_unused_references(True)

    # Since there is only coordinate position data in the states references,
    # this setting is enabled to fill in the missing coordinate speed data using
    # the derivative of splined position data.
    track.set_track_reference_position_derivatives(True)

    # Initial time, final time, and mesh interval.
    track.set_initial_time(0.81)
    track.set_final_time(1.65)
    track.set_mesh_interval(0.08)

    # Instead of calling solve(), call initialize() to receive a pre-configured
    # MocoStudy object based on the settings above. Use this to customize the
    # problem beyond the MocoTrack interface.
    study = track.initialize()

    # Get a reference to the MocoControlCost that is added to every MocoTrack
    # problem by default.
    problem = study.updProblem()
    effort = osim.MocoControlGoal.safeDownCast(
        problem.updGoal("control_effort"))

    # Put a large weight on the pelvis CoordinateActuators, which act as the
    # residual, or 'hand-of-god', forces which we would like to keep as small
    # as possible.
    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)

    # Solve and visualize.
    solution = study.solve()
    study.visualize(solution)
예제 #5
0
#from the model object here (says the model has no subcomponents?). A workaround
#is to process print out the model and call it to the processor via its filename,
#and then get a variable to call the processed model.

#Print out the edited model
osimModel.printToXML('simModel.osim')

#Set up a model processor to configure model
modelProcessor = osim.ModelProcessor('simModel.osim')

#Convert model muscles to DeGrooteFregly type
modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())

#Append settings for muscle models
#Set to ignore tendon compliance
modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
#Set to ignore conservative passive fiber forces
modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
#Set the fiber damping low to limit non-conservative passive forces
#This may also serve to limit the negative muscle forces that can happen
modelProcessor.append(osim.ModOpFiberDampingDGF(1e-02))

####### this parameter could be a factor in the different results coming up
####### along with te active force width (if that didn't change). default is 0.1
####### so this shift may be quite large (the original 1e-05 that is)?

#Scale active force width of muscles
modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))

##### don't think active force width was altered either in original simulations...
예제 #6
0
    def create_model_processor(self, root_dir, for_inverse=False, config=None):

        flags = []
        if config:
            flags = config.flags

        model = osim.Model(os.path.join(root_dir,
                'resources/Rajagopal2016/'
                'subject_walk_armless_contact_bounded_80musc.osim'))

        # for imusc in range(model.getMuscles().getSize()):
        #     musc = model.updMuscles().get(imusc)
        #     musc = osim.Millard2012EquilibriumMuscle.safeDownCast(musc)
        #     musc.upd_FiberForceLengthCurve().set_strain_at_one_norm_force(
        #         3.0)

        # for muscle in ['vasmed', 'vasint', 'vaslat', 'recfem', 'semimem',
        #                'semiten']:
        #     for side in ['_l', '_r']:
        #         musc = model.updMuscles().get('%s%s' % (muscle, side))
        #         musc = osim.Millard2012EquilibriumMuscle.safeDownCast(musc)
        #         musc.upd_FiberForceLengthCurve().set_strain_at_one_norm_force(
        #             3.5)

        if for_inverse:
            forceSet = model.getForceSet()
            numContacts = 0
            for i in np.arange(forceSet.getSize()):
                forceName = forceSet.get(int(i)).getName()
                if 'contact' in forceName: numContacts += 1

            print('Removing contact force elements from model...')
            contactsRemoved = 0
            while contactsRemoved < numContacts:
                for i in np.arange(forceSet.getSize()):
                    forceName = forceSet.get(int(i)).getName()
                    if 'contact' in forceName: 
                        print('  --> removed', forceSet.get(int(i)).getName())
                        forceSet.remove(int(i))
                        contactsRemoved += 1
                        break


        stiffnessModifier = 0.8
        print(f'Modifying contact element stiffnesses by factor {stiffnessModifier}...')
        for actu in model.getComponentsList():
            if actu.getConcreteClassName() == 'SmoothSphereHalfSpaceForce':
                force = osim.SmoothSphereHalfSpaceForce.safeDownCast(actu)
                force.set_stiffness(stiffnessModifier * force.get_stiffness())
                print(f'  --> modified contact element {force.getName()}')

        def add_reserve(model, coord, optimal_force, max_control):
            actu = osim.ActivationCoordinateActuator()
            actu.set_coordinate(coord)
            if coord.startswith('pelvis'):
                prefix = 'residual_'
            elif coord.startswith('lumbar'):
                prefix = 'torque_'
            else:
                prefix = 'reserve_'
            actu.setName(prefix + coord)
            actu.setOptimalForce(optimal_force)
            actu.setMinControl(-max_control)
            actu.setMaxControl(max_control)
            model.addForce(actu)
        add_reserve(model, 'lumbar_extension', 1, 50)
        add_reserve(model, 'lumbar_bending', 1, 50)
        add_reserve(model, 'lumbar_rotation', 1, 50)

        reserves_max = 250 if for_inverse else 1
        add_reserve(model, 'pelvis_tilt', 1, reserves_max)
        add_reserve(model, 'pelvis_list', 1, reserves_max)
        add_reserve(model, 'pelvis_rotation', 1, reserves_max)
        add_reserve(model, 'pelvis_tx', 1, reserves_max)
        add_reserve(model, 'pelvis_ty', 1, reserves_max)
        add_reserve(model, 'pelvis_tz', 1, reserves_max)

        optimal_force = 0.1
        add_reserve(model, 'hip_flexion_r', optimal_force, reserves_max)
        add_reserve(model, 'hip_adduction_r', optimal_force, reserves_max)
        add_reserve(model, 'hip_rotation_r', optimal_force, reserves_max)
        add_reserve(model, 'knee_angle_r', optimal_force, reserves_max)
        add_reserve(model, 'ankle_angle_r', optimal_force, reserves_max)
        add_reserve(model, 'hip_flexion_l', optimal_force, reserves_max)
        add_reserve(model, 'hip_adduction_l', optimal_force, reserves_max)
        add_reserve(model, 'hip_rotation_l', optimal_force, reserves_max)
        add_reserve(model, 'knee_angle_l', optimal_force, reserves_max)
        add_reserve(model, 'ankle_angle_l', optimal_force, reserves_max)

        def add_device(model, coord):
            actu = osim.ActivationCoordinateActuator()
            actu.set_coordinate(coord)
            actu.setName(f'device_{coord}')
            actu.setOptimalForce(1000.0)
            actu.setMinControl(-1.0)
            actu.setMaxControl(1.0)
            model.addForce(actu)
        if 'assistankle' in flags:
            add_device(model, 'ankle_angle_r')
            add_device(model, 'ankle_angle_l')

        if 'weaksoleus' in flags:
            soleus_r = model.updMuscles().get('soleus_r')
            soleus_r.set_max_isometric_force(
                0.25 * soleus_r.get_max_isometric_force())
            soleus_l = model.updMuscles().get('soleus_l')
            soleus_l.set_max_isometric_force(
                0.25 * soleus_l.get_max_isometric_force())
        if 'weakvasti' in flags:
            for muscle in ['vasmed', 'vasint', 'vaslat']:
                for side in ['_l', '_r']:
                    musc = model.updMuscles().get('%s%s' % (muscle, side))
                    musc.set_max_isometric_force(
                        0.10 * musc.get_max_isometric_force())
        if 'trendelenburg-lite' in flags:
            for muscle in ['glmin1','glmin2','glmin3','glmed1','glmed2','glmed3',
                    'glmax1','glmax2','glmax3','addbrev', 'addlong', 'addmagDist', 
                    'addmagIsch', 'addmagMid', 'addmagProx', 'piri', 'bflh', 
                    'sart', 'grac']:
                for side in ['_l', '_r']:
                    musc = model.updMuscles().get('%s%s' % (muscle, side))
                    musc.set_max_isometric_force(
                        0.10 * musc.get_max_isometric_force())
        if 'trendelenburg' in flags:
            for muscle in ['glmin1','glmin2','glmin3','glmed1','glmed2','glmed3',
                    'glmax1','glmax2','glmax3','addbrev', 'addlong', 'addmagDist', 
                    'addmagIsch', 'addmagMid', 'addmagProx', 'iliacus', 'psoas',
                    'piri', 'grac', 'bflh', 'recfem', 'sart', 'semimem', 
                    'semiten', 'tfl']:
                for side in ['_l', '_r']:
                    musc = model.updMuscles().get('%s%s' % (muscle, side))
                    musc.set_max_isometric_force(
                        0.10 * musc.get_max_isometric_force())
        if 'weakpfs' in flags:
            for muscle in ['soleus', 'gasmed', 'gaslat', 'perbrev', 'perlong',
                           'tibpost', 'fdl', 'fhl']:
                for side in ['_l', '_r']:
                    musc = model.updMuscles().get('%s%s' % (muscle, side))
                    musc.set_max_isometric_force(
                        0.10 * musc.get_max_isometric_force())

        modelProcessor = osim.ModelProcessor(model)

        modelProcessor.append(osim.ModOpReplaceJointsWithWelds(
            ['subtalar_r', 'mtp_r', 'subtalar_l', 'mtp_l']))
        modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
        modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
        # modelProcessor.append(osim.ModOpPassiveFiberStrainAtOneNormForceDGF(4.0))
        modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
        # modelProcessor.append(osim.ModOpFiberDampingDGF(0.001))
        if for_inverse:
            ext_loads_xml = os.path.join(root_dir,
                    'resources/Rajagopal2016/grf_walk.xml')
            modelProcessor.append(osim.ModOpAddExternalLoads(ext_loads_xml))

        model = modelProcessor.process()
        model.initSystem()
        muscles = model.updMuscles()
        for imusc in np.arange(muscles.getSize()):
            muscle = muscles.get(int(imusc))
            if 'gas' in muscle.getName() or 'soleus' in muscle.getName():
                muscle.set_ignore_tendon_compliance(False)

        modelProcessorTendonCompliance = osim.ModelProcessor(model)
        modelProcessorTendonCompliance.append(
                osim.ModOpUseImplicitTendonComplianceDynamicsDGF())

        return modelProcessorTendonCompliance
예제 #7
0
def solveMocoInverseWithEMG():

    # This initial block of code is identical to the code above.
    inverse = osim.MocoInverse()
    modelProcessor = osim.ModelProcessor('subject_walk_armless.osim')
    modelProcessor.append(osim.ModOpAddExternalLoads('grf_walk.xml'))
    modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
    modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
    modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
    modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))
    modelProcessor.append(osim.ModOpAddReserves(1.0))
    inverse.setModel(modelProcessor)
    inverse.setKinematics(osim.TableProcessor('coordinates.sto'))
    inverse.set_initial_time(0.81)
    inverse.set_final_time(1.79)
    inverse.set_mesh_interval(0.02)
    inverse.set_kinematics_allow_extra_columns(True)

    study = inverse.initialize()
    problem = study.updProblem()

    # Add electromyography tracking.
    emgTracking = osim.MocoControlTrackingGoal('emg_tracking')
    emgTracking.setWeight(50.0)
    # Each column in electromyography.sto is normalized so the maximum value in
    # each column is 1.0.
    controlsRef = osim.TimeSeriesTable('electromyography.sto')
    # Scale the tracked muscle activity based on peak levels from
    # "Gait Analysis: Normal and Pathological Function" by
    # Perry and Burnfield, 2010 (digitized by Carmichael Ong).
    soleus = controlsRef.updDependentColumn('soleus')
    gasmed = controlsRef.updDependentColumn('gastrocnemius')
    tibant = controlsRef.updDependentColumn('tibialis_anterior')
    for t in range(0, controlsRef.getNumRows()):
        soleus[t] = 0.77 * soleus[t]
        gasmed[t] = 0.87 * gasmed[t]
        tibant[t] = 0.37 * tibant[t]
    emgTracking.setReference(osim.TableProcessor(controlsRef))
    # Associate actuators in the model with columns in electromyography.sto.
    emgTracking.setReferenceLabel('/forceset/soleus_r', 'soleus')
    emgTracking.setReferenceLabel('/forceset/gasmed_r', 'gastrocnemius')
    emgTracking.setReferenceLabel('/forceset/gaslat_r', 'gastrocnemius')
    emgTracking.setReferenceLabel('/forceset/tibant_r', 'tibialis_anterior')
    problem.addGoal(emgTracking)

    # Solve the problem and write the solution to a Storage file.
    solution = study.solve()
    solution.write('example3DWalking_MocoInverseWithEMG_solution.sto')

    # Write the reference data in a way that's easy to compare to the solution.
    controlsRef.removeColumn('medial_hamstrings')
    controlsRef.removeColumn('biceps_femoris')
    controlsRef.removeColumn('vastus_lateralis')
    controlsRef.removeColumn('vastus_medius')
    controlsRef.removeColumn('rectus_femoris')
    controlsRef.removeColumn('gluteus_maximus')
    controlsRef.removeColumn('gluteus_medius')
    controlsRef.setColumnLabels(
        ['/forceset/soleus_r', '/forceset/gasmed_r', '/forceset/tibant_r'])
    controlsRef.appendColumn('/forceset/gaslat_r', gasmed)
    osim.STOFileAdapter.write(controlsRef, 'controls_reference.sto')

    # Generate a report comparing MocoInverse solutions without and with EMG
    # tracking.
    model = modelProcessor.process()
    output = 'example3DWalking_MocoInverseWithEMG_report.pdf'
    ref_files = [
        'example3DWalking_MocoInverseWithEMG_solution.sto',
        'controls_reference.sto'
    ]
    report = osim.report.Report(model,
                                'example3DWalking_MocoInverse_solution.sto',
                                output=output,
                                bilateral=True,
                                ref_files=ref_files)
    # The PDF is saved to the working directory.
    report.generate()
예제 #8
0
    def create_model_processor(self, root_dir):

        # Create base model without reserves.
        model = osim.Model(os.path.join(root_dir,
                'resources/Rajagopal2016/'
                'subject_walk_contact_bounded_80musc.osim'))

        forceSet = model.getForceSet()
        numContacts = 0
        for i in np.arange(forceSet.getSize()):
            forceName = forceSet.get(int(i)).getName()
            if 'contact' in forceName: numContacts += 1

        print('Removing contact force elements from model...')
        contactsRemoved = 0
        while contactsRemoved < numContacts:
            for i in np.arange(forceSet.getSize()):
                forceName = forceSet.get(int(i)).getName()
                if 'contact' in forceName: 
                    print('  --> removed', forceSet.get(int(i)).getName())
                    forceSet.remove(int(i))
                    contactsRemoved += 1
                    break

        modelProcessor = osim.ModelProcessor(model)
        modelProcessor.append(osim.ModOpReplaceJointsWithWelds(
            ['subtalar_r', 'mtp_r', 'subtalar_l', 'mtp_l', 'radius_hand_r',
             'radius_hand_l']))
        modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
        modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
        modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
        modelProcessor.append(osim.ModOpFiberDampingDGF(0))
        baseModel = modelProcessor.process()

        # Create model for CMC
        modelProcessorCMC = osim.ModelProcessor(baseModel)
        modelProcessorCMC.append(osim.ModOpAddReserves(1))
        cmcModel = modelProcessorCMC.process()

        tasks = osim.CMC_TaskSet()
        for coord in cmcModel.getCoordinateSet():
            cname = coord.getName()
            if cname.endswith('_beta'):
                continue
            task = osim.CMC_Joint()
            task.setName(cname)
            task.setCoordinateName(cname)
            task.setKP(100, 1, 1)
            task.setKV(20, 1, 1)
            task.setActive(True, False, False)
            tasks.cloneAndAppend(task)
        tasks.printToXML(
            os.path.join(root_dir, 'code',
                         'motion_prescribed_walking_cmc_tasks.xml'))

        cmcModel.printToXML(os.path.join(root_dir, 'resources/Rajagopal2016/'
                                         'subject_walk_for_cmc.osim'))

        # Create direct collocation model:
        #   - TODO reserves
        #   - implicit tendon compliance mode
        #   - add external loads
        def add_reserve(model, coord, max_control):
            actu = osim.CoordinateActuator(coord)
            if coord.startswith('lumbar'):
                prefix = 'torque_'
            elif coord.startswith('pelvis'):
                prefix = 'residual_'
            else:
                prefix = 'reserve_'
            actu.setName(prefix + coord)
            actu.setMinControl(-1)
            actu.setMaxControl(1)
            actu.setOptimalForce(max_control)
            model.addForce(actu)
        add_reserve(baseModel, 'lumbar_extension', 50)
        add_reserve(baseModel, 'lumbar_bending', 50)
        add_reserve(baseModel, 'lumbar_rotation', 20)
        for side in ['_l', '_r']:
            add_reserve(baseModel, f'arm_flex{side}', 15)
            add_reserve(baseModel, f'arm_add{side}', 15)
            add_reserve(baseModel, f'arm_rot{side}', 5)
            add_reserve(baseModel, f'elbow_flex{side}', 5)
            add_reserve(baseModel, f'pro_sup{side}', 1)
            add_reserve(baseModel, f'hip_rotation{side}', 0.5)

        add_reserve(baseModel, 'pelvis_tilt', 60)
        add_reserve(baseModel, 'pelvis_list', 30)
        add_reserve(baseModel, 'pelvis_rotation', 15)
        add_reserve(baseModel, 'pelvis_tx', 100)
        add_reserve(baseModel, 'pelvis_ty', 200)
        add_reserve(baseModel, 'pelvis_tz', 35)
        baseModel.initSystem()
        muscles = baseModel.updMuscles()
        for imusc in np.arange(muscles.getSize()):
            muscle = muscles.get(int(imusc))
            if 'gas' in muscle.getName() or 'soleus' in muscle.getName():
                muscle.set_ignore_tendon_compliance(False)

        modelProcessorDC = osim.ModelProcessor(baseModel)
        modelProcessorDC.append(osim.ModOpFiberDampingDGF(0.01))
        modelProcessorDC.append(osim.ModOpAddReserves(1, 2.5, True))
        modelProcessorDC.append(
            osim.ModOpTendonComplianceDynamicsModeDGF('implicit'))

        ext_loads_xml = os.path.join(root_dir,
                                     "resources/Rajagopal2016/grf_walk.xml")
        modelProcessorDC.append(osim.ModOpAddExternalLoads(ext_loads_xml))

        return modelProcessorDC
예제 #9
0
def muscleDrivenStateTracking():

    #Create and name an instance of the MocoTrack tool.
    track = osim.MocoTrack()
    track.setName('muscleDrivenStateTracking')

    #Construct a ModelProcessor and set it on the tool.
    #Currently the coordinate actuators for the pelvis, along with the reserve
    #actuators are fairly generally set, and not weighted at all in cost function.
    #These actuators could be more carefully considered to generate an appropriate
    #muscle driven simulation. For example, if they max and min control to 1 - the 
    #pelvis actuators may not produce enough torque.
    modelProcessor = osim.ModelProcessor('scaledModelMuscle.osim')
    modelProcessor.append(osim.ModOpAddExternalLoads('Jog05_grf.xml'))
    modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
    modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
    # Only valid for DeGrooteFregly2016Muscles.
    modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
    # Only valid for DeGrooteFregly2016Muscles.
    modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))
    modelProcessor.append(osim.ModOpAddReserves(2))
    track.setModel(modelProcessor)

    #Construct a TableProcessor of the coordinate data and pass it to the 
    #tracking tool. TableProcessors can be used in the same way as
    #ModelProcessors by appending TableOperators to modify the base table.
    #A TableProcessor with no operators, as we have here, simply returns the
    #base table.
    track.setStatesReference(osim.TableProcessor('ikResults_states.sto'))
    track.set_states_global_tracking_weight(5)

    ##### TODO: add more specific weights for different state coordinates like in RRA

    #This setting allows extra data columns contained in the states
    #reference that don't correspond to model coordinates.
    track.set_allow_unused_references(True)

    # Since there is only coordinate position data the states references, this
    # setting is enabled to fill in the missing coordinate speed data using
    # the derivative of splined position data.
    track.set_track_reference_position_derivatives(True)

    # Initial time, final time, and mesh interval.
    track.set_initial_time(osim.Storage('ikResults_states.sto').getFirstTime())
    track.set_final_time(osim.Storage('ikResults_states.sto').getLastTime())
    track.set_mesh_interval(0.08)

    #Instead of calling solve(), call initialize() to receive a pre-configured
    #MocoStudy object based on the settings above. Use this to customize the
    #problem beyond the MocoTrack interface.
    study = track.initialize()

    #Get a reference to the MocoControlCost that is added to every MocoTrack
    #problem by default.
    problem = study.updProblem()
    effort = osim.MocoControlGoal.safeDownCast(problem.updGoal('control_effort'))
    effort.setWeight(1)

    # # Put a large weight on the pelvis CoordinateActuators, which act as the
    # # residual, or 'hand-of-god', forces which we would like to keep as small
    # # as possible.
    # model = modelProcessor.process()
    # model.initSystem()
    # forceSet = model.getForceSet()
    # for ii in range(forceSet.getSize()):
    #     forcePath = forceSet.get(ii).getAbsolutePathString()
    #     if 'pelvis' in str(forcePath):
    #         effort.setWeightForControl(forcePath, 10)
            
    #Get solver and set the mesh interval
    solver = study.initCasADiSolver()
    #50 mesh intervals for half gait cycle recommended, keep smaller for now
    #19 will produce the same as inverse solution above
    # solver.set_num_mesh_intervals(19)
    
    #Set solver parameters
    solver.set_optim_constraint_tolerance(1e-3)
    solver.set_optim_convergence_tolerance(1e-3)
    
    # Solve and visualize.
    solution = study.solve()

    #Return the solution as an object that we can use
    return solution