test_IPKF

Dependencies:   mbed

source/kinematic.c

Committer:
LudovicoDani
Date:
2016-04-20
Revision:
0:fb6e494a7656

File content as of revision 0:fb6e494a7656:

#include "kinematic.h"
#include <stdio.h>

/**
 * @defgroup MACRO_GROUP
 *
 * @{
 */
 /**
  * @brief
  * Macro used to build the jacobian 
  * matrix column by column 
  */
#define BUILD_JACOBIAN(J, p, z, i) \
	J->element[0][i]=p.element[0][0];\
    J->element[1][i]=p.element[1][0];\
    J->element[2][i]=p.element[2][0];\
	J->element[3][i]=z.element[0][0];\
	J->element[4][i]=z.element[1][0];\
	J->element[5][i]=z.element[2][0];

/**
  * @brief
  * Macro used to check if the joint angle 
  * are in the interval between -pi and pi
  */
#define	CHECK_ANGLE()\
    while(joint->element[0][0] > PI)\
        joint->element[0][0] = joint->element[0][0] - 2*PI;\
    while(joint->element[0][0] < -PI)\
        joint->element[0][0] = joint->element[0][0] + 2*PI;\
		\
    while(joint->element[1][0] > PI)\
        joint->element[1][0] = joint->element[1][0] - 2*PI;\
    while(joint->element[1][0] < -PI)\
        joint->element[1][0] = joint->element[1][0] + 2*PI;\
		\
	while(joint->element[2][0] > PI)\
        joint->element[2][0] = joint->element[2][0] - 2*PI;\
    while(joint->element[2][0] < -PI)\
        joint->element[2][0] = joint->element[2][0] + 2*PI;\
		\
    while(joint->element[3][0] > PI)\
        joint->element[3][0] = joint->element[3][0] - 2*PI;\
    while(joint->element[3][0] < -PI)\
        joint->element[3][0] = joint->element[3][0] + 2*PI;\
		\
	while(joint->element[4][0] > PI)\
        joint->element[4][0] = joint->element[4][0] - 2*PI;\
    while(joint->element[4][0] < -PI)\
        joint->element[4][0] = joint->element[4][0] + 2*PI;\
		\
    while(joint->element[5][0] > PI)\
        joint->element[5][0] = joint->element[5][0] - 2*PI;\
    while(joint->element[5][0] < -PI)\
        joint->element[5][0] = joint->element[5][0] + 2*PI;\
 /** @} */

void DHP_update(DHP* dhp,matrix* joints)
{
    dhp[0].d = l1;
    dhp[0].theta = joints->element[0][0];
    dhp[0].a = 0;
    dhp[0].alpha = PI/2;

    dhp[1].d = 0;
    dhp[1].theta = joints->element[1][0];
    dhp[1].a = l2;
    dhp[1].alpha = 0;

    dhp[2].d = 0;
    dhp[2].theta = joints->element[2][0];
    dhp[2].a = l3;
    dhp[2].alpha = 0;

    dhp[3].d = 0;
    dhp[3].theta = joints->element[3][0];
    dhp[3].a= l4;
    dhp[3].alpha = -PI/2;

    dhp[4].d = 0;
    dhp[4].theta = joints->element[4][0] + PI/2;
    dhp[4].a = 0;
    dhp[4].alpha = PI/2;

    dhp[5].d = l5;
    dhp[5].theta = joints->element[5][0];
    dhp[5].a = 0;
    dhp[5].alpha = 0;

    return;
}

void DH_Transf(DHP* dhp, matrix* T)
{

    T->element[0][0] = (float)cos(dhp->theta);
    T->element[0][1] = (float)(-sin(dhp->theta)*cos(dhp->alpha));
    T->element[0][2] = (float)(sin(dhp->theta)*sin(dhp->alpha));
    T->element[0][3] = (float)(dhp->a * cos(dhp->theta));

    T->element[1][0] = (float)sin(dhp->theta);
    T->element[1][1] = (float)(cos(dhp->theta)*cos(dhp->alpha));
    T->element[1][2] = (float)(-cos(dhp->theta)*sin(dhp->alpha));
    T->element[1][3] = (float)(dhp->a * sin(dhp->theta));

    T->element[2][0] = 0;
    T->element[2][1] = (float)sin(dhp->alpha);
    T->element[2][2] = (float)cos(dhp->alpha);
    T->element[2][3] = dhp->d;

    T->element[3][0] = 0;
    T->element[3][1] = 0;
    T->element[3][2] = 0;
    T->element[3][3] = 1;

    return;
}

void DPKF(matrix* joint, matrix* p)
{

    int val = 0;
    matrix T01;
    matrix T12;
    matrix T23;
    matrix T34;
    matrix T45;
    matrix T56;
    matrix T_TCP;

    DHP dhp[6];

    /**< initialization of matrices */
    InitMatrix(&T01,4,4);
    InitMatrix(&T12,4,4);
    InitMatrix(&T23,4,4);
    InitMatrix(&T34,4,4);
    InitMatrix(&T45,4,4);
    InitMatrix(&T56,4,4);
    InitMatrix(&T_TCP,4,4);

    /**<  DHP initialization*/
    DHP_update(dhp, joint);

    /**< Homogeneous transformations */
    DH_Transf(&dhp[0], &T01);
    DH_Transf(&dhp[1], &T12);
    DH_Transf(&dhp[2], &T23);
    DH_Transf(&dhp[3], &T34);
    DH_Transf(&dhp[4], &T45);
    DH_Transf(&dhp[5], &T56);

    /**<  Tool center point transformation*/
    val = MxM(&T01, &T12, &T_TCP);
    val += MxM(&T_TCP, &T23, &T_TCP);
    val += MxM(&T_TCP, &T34, &T_TCP);
    val += MxM(&T_TCP, &T45, &T_TCP);
    val += MxM(&T_TCP, &T56, &T_TCP);
    
    if (val!=0)
    {
    	return;
    }

    /**< pose extrapolation*/
    p->element[0][0] = T_TCP.element[0][3];
    p->element[1][0] = T_TCP.element[1][3];
    p->element[2][0] = T_TCP.element[2][3];
    p->element[3][0] = (float)atan2(T_TCP.element[2][1],T_TCP.element[2][2]);
    p->element[4][0] = (float)atan2(-T_TCP.element[2][0],sin(p->element[3][0])*T_TCP.element[2][1] + cos(p->element[3][0])*T_TCP.element[2][2]);
    p->element[5][0] = (float)atan2(-cos(p->element[3][0])*T_TCP.element[0][1]+ sin(p->element[3][0]) * T_TCP.element[0][2],cos(p->element[3][0]) * T_TCP.element[1][1]- sin(p->element[3][0]) * T_TCP.element[1][2]);


    /**<  matrix delation*/
    DeleteMatrix(&T01);
    DeleteMatrix(&T12);
    DeleteMatrix(&T23);
    DeleteMatrix(&T34);
    DeleteMatrix(&T45);
    DeleteMatrix(&T56);
    DeleteMatrix(&T_TCP);

    return;
}

void JacobianG(matrix* joint, matrix* Jg, matrix* T_TCP)
{
    int i = 0;
    DHP dhp[6];

    matrix T01;
    matrix T12;
    matrix T23;
    matrix T34;
    matrix T45;
    matrix T56;

    matrix p0;
    matrix p1;
    matrix p2;
    matrix p3;
    matrix p4;
    matrix p5;
    matrix p_TCP;

    matrix z0;
    matrix z1;
    matrix z2;
    matrix z3;
    matrix z4;
    matrix z5;

    matrix CrossP;
    //p is matrix of RF origin positions
    //z is matrix of k axis for each RF

    /*Matrix creation*/
    InitMatrix(&T01,4,4);
    InitMatrix(&T12,4,4);
    InitMatrix(&T23,4,4);
    InitMatrix(&T34,4,4);
    InitMatrix(&T45,4,4);
    InitMatrix(&T56,4,4);

    InitMatrix(&p0,3,1);
    InitMatrix(&p1,3,1);
    InitMatrix(&p2,3,1);
    InitMatrix(&p3,3,1);
    InitMatrix(&p4,3,1);
    InitMatrix(&p5,3,1);
    InitMatrix(&p_TCP,3,1);

    InitMatrix(&z0,3,1);
    InitMatrix(&z1,3,1);
    InitMatrix(&z2,3,1);
    InitMatrix(&z3,3,1);
    InitMatrix(&z4,3,1);
    InitMatrix(&z5,3,1);

    InitMatrix(&CrossP,3,1);


    /**<compute dh_par */
    DHP_update(dhp,joint);

    /**>compute T from dhp*/
    DH_Transf(&dhp[0], &T01);
    DH_Transf(&dhp[1], &T12);
    DH_Transf(&dhp[2], &T23);
    DH_Transf(&dhp[3], &T34);
    DH_Transf(&dhp[4], &T45);
    DH_Transf(&dhp[5], &T56);

    /* R0 - JOINT 1
    distance between Global RF origin & R0 origin + R0 k axis */
    p0.element[0][0] = 0;
    p0.element[1][0] = 0;
    p0.element[2][0] = 0;

    z0.element[0][0] = 0;
    z0.element[1][0] = 0;
    z0.element[2][0] = 1;


    /* R1 -JOINT 2
    distance between Global RF origin & R1 origin + R1 k axis */
    for(i = 0; i < 3; i++) {
        p1.element[i][0] = T01.element[i][3];
    }
    // z1 = omo2rot(T02)*[0;0;1];
    for(i = 0; i < 3; i++) {
        z1.element[i][0] = T01.element[i][2];
    }

    /* R2 -JOINT 3
    distance between Global RF origin & R2 origin + R2 k axis */
    MxM(&T01, &T12, T_TCP);
    for(i = 0; i < 3; i++) {
        p2.element[i][0] = T_TCP->element[i][3];
    }
    // z2 = omo2rot(T02)*[0;0;1];
    for(i=0; i<3; i++) {
        z2.element[i][0] = T_TCP->element[i][2];
    }

    /* R3 -JOINT 4
    distance between Global RF origin & R3 origin + R3 k axis */
    MxM(T_TCP, &T23, T_TCP);
    for(i = 0; i < 3; i++) {
        p3.element[i][0] = T_TCP->element[i][3];
    }
    // z3 = omo2rot(T03)*[0;0;1];
    for(i = 0; i < 3; i++) {
        z3.element[i][0] = T_TCP->element[i][2];
    }


    /* R4 -JOINT 5
    distance between Global RF origin & R4 origin + R4 k axis */
    MxM(T_TCP, &T34, T_TCP);
    for(i = 0; i < 3; i++) {
        p4.element[i][0] = T_TCP->element[i][3];
    }
    // z4 = omo2rot(T03)*[0;0;1];
    for(i = 0; i < 3; i++) {
        z4.element[i][0] = T_TCP->element[i][2];
    }

    /* R5 -JOINT 6
    distance between Global RF origin & R5 origin + R5 k axis */
    MxM(T_TCP, &T45, T_TCP);
    for(i = 0; i < 3; i++) {
        p5.element[i][0] = T_TCP->element[i][3];
    }
    // z5 = omo2rot(T03)*[0;0;1];
    for(i = 0; i < 3; i++) {
        z5.element[i][0] = T_TCP->element[i][2];
    }

    MxM(T_TCP, &T56, T_TCP);
    for(i = 0; i < 3; i++) {
        p_TCP.element[i][0] = T_TCP->element[i][3];
    }

    /**compute distance from TCP*/

    Sub(&p_TCP, &p0, &p0);
    Sub(&p_TCP, &p1, &p1);
    Sub(&p_TCP, &p2, &p2);
    Sub(&p_TCP, &p3, &p3);
    Sub(&p_TCP, &p4, &p4);
    Sub(&p_TCP, &p5, &p5);

    /**compute jacobian*/

    CrossProd(&z0, &p0, &CrossP);

    BUILD_JACOBIAN(Jg, CrossP, z0, 0)


    CrossProd(&z1, &p1, &CrossP);

    BUILD_JACOBIAN(Jg, CrossP, z1, 1)


    CrossProd(&z2, &p2, &CrossP);

    BUILD_JACOBIAN(Jg, CrossP, z2, 2)


    CrossProd(&z3, &p3, &CrossP);

    BUILD_JACOBIAN(Jg, CrossP, z3, 3)


    CrossProd(&z4, &p4, &CrossP);

    BUILD_JACOBIAN(Jg, CrossP, z4, 4)



    CrossProd(&z5, &p5, &CrossP);

    BUILD_JACOBIAN(Jg, CrossP, z5, 5)


    DeleteMatrix(&p0);
    DeleteMatrix(&p1);
    DeleteMatrix(&p2);
    DeleteMatrix(&p3);
    DeleteMatrix(&p4);
    DeleteMatrix(&p5);
    DeleteMatrix(&p_TCP);

    DeleteMatrix(&z0);
    DeleteMatrix(&z1);
    DeleteMatrix(&z2);
    DeleteMatrix(&z3);
    DeleteMatrix(&z4);
    DeleteMatrix(&z5);

    DeleteMatrix(&T01);
    DeleteMatrix(&T12);
    DeleteMatrix(&T23);
    DeleteMatrix(&T34);
    DeleteMatrix(&T45);
    DeleteMatrix(&T56);

    DeleteMatrix(&CrossP);

    return;
}

void JacobianA(matrix* joint, matrix* Ja)
{

    int i = 0;
    int j = 0;

    matrix Jg;
    matrix M;
    matrix Ttcp;
    matrix JgA;
    matrix JaA;

    matrix p;

    InitMatrix(&Jg, Ja->row, Ja->col );
    InitMatrix(&M, 3 ,3 );
    InitMatrix(&JgA, 3, 6 );
    InitMatrix(&JaA, 3, 6 );
    InitMatrix(&Ttcp, 4, 4 );
    InitMatrix(&p, 6, 1);

    JacobianG(joint, &Jg, &Ttcp);

    p.element[0][0] = Ttcp.element[0][3];
    p.element[1][0] = Ttcp.element[1][3];
    p.element[2][0] = Ttcp.element[2][3];
    p.element[3][0] = (float)atan2(Ttcp.element[2][1],Ttcp.element[2][2]);
    p.element[4][0] = (float)atan2(-Ttcp.element[2][0],sin(p.element[3][0])*Ttcp.element[2][1]+cos(p.element[3][0])*Ttcp.element[2][2]);
    p.element[5][0] = (float)atan2(-cos(p.element[3][0])*Ttcp.element[0][1]+ sin(p.element[3][0])*Ttcp.element[0][2],cos(p.element[3][0])*Ttcp.element[1][1]-sin(p.element[3][0])*Ttcp.element[1][2]);


    // Transformation matrix
    M.element[0][0] = (float)(cos(p.element[5][0])/cos(p.element[4][0]));
    M.element[0][1] = (float)(sin(p.element[5][0])/cos(p.element[4][0]));
    M.element[0][2] = 0;

    M.element[1][0] = (float)-sin(p.element[5][0]);
    M.element[1][1] = (float)cos(p.element[5][0]);
    M.element[1][2] = 0;

    M.element[2][0] = (float)(cos(p.element[5][0])*sin(p.element[4][0])/cos(p.element[4][0]));
    M.element[2][1] = (float)(-sin(p.element[4][0])*sin(p.element[5][0])/cos(p.element[4][0]));
    M.element[2][2] = 1;


    for(i = 0; i < JgA.row; i++) {
        for(j = 0; j< JgA.col; j++) {
            JgA.element[i][j] = Jg.element[i+3][j];
        }
    }

    MxM(&M, &JgA, &JaA);


    for(i = 0; i < JaA.row; i++) {
        for(j = 0; j< JaA.col; j++) {
            Ja->element[i][j] = Jg.element[i][j];
        }
    }

    for(i = 0; i < JaA.row; i++) {
        for(j = 0; j< JaA.col; j++) {
            Ja->element[i+3][j] = JaA.element[i][j];
        }
    }

    DeleteMatrix(&M);
    DeleteMatrix(&Jg);
    DeleteMatrix(&JgA);
    DeleteMatrix(&JaA);
    DeleteMatrix(&Ttcp);
    DeleteMatrix(&p);

    return;
}

int IPKF (matrix* p, matrix* joint)
{

    float sentinel = 2;
    float sum = 0.0;
    float error_G = 0.5;
    float error_N = (float)0.0001;
    float alpha = (float)0.27; //after several trials
    int c = 0;
    int i = 0;


    DHP dhp[6];

    matrix f;//computed position through Direct Kinematics
    matrix J;
    matrix delta_p;
    matrix delta_q;
    matrix inv_J;


    InitMatrix(&f, 6, 1);
    InitMatrix(&J, 6, 6);
    InitMatrix(&inv_J, 6, 6);
    InitMatrix(&delta_q, 6,1);
    InitMatrix(&delta_p, 6,1);


    /*gradient method*/
    while(sentinel >= error_G) {
//
        /*compute the direct kinematics*/
        DPKF(joint, &f);

        /*compute dh_par*/
        DHP_update(dhp,joint);

        /*compute jacobian*/
        JacobianA(joint, &J);// to be defined

        /*compute the next value of angle*/
        Traspost(&J, &J); //Transpose of J saved in JT
        axM(&J, alpha, &J);// Transpose of J (J) multiplied by alpha and saved in J

        /*subtraction of two pose objects into matrix*/
        Sub(p , &f, &delta_p);

        //alpha*J'*(p-f)
        MxM(&J, &delta_p, &delta_q);

        Sum(joint, &delta_q, joint);

        CHECK_ANGLE()

        c = c+1;

        /*if the gradient method does not converge break the cycle*/
        if (c > 1000) {
            break;
        }

        /* norm of p_minus_f*/

        for(i=0; i<6; i++) {
            sum += (delta_p.element[i][0] * delta_p.element[i][0]);
        }
        sentinel = (float)sqrt(sum);
        sum = 0;
    }

//printf("c = %d\n", c);

    /*Newton method*/
    while (sentinel >= error_N) {

        /*compute the direct kinematics*/
        DPKF(joint,&f);

        /*compute dh_par*/
        DHP_update(dhp,joint);

        /*compute jacobian*/
        JacobianA(joint, &J);// to be defined

        /*compute the next value of angle*/

        //check if Jacobian is invertible
        if(Inv(&J, &inv_J) == 6 ) {
            break;
            //printf("error due to jacobuan singularities");
        }

        Sub(p, &f, &delta_p);

        MxM(&inv_J, &delta_p, &delta_q);

        //q = q +  J \ (p-f);
        Sum(joint, &delta_q, joint);

        CHECK_ANGLE();

        c = c+1;

        /*if the newton method does not converge break the cycle*/
        if (c > 2000) {
            break;
        }
        /* norm of p_minus_f*/
        sum = 0.0;

        for(i=0; i<6; i++) {
            sum += delta_p.element[i][0] * delta_p.element[i][0];
        }
        sentinel = (float)sqrt(sum);
    }
    
    DeleteMatrix(&f);
    DeleteMatrix(&J);
    DeleteMatrix(&delta_p);
    DeleteMatrix(&delta_q);
    DeleteMatrix(&inv_J);
    //printf("c = %d\n",c);
	if(c >=2000)
	{
		return 1;
	}
	else
    { 
    	return 0;
    }
}

void Print_DHP(DHP* dhp)
{
    printf("d = %f\n",dhp->d);
    printf("theta = %f\n",dhp->theta);
    printf("a = %f\n",dhp->a);
    printf("alpha = %f\n",dhp->alpha);
    printf("\n");
}