Minimization of CoP - Custom Goal

OpenSim Moco is a software toolkit to solve optimal control problems with musculoskeletal models defined in OpenSim using the direct collocation method.
POST REPLY
User avatar
Burak Kula
Posts: 31
Joined: Wed Dec 04, 2019 3:34 pm

Minimization of CoP - Custom Goal

Post by Burak Kula » Mon Feb 01, 2021 12:59 pm

Hello Everyone,

Recently I am working on minimization of oscillations of CoP. As far as I realized, in Moco there no built-in codes for this task so I am planing to use a specific goal. But I faced with a problem that even if I am able to find CoP, I don't know how can I implement them with moco problem. I am going to give my codes below. I am waiting for tips or hints to complete the task.

I don't know how to establish a connection between, points and moco problem.

Code: Select all


function value = CoPMinimizationGoal
% This example allows Matlab users of Moco to prototype custom costs/goals
% to send to Moco developers for implementing in C++.
% If you can write your goal in the "...GoalIntegrand" and "...GoalValue"
% functions below and you can invoke evaluateCustomGoal() (shown below)
% without error, then Moco developers can probably easily convert your goal
% into a proper C++ goal for you. Once your prototype works, create an issue
% on GitHub.
%
% In C++, MocoGoals can be in cost mode or endpoint constraint mode. In this
% example, we expect that your goal is in cost mode.
%
% In this example, the custom goal is minimizing the sum of squared controls
% divided by the time duration of the phase.

import org.opensim.modeling.*;

study = MocoStudy();
problem = study.updProblem();
mp=ModelProcessor('2D_Exo_Gait_V1_exo_integrated.osim');
problem.setModelProcessor(mp);
model = mp.process();
model.initSystem();

% State Bounds
problem.setTimeBounds(0, [1 1.1]);
% States of Upper Body Musculoskeletal System.
problem.setStateInfo('/jointset/groundPelvis/pelvis_tilt/value', ...
    [-10*pi/180, 10*pi/180]);
problem.setStateInfo('/jointset/groundPelvis/pelvis_tx/value', ...
    [-0.2 2]);
problem.setStateInfo('/jointset/groundPelvis/pelvis_ty/value', ...
    [0.75, 1.25]);
problem.setStateInfo("/jointset/lumbar/lumbar/value", ...
    [0, 20*pi/180]);
% States of Exoskeleton.
problem.setStateInfo('/jointset/exo_hip_r/exo_hip_flexion_r/value', ...
    [-25*pi/180, 45*pi/180]);
problem.setStateInfo('/jointset/exo_hip_l/exo_hip_flexion_l/value', ...
    [-25*pi/180, 45*pi/180]);
problem.setStateInfo('/jointset/exo_knee_r/exo_knee_angle_r/value', ...
    [-75*pi/180, 0]);
problem.setStateInfo('/jointset/exo_knee_l/exo_knee_angle_l/value', ...
    [-75*pi/180, 0]);
problem.setStateInfo('/jointset/exo_ankle_r/exo_ankle_angle_r/value', ...
    [-30*pi/180, 20*pi/180]);
problem.setStateInfo('/jointset/exo_ankle_l/exo_ankle_angle_l/value', ...
    [-30*pi/180, 20*pi/180]);

solver = study.initCasADiSolver();
% trajectory = solver.createGuess();
trajectory=solver.createGuess('bounds'); % Use bounds as initial guess
trajectory.resampleWithNumTimes(2);
trajectory.setTime([0 1]); 
trajectory.setState('/jointset/groundPelvis/pelvis_tilt/value', ...
    [-20*pi/180, -10*pi/180]);
trajectory.setState('/jointset/groundPelvis/pelvis_tx/value', ...
    [0, 1]);
trajectory.setState('/jointset/groundPelvis/pelvis_ty/value', ...
    [0.75, 1.25]);
trajectory.setState("/jointset/lumbar/lumbar/value", ...
    [0, 20*pi/180]);
trajectory.setState('/jointset/exo_hip_r/exo_hip_flexion_r/value', ...
    [-10*pi/180, 60*pi/180]);
trajectory.setState('/jointset/exo_hip_l/exo_hip_flexion_l/value', ...
    [-10*pi/180, 60*pi/180]);
trajectory.setState('/jointset/exo_knee_r/exo_knee_angle_r/value', ...
    [-50*pi/180, 0]);
trajectory.setState('/jointset/exo_knee_l/exo_knee_angle_l/value', ...
    [-50*pi/180, 0]);
trajectory.setState('/jointset/exo_ankle_r/exo_ankle_angle_r/value', ...
    [-15*pi/180, 25*pi/180]);
trajectory.setState('/jointset/exo_ankle_l/exo_ankle_angle_l/value', ...
    [-15*pi/180, 25*pi/180]);
solver.setGuess(trajectory);

%Contact Determination
contact_r = StdVectorString();
contact_l = StdVectorString();
contact_r.add('/contactHeel_r');
contact_r.add('/contactFront_r');
contact_l.add('/contactHeel_l');
contact_l.add('/contactFront_l');
externalForcesTableFlat = opensimMoco.createExternalLoadsTableForGait(model,trajectory,contact_r,contact_l);
data = osimMocoTableToStruct(externalForcesTableFlat);

Right_GRF_X=data.ground_force_r_vx;
Right_GRF_Y=data.ground_force_r_vy;
Right_GRF_Z=data.ground_force_r_vz;
Right_Torque_X=data.ground_torque_r_x;
Right_Torque_Y=data.ground_torque_r_y;
Right_Torque_Z=data.ground_torque_r_z;

Left_GRF_X=data.ground_force_l_vx;
Left_GRF_Y=data.ground_force_l_vy;
Left_GRF_Z=data.ground_force_l_vz;
Left_Torque_X=data.ground_torque_l_x;
Left_Torque_Y=data.ground_torque_l_y;
Left_Torque_Z=data.ground_torque_l_z;

point_Right_X=Right_Torque_X./Right_GRF_X;
point_Right_Y=Right_Torque_Y./Right_GRF_Y;
point_Right_Z=Right_Torque_Z./Right_GRF_Z;
point_Left_X=Left_Torque_X./Left_GRF_X;
point_Left_Y=Left_Torque_Y./Left_GRF_Y;
point_Left_Z=Left_Torque_Z./Left_GRF_Z;

points_Right=[point_Right_X point_Right_Y point_Right_Z];
points_Left=[point_Left_X point_Left_Y point_Left_Z];
points=[points_Right points_Left];

value = evaluateCustomGoal(problem, trajectory , ...
        @calcMyCoPGoalIntegrand, @calcMyCoPValue);


User avatar
Nicholas Bianco
Posts: 963
Joined: Thu Oct 04, 2012 8:09 pm

Re: Minimization of CoP - Custom Goal

Post by Nicholas Bianco » Fri Feb 05, 2021 12:51 pm

Hi Burak,

The Matlab code is available just as a prototyping tool. The code will need to be converted to C++ to be incorporated into Moco.

Have you confirmed that this code correctly computes COP (e.g., given an existing motion)? Also, is the purpose of this goal to minimize COP or track an existing COP trajectory? I'm not sure the usefulness of minimizing the COP on its own, as the COP will need to vary over a gait cycle.

-Nick

User avatar
Simon Jeng
Posts: 87
Joined: Fri Sep 07, 2018 8:26 pm

Re: Minimization of CoP - Custom Goal

Post by Simon Jeng » Wed Feb 10, 2021 1:12 am

Hi Nick,

I have tried to prototype a custom goal of minimizing CoP displacement using examplePrototypeCustomGoal.m. I successfully write my goal in the "...GoalIntegrand" and "...GoalValue" functions and invoke evaluateCustomGoal() to calculate the integral of squared CoP displacement without error. My goal is only used for human movements that the foot does not move relative to the ground(e.g. squat-to-stand) because the location of CoP is obtained by calculating the joint reaction force/moment(the joint is a weld joint connecting the foot and ground). Next, is it possible for me to please Moco developers convert my goal into a plugin for me so that I can use it in Matlab? If it's possible, I would show the code.

Best,
Simon

User avatar
Simon Jeng
Posts: 87
Joined: Fri Sep 07, 2018 8:26 pm

Re: Minimization of CoP - Custom Goal

Post by Simon Jeng » Tue Feb 16, 2021 2:57 am

Thanks Nick,

I have finished plugin-making.

Best,
Simon

User avatar
Nicholas Bianco
Posts: 963
Joined: Thu Oct 04, 2012 8:09 pm

Re: Minimization of CoP - Custom Goal

Post by Nicholas Bianco » Mon Feb 22, 2021 1:07 pm

Hi Simon,

I see -- you're leaving in the weld joint between the feet and the ground, but you want the COP to remain beneath the feet to make the motion realistic, good idea!

I think we were to create a new goal, I'd want to make sure it's a generally useful as possible. I'd want a COP goal to be able to track any COP trajectory, not just minimize the COP (which is the equivalent to tracking a "zero" trajectory). But if your plugin is working for you now, maybe we can wait on this.

-Nick

POST REPLY