Raw File
MuscleOptimization.cpp
#include "MuscleOptimization.h"
#include "IntegratedWorld.h"
#include "MusculoSkeletalSystem.h"
#include "Ball.h"
#include <IpIpoptData.hpp>
using namespace Ipopt;
MuscleOptimization::
MuscleOptimization(const std::shared_ptr<IntegratedWorld>& iw)
	:mIntegratedWorld(iw),mWeightTracking(1.0),mWeightEffort(0.1),mSparseUpdateCount(0)
{
	int num_muscles =  mIntegratedWorld->GetMusculoSkeletalSystem()->GetNumMuscles();
	int num_muscle_forces =  mIntegratedWorld->GetMusculoSkeletalSystem()->GetNumMuscleForces();
	int dofs 		=  mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getNumDofs();  
	mSolution.resize(dofs +num_muscles);
	mQddDesired.resize(dofs);

	mJt.resize(dofs,(num_muscle_forces)*3);
	mA.resize(num_muscle_forces*3,num_muscles);
	mP.resize(num_muscle_forces*3);

	mM_minus_JtA.resize(dofs,dofs+num_muscles);
	mJtp_minus_c.resize(dofs);	
	mSolution.setZero();
	mQddDesired.setZero();

	mJt.setZero();
	mP.setZero();

	mM_minus_JtA.setZero();
	mJtp_minus_c.setZero();
}
MuscleOptimization::
~MuscleOptimization()
{

}
void
MuscleOptimization::
Update(const Eigen::VectorXd& qdd_desired)
{
	mQddDesired = qdd_desired;

	//Update Jt
	auto& skel = mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton();
	int dofs = skel->getNumDofs();
	int index = 0;
	mJt.setZero();
	for(auto& muscle : mIntegratedWorld->GetMusculoSkeletalSystem()->GetMuscles())
	{
		
		auto& origin_way_points = muscle->origin_way_points;
		auto& insertion_way_points = muscle->insertion_way_points;
		int n = muscle->GetNumForces();
		int no = origin_way_points.size();
		mJt.block(0,index*3,dofs,muscle->GetNumForces()*3) = muscle->GetJacobianTranspose();
		// std::cout<<mJt<<std::endl<<std::endl;
		// mJt.block(0,(index+0)*3,dofs,3) = skel->getLinearJacobian(muscle->origin_way_points.back().first,muscle->origin_way_points.back().second).transpose();
		// mJt.block(0,(index+1)*3,dofs,3) = skel->getLinearJacobian(muscle->insertion_way_points.back().first,muscle->insertion_way_points.back().second).transpose();
		// for(int j=0;j<no;j++)
		// 	mJt.block(0,(index+j)*3,dofs,3) = skel->getLinearJacobian(muscle->origin_way_points[j].first,muscle->origin_way_points[j].second).transpose();

		// for(int j=no;j<n;j++)
		// 	mJt.block(0,(index+j)*3,dofs,3) = skel->getLinearJacobian(muscle->insertion_way_points[j-no].first,muscle->insertion_way_points[j-no].second).transpose();

		index +=n;
	}
	// std::cout<<std::endl;
	int num_muscles =  mIntegratedWorld->GetMusculoSkeletalSystem()->GetNumMuscles();
	mIntegratedWorld->GetMusculoSkeletalSystem()->ComputeForceDerivative(mIntegratedWorld->GetSoftWorld(),mA);
	mP = mIntegratedWorld->GetMusculoSkeletalSystem()->ComputeForce(mIntegratedWorld->GetSoftWorld());

	mP = mP-mA*mIntegratedWorld->GetMusculoSkeletalSystem()->GetActivationLevels();

	mM_minus_JtA.setZero();
	mM_minus_JtA.block(0,0,dofs,dofs)= mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getMassMatrix();
	mM_minus_JtA.block(0,dofs,dofs,num_muscles)= -mJt*mA;
	mJtp_minus_c = mJt*mP - mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getCoriolisAndGravityForces();
}

const Eigen::VectorXd&
MuscleOptimization::
GetSolution()
{
	return mSolution;
}

void
MuscleOptimization::
UpdateConstraints(const Eigen::VectorXd& act)
{
	// return;
	auto prev_act = mIntegratedWorld->GetMusculoSkeletalSystem()->GetActivationLevels();
	int num_muscles =  mIntegratedWorld->GetMusculoSkeletalSystem()->GetNumMuscles();
	int dofs 		=  mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getNumDofs(); 
	// if(mSparseUpdateCount%10==0)
	// {
	// 	if( (act-prev_act).norm()>1E-5 || mSparseUpdateCount ==0)
	// 	{
			mIntegratedWorld->GetMusculoSkeletalSystem()->SetActivationLevels(act);
			mIntegratedWorld->GetSoftWorld()->TimeStepping(false);
			//Update A,p
			mIntegratedWorld->GetMusculoSkeletalSystem()->ComputeForceDerivative(mIntegratedWorld->GetSoftWorld(),mA);
			mP = mIntegratedWorld->GetMusculoSkeletalSystem()->ComputeForce(mIntegratedWorld->GetSoftWorld());

			mP = mP-mA*act;
			//Update Cache
			mM_minus_JtA.block(0,0,dofs,dofs)= mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getMassMatrix();
			mM_minus_JtA.block(0,dofs,dofs,num_muscles)= -mJt*mA;
			mJtp_minus_c = mJt*mP - mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getCoriolisAndGravityForces();
	// 	}
	// }
	mSparseUpdateCount++;
}
bool
MuscleOptimization::
get_nlp_info(	Index& n, Index& m, Index& nnz_jac_g,Index& nnz_h_lag, IndexStyleEnum& index_style)
{
	m = mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getNumDofs();
	n = m + mIntegratedWorld->GetMusculoSkeletalSystem()->GetNumMuscles();

	nnz_jac_g = n*m;			//g : full matrix
	nnz_h_lag = n;				//H : full matrix

	index_style = TNLP::C_STYLE;
	return true;
}
bool
MuscleOptimization::
get_bounds_info(Index n, Number* x_l, Number* x_u,Index m, Number* g_l, Number* g_u)
{
	for(int i=0;i<m;i++)
	{
		x_l[i] =-1E5;
		x_u[i] =1E5;
	}
	for(int i=m;i<n;i++)
	{
		x_l[i] = 0.0;
		x_u[i] = 1.0;
	}
	for(int i =0;i<m;i++)
		g_l[i]=g_u[i] =0.0;

	return true;
}
bool
MuscleOptimization::
get_starting_point(	Index n, bool init_x, Number* x,bool init_z, Number* z_L, Number* z_U,Index m, bool init_lambda,Number* lambda)
{
	for(int i =0;i<n;i++)
		x[i] = mSolution[i];

	return true;
}
bool
MuscleOptimization::
eval_f(	Index n, const Number* x, bool new_x, Number& obj_value)
{
	double track = 0.0;
	double effort = 0.0;

	int m = mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getNumDofs();
	Eigen::VectorXd qdd(m);

	for(int i=0;i<m;i++)
		qdd[i] = x[i];

	track = mWeightTracking*((qdd-mQddDesired).squaredNorm());

	for(int i=m;i<n;i++)
		effort += x[i]*x[i];
	effort *= mWeightEffort;

	obj_value = track + effort;

	return true;
}
bool
MuscleOptimization::
eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
{
	int m = mIntegratedWorld->GetMusculoSkeletalSystem()->GetSkeleton()->getNumDofs();

	for(int i=0;i<m;i++)
		grad_f[i] = 2.0*mWeightTracking*(x[i]-mQddDesired[i]);
	for(int i=m;i<n;i++)
		grad_f[i] = 2.0*mWeightEffort*(x[i]);

	return true;
}
bool
MuscleOptimization::
eval_g(	Index n, const Number* x, bool new_x, Index m, Number* g)
{
	Eigen::VectorXd eigen_x(n), activation(n-m),eigen_g(m);
	for(int i=0;i<n;i++)
		eigen_x[i] = x[i];

	activation = eigen_x.tail(n-m);
	UpdateConstraints(activation);
	eigen_g = mM_minus_JtA*eigen_x - mJtp_minus_c;
	for(int i = 0;i<m;i++)
		g[i] = eigen_g[i];

	return true;
}
bool
MuscleOptimization::
eval_jac_g( Index n, const Number* x, bool new_x,Index m, Index nele_jac, Index* iRow, Index *jCol,Number* values)
{
	int nnz = 0;

	if(values == NULL)
	{
		for(int i =0;i<m;i++)
		{
			for(int j =0;j<n;j++)
			{
				iRow[nnz] = i;
				jCol[nnz++] = j;
			}
		}
	}
	else
	{
		Eigen::VectorXd eigen_x(n), activation(n-m),eigen_g(m);
		for(int i=0;i<n;i++)
			eigen_x[i] = x[i];

		activation = eigen_x.tail(n-m);
		UpdateConstraints(activation);
		for(int i =0;i<m;i++)
		{
			for(int j =0;j<n;j++)
			{
				values[nnz++] = mM_minus_JtA(i,j);
			}
		}
	}

	return true;

}
bool
MuscleOptimization::
eval_h( Index n, const Number* x, bool new_x,Number obj_factor, Index m, const Number* lambda,bool new_lambda, Index nele_hess, Index* iRow,Index* jCol, Number* values)
{
	int nnz = 0;

	if(values == NULL)
	{
		for(int i =0;i<n;i++)
		{
			iRow[nnz] = i;
			jCol[nnz++] = i;
		}

	}
	else
	{
		for(int i =0;i<m;i++)
			values[nnz++] =  2.0*obj_factor*mWeightTracking;
		for(int i=m;i<n;i++)
			values[nnz++] = 2.0*obj_factor*mWeightEffort;
	}

	return true;
}
Ipopt::Index num_iter=0;
void
MuscleOptimization::
finalize_solution(	SolverReturn status,Index n, const Number* x, const Number* z_L, const Number* z_U,Index m, const Number* g, const Number* lambda,Number obj_value,const IpoptData* ip_data,IpoptCalculatedQuantities* ip_cq)
{
	num_iter+=ip_data->iter_count();
	// std::cout<<ip_data->iter_count()<<std::endl;
	// std::cout<<num_iter<<std::endl;
	for(int i=0;i<n;i++)
		mSolution[i] = x[i];
	mSparseUpdateCount = 0;
}
back to top