Пример #1
0
void
test_constraint(void)
{
  int i,j,n,m;
  static Matrix Jbig;
  static Matrix dJbigdt;
  static Vector dsbigdt;
  static Matrix JbigMinvJbigt;
  static Matrix JbigMinvJbigtinv;
  static Matrix Minv;
  static Matrix MinvJbigt;
  static Matrix Jbigt;
  static Vector dJbigdtdsbigdt;
  static Matrix Jbart;
  static Matrix Jbar;
  static Vector lv;
  static Vector lambda;
  static Vector f;
  static Matrix R;
  static Vector v;
  static int firsttime = TRUE;
  int    debug_print = TRUE;

  if (firsttime) {
    firsttime = FALSE;
    Jbig             = my_matrix(1,N_ENDEFFS*6,1,N_DOFS+6);
    Jbigt            = my_matrix(1,N_DOFS+6,1,N_ENDEFFS*6);
    dJbigdt          = my_matrix(1,N_ENDEFFS*6,1,N_DOFS+6);
    JbigMinvJbigt    = my_matrix(1,N_ENDEFFS*6,1,N_ENDEFFS*6);
    JbigMinvJbigtinv = my_matrix(1,N_ENDEFFS*6,1,N_ENDEFFS*6);
    Minv             = my_matrix(1,N_DOFS+6,1,N_DOFS+6);
    MinvJbigt        = my_matrix(1,N_DOFS+6,1,N_ENDEFFS*6);
    dsbigdt          = my_vector(1,N_DOFS+6);
    dJbigdtdsbigdt   = my_vector(1,N_ENDEFFS*6);
    Jbar             = my_matrix(1,N_DOFS+6,1,N_ENDEFFS*6);
    Jbart            = my_matrix(1,N_ENDEFFS*6,1,N_DOFS+6);
    lv               = my_vector(1,N_ENDEFFS*6);
    lambda           = my_vector(1,N_ENDEFFS*6);
    f                = my_vector(1,N_DOFS+6);
    R                = my_matrix(1,N_CART,1,N_CART);
    v                = my_vector(1,N_CART);

    // the base part of Jbig is just the identity matrix for both constraints
    for (i=1; i<=6; ++i)
      Jbig[i][N_DOFS+i] = 1.0;

    for (i=1; i<=6; ++i)
      Jbig[i+6][N_DOFS+i] = 1.0;

  }

  // build the Jacobian including the base -- just copy J into Jbig
  mat_equal_size(J,N_ENDEFFS*6,N_DOFS,Jbig);
  mat_trans(Jbig,Jbigt);

  // build the Jacobian derivative
  mat_equal_size(dJdt,N_ENDEFFS*6,N_DOFS,dJbigdt);

  // build the augmented state derivate vector
  for (i=1; i<=N_DOFS; ++i)
    dsbigdt[i] = joint_state[i].thd;

  for (i=1; i<=N_CART; ++i)
    dsbigdt[N_DOFS+i] = base_state.xd[i];

  for (i=1; i<=N_CART; ++i)
    dsbigdt[N_DOFS+N_CART+i] = base_orient.ad[i];


  // compute J-bar transpose
  my_inv_ludcmp(rbdInertiaMatrix,N_DOFS+6, Minv);
  mat_mult(Minv,Jbigt,MinvJbigt);
  mat_mult(Jbig,MinvJbigt,JbigMinvJbigt);
  my_inv_ludcmp(JbigMinvJbigt,N_ENDEFFS*6,JbigMinvJbigtinv);
  mat_mult(MinvJbigt,JbigMinvJbigtinv,Jbar);
  mat_trans(Jbar,Jbart);

  // compute C+G-u
  for (i=1; i<=N_DOFS; ++i)
    f[i] = -joint_state[i].u;
  
  for (i=1; i<=6; ++i)
    f[N_DOFS+i] = 0.0;

  vec_add(f,rbdCplusGVector,f);

  // compute first part of lambda
  mat_vec_mult(Jbart,f,lambda);

  // compute second part of lambda
  mat_vec_mult(dJbigdt,dsbigdt,dJbigdtdsbigdt);
  mat_vec_mult(JbigMinvJbigtinv,dJbigdtdsbigdt,lv);

  // compute final lambda
  vec_sub(lambda,lv,lambda);

  // ----------------------------------------------------------------------
  // express lambda in the same coordinate at the foot sensors

  /* rotation matrix from world to L_AAA coordinates:
     we can borrow this matrix from the toes, which have the same
     rotation, but just a different offset vector, which is not
     needed here */

  mat_trans_size(Alink[L_IN_HEEL],N_CART,N_CART,R);

  // transform forces
  for (i=1; i<=N_CART; ++i)
    v[i] = lambda[N_CART*2+i];
  mat_vec_mult(R,v,v);

  if (debug_print) {
    printf("LEFT Force: lx=% 7.5f   sx=% 7.5f\n",v[1],misc_sim_sensor[L_CFx]);
    printf("LEFT Force: ly=% 7.5f   sy=% 7.5f\n",v[2],misc_sim_sensor[L_CFy]);
    printf("LEFT Force: lz=% 7.5f   sz=% 7.5f\n",v[3],misc_sim_sensor[L_CFz]);
  }

  misc_sensor[L_CFx] = v[1];
  misc_sensor[L_CFy] = v[2];
  misc_sensor[L_CFz] = v[3];

  // transform torques
  for (i=1; i<=N_CART; ++i)
    v[i] = lambda[N_CART*2+N_CART+i];
  mat_vec_mult(R,v,v);

  if (debug_print) {
    printf("LEFT Torque: lx=% 7.5f   sx=% 7.5f\n",v[1],misc_sim_sensor[L_CTa]);
    printf("LEFT Torque: ly=% 7.5f   sy=% 7.5f\n",v[2],misc_sim_sensor[L_CTb]);
    printf("LEFT Torque: lz=% 7.5f   sz=% 7.5f\n",v[3],misc_sim_sensor[L_CTg]);
  }

  misc_sensor[L_CTa] = v[1];
  misc_sensor[L_CTb] = v[2];
  misc_sensor[L_CTg] = v[3];

  /* rotation matrix from world to R_AAA coordinates :
     we can borrow this matrix from the toes, which have the same
     rotation, but just a different offset vector, which is not
     needed here */
  mat_trans_size(Alink[R_IN_HEEL],N_CART,N_CART,R);

  // transform forces
  for (i=1; i<=N_CART; ++i)
    v[i] = lambda[i];
  mat_vec_mult(R,v,v);

  if (debug_print) {
    printf("RIGHT Force: lx=% 7.5f   sx=% 7.5f\n",v[1],misc_sim_sensor[R_CFx]);
    printf("RIGHT Force: ly=% 7.5f   sy=% 7.5f\n",v[2],misc_sim_sensor[R_CFy]);
    printf("RIGHT Force: lz=% 7.5f   sz=% 7.5f\n",v[3],misc_sim_sensor[R_CFz]);
  }
    
  misc_sensor[R_CFx] = v[1];
  misc_sensor[R_CFy] = v[2];
  misc_sensor[R_CFz] = v[3];

  // transform torques
  for (i=1; i<=N_CART; ++i)
    v[i] = lambda[N_CART+i];
  mat_vec_mult(R,v,v);

  if (debug_print) {
    printf("RIGHT Torque: lx=% 7.5f   sx=% 7.5f\n",v[1],misc_sim_sensor[R_CTa]);
    printf("RIGHT Torque: ly=% 7.5f   sy=% 7.5f\n",v[2],misc_sim_sensor[R_CTb]);
    printf("RIGHT Torque: lz=% 7.5f   sz=% 7.5f\n",v[3],misc_sim_sensor[R_CTg]);
  }

  misc_sensor[R_CTa] = v[1];
  misc_sensor[R_CTb] = v[2];
  misc_sensor[R_CTg] = v[3];

  if (debug_print)
    getchar();
  
}
Пример #2
0
/*!*****************************************************************************
 *******************************************************************************
\note  parm_opt
\date  10/20/91

\remarks 
		this is the major optimzation program

 *******************************************************************************
 Function Parameters: [in]=input,[out]=output

 \param[in]     tol      : error tolernance to be achieved
 \param[in]     n_parm   : number of parameters to be optimzed
 \param[in]     n_con    : number of contraints to be taken into account
 \param[in]     f_dLda   : function which calculates the derivative of the 
                    optimziation criterion with respect to the parameters;
		    must return vector
 \param[in]     f_dMda   : function which calculates the derivate of the 
                    constraints with respect to parameters
		    must return matrix
 \param[in]     f_M      : constraints function, must always be formulted to
                    return 0 for properly fulfilled constraints
 \param[in]     f_L      : function to calculate simple cost (i.e., constraint
	            cost NOT included), the constraint costs are added
		    by this program automatically, the function returns
		    a double scalar
 \param[in]     f_dLdada : second derivative of L with respect to the parameters, 
                    must be a matrix of dim n_parm x n_parm
 \param[in]     f_dMdada : second derivative of M with respect to parameters,
                    must be a matrix n_con*n_parm x n_parm
 \param[in]     use_newton: TRUE or FALSE to indicate that second derivatives
                    are given and can be used for Newton algorithm
 \param[in,out] a        : initial setting of parameters and also return of
                    optimal value (must be a vector, even if scalar)
 \param[out]    final_cost: the final cost
 \param[out]    err       : the sqrt of the squared error of all constraints
      				
      NOTE: - program returns TRUE if everything correct, otherwise FALSE
      			- always minimizes the cost!!!
      			-	algorithms come from Dyer McReynolds
      			
      NOTE: besides the possiblity of a bug, the Newton method seems to
      			sacrifice the validity of the constraint a little up to
      			quite a bit and should be used prudently

 ******************************************************************************/
int
parm_opt(double *a,int n_parm, int n_con, double *tol, void (*f_dLda)(), 
	void (*f_dMda)(), void (*f_M)(), double (*f_L)(), void (*f_dMdada)(),
	void (*f_dLdada)(), int use_newton, double *final_cost, double *err)

{
  
  register int i,j,n;
  double cost= 999.e30;
  double last_cost = 0.0;
  double *mult=NULL, *new_mult=NULL; /* this is the vector of Lagrange mulitplier */
  double **dMda=NULL, **dMda_t=NULL;
  double *dLda;
  double *K=NULL; /* the error in the constraints */
  double eps = 0.025; /* the learning rate */
  double **aux_mat=NULL; /* needed for inversion of matrix */
  double *aux_vec=NULL;
  double *new_a;
  double **dMdada=NULL;
  double **dLdada=NULL;
  double **A=NULL; /* big matrix, a combination of several other matrices */
  double *B=NULL;  /* a big vector */
  double **A_inv=NULL;
  int    rc=TRUE;
  long   count = 0;
  int    last_sign = 1;
  int    pending1 = FALSE, pending2 = FALSE;
  int    firsttime = TRUE;
  int    newton_active = FALSE;
  
  dLda    = my_vector(1,n_parm);
  new_a   = my_vector(1,n_parm);
  if (n_con > 0) {
    mult    = my_vector(1,n_con);
    dMda    = my_matrix(1,n_con,1,n_parm);
    dMda_t  = my_matrix(1,n_parm,1,n_con);
    K       = my_vector(1,n_con);
    aux_mat = my_matrix(1,n_con,1,n_con);
    aux_vec = my_vector(1,n_con);
  }

  
  if (use_newton) {
    
    dLdada   = my_matrix(1,n_parm,1,n_parm);
    A        = my_matrix(1,n_parm+n_con,1,n_parm+n_con);
    A_inv    = my_matrix(1,n_parm+n_con,1,n_parm+n_con);
    B        = my_vector(1,n_parm+n_con);

    if (n_con > 0) {
      dMdada   = my_matrix(1,n_con*n_parm,1,n_parm);
      new_mult = my_vector(1,n_con);
    }
    
    for (i=1+n_parm; i<=n_con+n_parm; ++i) {
      for (j=1+n_parm; j<=n_con+n_parm; ++j) {
	A[i][j] = 0.0;
      }
    }
    
  }
  
  
  while (fabs(cost-last_cost) > *tol) {
    
    ++count;
    pending1 = FALSE;
    pending2 = FALSE;
    
  AGAIN:
    
    /* calculate the current Lagrange multipliers */
    
    if (n_con > 0) {
      (*f_M)(a,K);       /* takes the parameters, returns residuals */
      (*f_dMda)(a,dMda); /* takes the parameters, returns the Jacobian */
    }
    (*f_dLda)(a,dLda); /* takes the parameters, returns the gradient */
    
    if (n_con > 0) {
      mat_trans(dMda,dMda_t);
    }
    
    
    if (newton_active) {
      if (n_con > 0) {
	(*f_dMdada)(a,dMdada);
      }
      (*f_dLdada)(a,dLdada);
    }
    
    
    /* the first step is always a gradient step */
    
    if (newton_active) {
      
      if (firsttime) {
	firsttime = FALSE;
	eps = 0.1; 
      }
      
      
      /* build the A matrix */
      
      for (i=1; i<=n_parm; ++i) {
	for (j=1; j<=n_parm; ++j) {
	  
	  A[i][j] = dLdada[i][j];
	  
	  for (n=1; n<=n_con; ++n) {
	    A[i][j] += mult[n]*dMdada[n+(i-1)*n_con][j];
	  }
	  
	}
      }
      
      
      for (i=1+n_parm; i<=n_con+n_parm; ++i) {
	for (j=1; j<=n_parm; ++j) {
	  A[j][i] = A[i][j] = dMda[i-n_parm][j];
	}
      }
      
      
      /* build the B vector */
      
      if (n_con > 0) {
	mat_vec_mult(dMda_t,mult,B);
      }
      
      
      for (i=1; i<=n_con; ++i) {
	B[i+n_parm] = K[i];
      }
      
      /* invert the A matrix */
      
      if (!my_inv_ludcmp(A, n_con+n_parm, A_inv)) {
	rc = FALSE;
	break;
      }
      
      mat_vec_mult(A_inv,B,B);
      vec_mult_scalar(B,eps,B);
      
      for (i=1; i<=n_parm; ++i) {
	new_a[i] = a[i] + B[i];
      }
      
      for (i=1; i<=n_con; ++i) {
	new_mult[i] = mult[i] + B[n_parm+i];
      }
      
      
      
    } else {
      
      
      if (n_con > 0) {

	/* the mulitpliers are updated according:
	   mult = (dMda dMda_t)^(-1) (K/esp - dMda dLda_t)       */

	mat_mult(dMda,dMda_t,aux_mat);
      
	if (!my_inv_ludcmp(aux_mat, n_con, aux_mat)) {
	  rc = FALSE;
	  break;
	}
      
	mat_vec_mult(dMda,dLda,aux_vec);
      
	vec_mult_scalar(K,1./eps,K);
      
	vec_sub(K,aux_vec,aux_vec);
      
	mat_vec_mult(aux_mat,aux_vec,mult);

      }
      
      
      /* the update step looks the following:
	 a_new = a - eps * (dLda + mult_t * dMda)_t     */
      
      if (n_con > 0) {

	vec_mat_mult(mult,dMda,new_a);
      
	vec_add(dLda,new_a,new_a);

      } else {

	vec_equal(dLda,new_a);

      }
      
      vec_mult_scalar(new_a,eps,new_a);
      
      vec_sub(a,new_a,new_a);
      
    }
    
    
    if (count == 1 && !pending1) {
      
      last_cost  = (*f_L)(a);

      if (n_con > 0) {
	(*f_M)(a,K);
	last_cost += vec_mult_inner(K,mult);
      }
      
    } else {
    
      last_cost = cost;

    }
    
    /* calculate the updated cost */
    
    
    cost = (*f_L)(new_a);
    /*printf("   %f\n",cost);*/

    if (n_con > 0) {

      (*f_M)(new_a,K);
      
      if (newton_active) {
	cost += vec_mult_inner(K,new_mult);
      } else {
	cost += vec_mult_inner(K,mult);
      }

    }
    
    /* printf("last=%f new=%f\n",last_cost,cost); */
    
    
    /* check out whether we reduced the cost */
    
    if (cost > last_cost && fabs(cost-last_cost) > *tol) {
      
      /* reduce the gradient climbing rate: sometimes a reduction of eps
	 causes an increase in cost, thus leave an option to increase
	 eps */
      
      cost = last_cost; /* reset last_cost */
      
      
      if (pending1 && pending2) {
	
	/* this means that either increase nor decrease
	   of eps helps, ==> leave the program */
	
	rc = TRUE;
	break;
	
      } else if (pending1) {
	
	eps *= 4.0;  /* the last cutting by half did not help, thus
			multiply by 2 to get to previous value, and
			one more time by 2 to get new value */
	pending2 = TRUE;
	
      } else {
	
	eps /= 2.0;
	pending1 = TRUE;
	
      }
      
      goto AGAIN;
      
    } else {
      
      vec_equal(new_a,a);
      if (newton_active && n_con > 0) {
	vec_equal(new_mult,mult);
      }
      if (use_newton && fabs(cost-last_cost) < NEWTON_THRESHOLD) 
	newton_active = TRUE;
      
    }
    
    
  }
  
  my_free_vector(dLda,1,n_parm);
  my_free_vector(new_a,1,n_parm);
  if (n_con > 0) {
    my_free_vector(mult,1,n_con);
    my_free_matrix(dMda,1,n_con,1,n_parm);
    my_free_matrix(dMda_t,1,n_parm,1,n_con);
    my_free_vector(K,1,n_con);
    my_free_matrix(aux_mat,1,n_con,1,n_con);
    my_free_vector(aux_vec,1,n_con);
  }
  
  if (use_newton) {
    
    my_free_matrix(dLdada,1,n_parm,1,n_parm);
    my_free_matrix(A,1,n_parm+n_con,1,n_parm+n_con);
    my_free_matrix(A_inv,1,n_parm+n_con,1,n_parm+n_con);
    my_free_vector(B,1,n_parm+n_con);
    if (n_con > 0) {
      my_free_matrix(dMdada,1,n_con*n_parm,1,n_parm);
      my_free_vector(new_mult,1,n_con);
    }
    
  }
  *final_cost = cost;
  *tol = fabs(cost-last_cost);
  if (n_con > 0) {
    *err = sqrt(vec_mult_inner(K,K));
  } else {
    *err = 0.0;
  }
/*  
  printf("count=%ld  rc=%d\n",count,rc);
*/ 
  return rc;
  
}
Пример #3
0
void expm(Matrix A, Matrix B, double h) {

	static int firsttime = TRUE;
	static Matrix M;
	static Matrix M2;
	static Matrix M3;
	static Matrix D;
	static Matrix N;

	if (firsttime) {
		firsttime = FALSE;
		M = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
		M2 = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
		M3 = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
		D = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
		N = my_matrix(1,3*N_DOFS,1,3*N_DOFS);
	}

	int norm = 0;
	double c = 0.5;
	int q = 6; // uneven p-q order for Pade approx.
	int p = 1;
	int i,j,k;

	// Form the big matrix
	mat_mult_scalar(A, h, A);
	mat_equal_size(A, 2*N_DOFS, 2*N_DOFS, M);
	for (i = 1; i <= 2*N_DOFS; ++i) {
		for (j = 1; j <= N_DOFS; ++j) {
			M[i][2*N_DOFS + j] = h * B[i][j];
	    }
	}
	//print_mat("M is:\n", M);

	// scale M by power of 2 so that its norm < 1/2
	norm = (int)(log2(inf_norm(M))) + 2;
	//printf("Inf norm of M: %f \n", inf_norm(M));
	if (norm < 0)
		norm = 0;

	mat_mult_scalar(M, 1/pow(2,(double)norm), M);
	//printf("Norm of M logged, floored and 2 added is: %d\n", norm);
	//print_mat("M after scaling is:\n", M);

	for (i = 1; i <= 3*N_DOFS; i++) {
		for (j = 1; j <= 3*N_DOFS; j++) {
			N[i][j] = c * M[i][j];
			D[i][j] = -c * M[i][j];
		}
		N[i][i] = N[i][i] + 1.0;
		D[i][i] = D[i][i] + 1.0;
	}

	// set M2 equal to M
	mat_equal(M, M2);

	// start pade approximation

	for (k = 2; k <= q; k++) {
		c = c * (q - k + 1) / (double)(k * (2*q - k + 1));
		mat_mult(M,M2,M2);
		mat_mult_scalar(M2,c,M3);
		mat_add(N,M3,N);
		if (p == 1)
			mat_add(D,M3,D);
		else
			mat_sub(D,M3,D);
		p = -1 * p;
	}

	// multiply denominator with nominator i.e. D\E
	my_inv_ludcmp(D, 3*N_DOFS, D);
	mat_mult(D,N,N);

	// undo scaling by repeated squaring
	for (k = 1; k <= norm; k++)
		mat_mult(N,N,N);

	// get the matrices out
	// read off the entries
	for (i = 1; i <= 2*N_DOFS; i++) {
		for (j = 1; j <= 2*N_DOFS; j++) {
			A[i][j] = N[i][j];
		}
		for (j = 1; j <= N_DOFS; j++) {
			B[i][j] = N[i][2*N_DOFS + j];
		}
	}
}