int main(int argc, char** argv)
{
    IKREAL_TYPE eerot[9],eetrans[3];

#if IK_VERSION > 54
    // for IKFast 56,61
    unsigned int num_of_joints = GetNumJoints();
    unsigned int num_free_parameters = GetNumFreeParameters();
#else
    // for IKFast 54
    unsigned int num_of_joints = getNumJoints();
    unsigned int num_free_parameters = getNumFreeParameters();
#endif
 
    std::string cmd;
    if (argv[1]) cmd = argv[1];

    //printf("command: %s \n\n", cmd.c_str() );

    if (cmd.compare("ik") == 0) // ik mode
    {
        if( argc == 1+7+num_free_parameters+1 )  // ik, given translation vector and quaternion pose
        {
#if IK_VERSION > 54
            // for IKFast 56,61
            IkSolutionList<IKREAL_TYPE> solutions;
#else
            // for IKFast 54
            std::vector<IKSolution> vsolutions;
#endif
            std::vector<IKREAL_TYPE> vfree(num_free_parameters);

            eetrans[0] = atof(argv[2]);
            eetrans[1] = atof(argv[3]);
            eetrans[2] = atof(argv[4]);

            // Convert input effector pose, in w x y z quaternion notation, to rotation matrix. 
            // Must use doubles, else lose precision compared to directly inputting the rotation matrix.
            double qw = atof(argv[5]);
            double qx = atof(argv[6]);
            double qy = atof(argv[7]);
            double qz = atof(argv[8]);
            const double n = 1.0f/sqrt(qx*qx+qy*qy+qz*qz+qw*qw);
            qw *= n;
            qx *= n;
            qy *= n;
            qz *= n;
            eerot[0] = 1.0f - 2.0f*qy*qy - 2.0f*qz*qz;  eerot[1] = 2.0f*qx*qy - 2.0f*qz*qw;         eerot[2] = 2.0f*qx*qz + 2.0f*qy*qw;
            eerot[3] = 2.0f*qx*qy + 2.0f*qz*qw;         eerot[4] = 1.0f - 2.0f*qx*qx - 2.0f*qz*qz;  eerot[5] = 2.0f*qy*qz - 2.0f*qx*qw;
            eerot[6] = 2.0f*qx*qz - 2.0f*qy*qw;         eerot[7] = 2.0f*qy*qz + 2.0f*qx*qw;         eerot[8] = 1.0f - 2.0f*qx*qx - 2.0f*qy*qy;

            // For debugging, output the matrix
            
            for (unsigned char i=0; i<=8; i++)
            {   // detect -0.0 and replace with 0.0
                if ( ((int&)(eerot[i]) & 0xFFFFFFFF) == 0) eerot[i] = 0.0;
            }
            printf("     Rotation     %f   %f   %f  \n", eerot[0], eerot[1], eerot[2] );
            printf("                  %f   %f   %f  \n", eerot[3], eerot[4], eerot[5] );
            printf("                  %f   %f   %f  \n", eerot[6], eerot[7], eerot[8] );
            printf("\n");
            

            for(std::size_t i = 0; i < vfree.size(); ++i)
                vfree[i] = atof(argv[13+i]);

#if IK_VERSION > 54
            // for IKFast 56,61
            bool bSuccess = ComputeIk(eetrans, eerot, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
#else
            // for IKFast 54
            bool bSuccess = ik(eetrans, eerot, vfree.size() > 0 ? &vfree[0] : NULL, vsolutions);
#endif
            if( !bSuccess ) {
                fprintf(stderr,"Failed to get ik solution\n");
                //return -1;
            }

#if IK_VERSION > 54
            // for IKFast 56,61
            unsigned int num_of_solutions = (int)solutions.GetNumSolutions();
#else
            // for IKFast 54
            unsigned int num_of_solutions = (int)vsolutions.size();
#endif
            printf("Found %d ik solutions:\n", num_of_solutions ); 

            std::vector<IKREAL_TYPE> solvalues(num_of_joints);
            for(std::size_t i = 0; i < num_of_solutions; ++i) {
#if IK_VERSION > 54
                // for IKFast 56,61
                const IkSolutionBase<IKREAL_TYPE>& sol = solutions.GetSolution(i);
                int this_sol_free_params = (int)sol.GetFree().size(); 
#else
                // for IKFast 54
                int this_sol_free_params = (int)vsolutions[i].GetFree().size();
#endif
                printf("sol%d (free=%d): ", (int)i, this_sol_free_params );
                std::vector<IKREAL_TYPE> vsolfree(this_sol_free_params);

#if IK_VERSION > 54
                // for IKFast 56,61
                sol.GetSolution(&solvalues[0],vsolfree.size()>0?&vsolfree[0]:NULL);
#else
                // for IKFast 54
                vsolutions[i].GetSolution(&solvalues[0],vsolfree.size()>0?&vsolfree[0]:NULL);
#endif
                for( std::size_t j = 0; j < solvalues.size(); ++j)
                    printf("%.15f, ", solvalues[j]);
                printf("\n");
            }

        } 
        else if( argc == 1+12+num_free_parameters+1 )  // ik, given rotation-translation matrix
        {
#if IK_VERSION > 54
            // for IKFast 56,61
            IkSolutionList<IKREAL_TYPE> solutions;
#else
            // for IKFast 54
            std::vector<IKSolution> vsolutions;
#endif
            std::vector<IKREAL_TYPE> vfree(num_free_parameters);

            eerot[0] = atof(argv[2]);  eerot[1] = atof(argv[3]);  eerot[2] = atof(argv[4]);  eetrans[0] = atof(argv[5]);
            eerot[3] = atof(argv[6]);  eerot[4] = atof(argv[7]);  eerot[5] = atof(argv[8]);  eetrans[1] = atof(argv[9]);
            eerot[6] = atof(argv[10]); eerot[7] = atof(argv[11]); eerot[8] = atof(argv[12]); eetrans[2] = atof(argv[13]);

            for(std::size_t i = 0; i < vfree.size(); ++i)
                vfree[i] = atof(argv[14+i]);

            printf("translation: \n");
            for (unsigned int i = 0; i < 3; i++) {
                printf("%lf ", eetrans[i]);
            }
            printf("\n");
            printf("rotation matix: \n");
            for (unsigned int i = 0; i < 9; i++) {
                printf("%lf%s", eerot[i], (i % 3 == 2)?"\n":" ");
            }
            printf("\n");

            printf("vfree:\n");
            for(std::size_t i = 0; i < vfree.size(); ++i)
                printf("%lf ", vfree[i]);
            printf("\n");

#if IK_VERSION > 54
            // for IKFast 56,61
            bool bSuccess = ComputeIk(eetrans, eerot, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
#else
            // for IKFast 54
            bool bSuccess = ik(eetrans, eerot, vfree.size() > 0 ? &vfree[0] : NULL, vsolutions);
#endif
            if( !bSuccess ) {
                fprintf(stderr,"Failed to get ik solution\n");
                return -1;
            }

#if IK_VERSION > 54
            // for IKFast 56,61
            unsigned int num_of_solutions = (int)solutions.GetNumSolutions();
#else
            // for IKFast 54
            unsigned int num_of_solutions = (int)vsolutions.size();
#endif
            printf("Found %d ik solutions:\n", num_of_solutions ); 

            std::vector<IKREAL_TYPE> solvalues(num_of_joints);
            for(std::size_t i = 0; i < num_of_solutions; ++i) {
#if IK_VERSION > 54
                // for IKFast 56,61
                const IkSolutionBase<IKREAL_TYPE>& sol = solutions.GetSolution(i);
                int this_sol_free_params = (int)sol.GetFree().size(); 
#else
                // for IKFast 54
                int this_sol_free_params = (int)vsolutions[i].GetFree().size();
#endif
                printf("sol%d (free=%d): ", (int)i, this_sol_free_params );
                std::vector<IKREAL_TYPE> vsolfree(this_sol_free_params);

#if IK_VERSION > 54
                // for IKFast 56,61
                sol.GetSolution(&solvalues[0],vsolfree.size()>0?&vsolfree[0]:NULL);
#else
                // for IKFast 54
                vsolutions[i].GetSolution(&solvalues[0],vsolfree.size()>0?&vsolfree[0]:NULL);
#endif
                for( std::size_t j = 0; j < solvalues.size(); ++j)
                    printf("%.15f, ", solvalues[j]);
                printf("\n");
            }

        }
        else {
            printf("\n "
                   "Usage: \n\n " 
                   "         ./compute ik  t0 t1 t2  qw qi qj qk  free0 ...\n\n "
                   "         Returns the ik solutions given the transformation of the end effector specified by \n "
                   "         a 3x1 translation (tX), and a 1x4 quaternion (w + i + j + k). \n "
                   "         There are %d free parameters that have to be specified.\n\n", num_free_parameters );
            printf(" \n "
                   "         ./compute ik  r00 r01 r02 t0  r10 r11 r12 t1  r20 r21 r22 t2  free0 ...\n\n "
                   "         Returns the ik solutions given the transformation of the end effector specified by \n "
                   "         a 3x3 rotation R (rXX), and a 3x1 translation (tX). \n "
                   "         There are %d free parameters that have to be specified.\n\n", num_free_parameters );
            return 1;

        }
    } // endif ik mode

    else if (cmd.compare("fk") == 0) // fk mode
    {
        if( argc != num_of_joints+2 ) {
            printf("\n "
                   "Usage: \n\n "
                   "         ./compute fk j0 j1 ... j%d \n\n"
                   "         Returns the forward kinematic solution given the joint angles (in radians). \n\n", num_of_joints-1 );
            return 1;
        }
        printf("\n\n");

        // Put input joint values into array
        IKREAL_TYPE joints[num_of_joints];
        for (unsigned int i=0; i<num_of_joints; i++)
        {
            joints[i] = atof(argv[i+2]);
        }

#if IK_VERSION > 54
        // for IKFast 56,61
        ComputeFk(joints, eetrans, eerot); // void return
#else
        // for IKFast 54
        fk(joints, eetrans, eerot); // void return
#endif
        printf("Found fk solution for end frame: \n\n");

        printf("  Translation:  x: %f  y: %f  z: %f  \n", eetrans[0], eetrans[1], eetrans[2] );
        printf("\n");
        printf("     Rotation     %f   %f   %f  \n", eerot[0], eerot[1], eerot[2] );
        printf("       Matrix:    %f   %f   %f  \n", eerot[3], eerot[4], eerot[5] );
        printf("                  %f   %f   %f  \n", eerot[6], eerot[7], eerot[8] );
        printf("\n");

        // Display equivalent Euler angles
        float yaw;
        float pitch;
        float roll;
        if ( eerot[5] > 0.998 || eerot[5] < -0.998 ) { // singularity
            yaw = IKatan2( -eerot[6], eerot[0] );
            pitch = 0;
        } else {
            yaw = IKatan2( eerot[2], eerot[8] );
            pitch = IKatan2( eerot[3], eerot[4] );
        }
        roll = IKasin( eerot[5] );
        printf(" Euler angles: \n");
        printf("       Yaw:   %f    ", yaw ); printf("(1st: rotation around vertical blue Z-axis in ROS Rviz) \n");
        printf("       Pitch: %f  \n", pitch ); 
        printf("       Roll:  %f  \n", roll ); 
        printf("\n");

        // Convert rotation matrix to quaternion (Daisuke Miyazaki)
        float q0 = ( eerot[0] + eerot[4] + eerot[8] + 1.0f) / 4.0f;
        float q1 = ( eerot[0] - eerot[4] - eerot[8] + 1.0f) / 4.0f;
        float q2 = (-eerot[0] + eerot[4] - eerot[8] + 1.0f) / 4.0f;
        float q3 = (-eerot[0] - eerot[4] + eerot[8] + 1.0f) / 4.0f;
        if(q0 < 0.0f) q0 = 0.0f;
        if(q1 < 0.0f) q1 = 0.0f;
        if(q2 < 0.0f) q2 = 0.0f;
        if(q3 < 0.0f) q3 = 0.0f;
        q0 = sqrt(q0);
        q1 = sqrt(q1);
        q2 = sqrt(q2);
        q3 = sqrt(q3);
        if(q0 >= q1 && q0 >= q2 && q0 >= q3) {
            q0 *= +1.0f;
            q1 *= SIGN(eerot[7] - eerot[5]);
            q2 *= SIGN(eerot[2] - eerot[6]);
            q3 *= SIGN(eerot[3] - eerot[1]);
        } else if(q1 >= q0 && q1 >= q2 && q1 >= q3) {
            q0 *= SIGN(eerot[7] - eerot[5]);
            q1 *= +1.0f;
            q2 *= SIGN(eerot[3] + eerot[1]);
            q3 *= SIGN(eerot[2] + eerot[6]);
        } else if(q2 >= q0 && q2 >= q1 && q2 >= q3) {
            q0 *= SIGN(eerot[2] - eerot[6]);
            q1 *= SIGN(eerot[3] + eerot[1]);
            q2 *= +1.0f;
            q3 *= SIGN(eerot[7] + eerot[5]);
        } else if(q3 >= q0 && q3 >= q1 && q3 >= q2) {
            q0 *= SIGN(eerot[3] - eerot[1]);
            q1 *= SIGN(eerot[6] + eerot[2]);
            q2 *= SIGN(eerot[7] + eerot[5]);
            q3 *= +1.0f;
        } else {
            printf("Error while converting to quaternion! \n");
        }
        float r = NORM(q0, q1, q2, q3);
        q0 /= r;
        q1 /= r;
        q2 /= r;
        q3 /= r;
        printf("  Quaternion:  %f   %f   %f   %f   \n", q0, q1, q2, q3 );
        printf("               ");
        // print quaternion with convention and +/- signs such that it can be copy-pasted into WolframAlpha.com
        printf("%f ", q0);
        if (q1 > 0) printf("+ %fi ", q1); else if (q1 < 0) printf("- %fi ", -q1); else printf("+ 0.00000i ");
        if (q2 > 0) printf("+ %fj ", q2); else if (q2 < 0) printf("- %fj ", -q2); else printf("+ 0.00000j ");
        if (q3 > 0) printf("+ %fk ", q3); else if (q3 < 0) printf("- %fk ", -q3); else printf("+ 0.00000k ");
        printf("  (alternate convention) \n");
        printf("\n\n");


    }
    else if (cmd.compare("iktiming") == 0) // generate random ik and check time performance
    {
        if( argc != 2 ) {
            printf("\n "
                   "Usage: \n\n "
                   "         ./compute iktiming \n\n"
                   "         For fixed number of iterations, generates random joint angles, then  \n"
                   "         calculates fk, calculates ik, measures average time taken. \n\n", num_of_joints-1 );
            return 1;
        }
        printf("\n\n");

#if IK_VERSION > 54
        // for IKFast 56,61
        IkSolutionList<IKREAL_TYPE> solutions;
#else
        // for IKFast 54
        std::vector<IKSolution> vsolutions;
#endif
        std::vector<IKREAL_TYPE> vfree(num_free_parameters);

        //for(std::size_t i = 0; i < vfree.size(); ++i)
        //    vfree[i] = atof(argv[13+i]);

        srand( (unsigned)time(0) ); // seed random number generator
        float min = -3.14;
        float max = 3.14;
        float rnd;

        IKREAL_TYPE joints[num_of_joints];

        timespec start_time, end_time;
        unsigned int elapsed_time = 0;
        unsigned int sum_time = 0;
        unsigned int fail_count = 0;

#if IK_VERSION > 54
        // for IKFast 56,61
        unsigned int num_of_tests = 10; 
#else
        // for IKFast 54
        unsigned int num_of_tests = 100000; 
#endif

        for (unsigned int i=0; i < num_of_tests; i++)
        {
            // Measure avg time for whole process
            //clock_gettime(CLOCK_REALTIME, &start_time); 

            // Put random joint values into array
            for (unsigned int i=0; i<num_of_joints; i++)
            {
                float rnd = (float)rand() / (float)RAND_MAX;
                joints[i] = min + rnd * (max - min);
            }
            /*
            printf("Joint angles:  ");
            for (unsigned int i=0; i<num_of_joints; i++)
            {
                printf("%f  ", joints[i] );
            }
            printf("\n");
            */

#if IK_VERSION > 54
            // for IKFast 56,61
            ComputeFk(joints, eetrans, eerot); // void return
#else
            // for IKFast 54
            fk(joints, eetrans, eerot); // void return
#endif

            // Measure avg time for IK
            clock_gettime(CLOCK_REALTIME, &start_time);
#if IK_VERSION > 54
            // for IKFast 56,61
            vfree[0] = 5;
           if (!ComputeIk(eetrans, eerot, vfree.size() > 0 ? &vfree[0] : NULL, solutions)) {
            fail_count++;
           } else {
            printf("joint angles: \n");
            for (unsigned int i=0; i<num_of_joints; i++)
            {
               printf("%lf ", joints[i]);
            }
            printf("\n");

            printf("translation: \n");
            for (unsigned int i = 0; i < 3; i++) {
                printf("%lf ", eetrans[i]);
            }
            printf("\n");
            printf("rotation matix: \n");
            for (unsigned int i = 0; i < 9; i++) {
                printf("%lf%s", eerot[i], (i % 3 == 2)?"\n":" ");
            }
            printf("\n");

            /*unsigned int num_of_solutions = (int)solutions.GetNumSolutions();
            printf("Found %d ik solutions:\n", num_of_solutions ); 

            std::vector<IKREAL_TYPE> solvalues(num_of_joints);
            for(std::size_t i = 0; i < num_of_solutions; ++i) {
                const IkSolutionBase<IKREAL_TYPE>& sol = solutions.GetSolution(i);
                int this_sol_free_params = (int)sol.GetFree().size(); 
                printf("sol%d (free=%d): ", (int)i, this_sol_free_params );
                std::vector<IKREAL_TYPE> vsolfree(this_sol_free_params);

                sol.GetSolution(&solvalues[0],vsolfree.size()>0?&vsolfree[0]:NULL);
                for( std::size_t j = 0; j < solvalues.size(); ++j)
                    printf("%.15f, ", solvalues[j]);
                printf("\n");
            }*/
           }
#else
            // for IKFast 54
            ik(eetrans, eerot, vfree.size() > 0 ? &vfree[0] : NULL, vsolutions);
#endif

            /*
#if IK_VERSION > 54
            // for IKFast 56,61
            unsigned int num_of_solutions = (int)solutions.GetNumSolutions();
#else
            // for IKFast 54
            unsigned int num_of_solutions = (int)vsolutions.size();
#endif
            printf("Found %d ik solutions:\n", num_of_solutions ); 
            */

            clock_gettime(CLOCK_REALTIME, &end_time); 
            elapsed_time = (unsigned int)(end_time.tv_nsec - start_time.tv_nsec);
            sum_time += elapsed_time;
        } // endfor

        unsigned int avg_time = (unsigned int)sum_time / (unsigned int)num_of_tests; 
        printf("avg time: %f ms   over %d tests \n", (float)avg_time/1000.0, num_of_tests );
        printf("Failed of %d tests\n", fail_count);

        return 1;
  
    }
    else if (cmd.compare("iktiming2") == 0) // for fixed joint values, check time performance of ik
    {
        if( argc != 2 ) {
            printf("\n "
                   "Usage: \n\n "
                   "         ./compute iktiming2 \n\n"
                   "         For fixed number of iterations, with one set of joint variables, this  \n"
                   "         finds the ik solutions and measures the average time taken. \n\n", num_of_joints-1 );
            return 1;
        }
        printf("\n\n");

#if IK_VERSION > 54
        // for IKFast 56,61
        IkSolutionList<IKREAL_TYPE> solutions;
#else
        // for IKFast 54
        std::vector<IKSolution> vsolutions;
#endif
        std::vector<IKREAL_TYPE> vfree(num_free_parameters);

        //for(std::size_t i = 0; i < vfree.size(); ++i)
        //    vfree[i] = atof(argv[13+i]);

        IKREAL_TYPE joints[num_of_joints];

        timespec start_time, end_time;
        unsigned int elapsed_time = 0;
        unsigned int sum_time = 0;

#if IK_VERSION > 54
        // for IKFast 56,61
        unsigned int num_of_tests = 1000000; 
#else
        // for IKFast 54
        unsigned int num_of_tests = 100000; 
#endif

        // fixed rotation-translation matrix corresponding to an unusual robot pose
        eerot[0] = 0.002569;  eerot[1] = -0.658044;  eerot[2] = -0.752975;  eetrans[0] = 0.121937;
        eerot[3] = 0.001347;  eerot[4] = -0.752975;  eerot[5] = 0.658048;  eetrans[1] = -0.276022;
        eerot[6] = -0.999996; eerot[7] = -0.002705; eerot[8] = -0.001047; eetrans[2] = 0.005685;

        for (unsigned int i=0; i < num_of_tests; i++)
        {
            clock_gettime(CLOCK_REALTIME, &start_time);

#if IK_VERSION > 54
            // for IKFast 56,61
            ComputeIk(eetrans, eerot, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
#else
            // for IKFast 54
            ik(eetrans, eerot, vfree.size() > 0 ? &vfree[0] : NULL, vsolutions);
#endif

            /*
#if IK_VERSION > 54
            // for IKFast 56,61
            unsigned int num_of_solutions = (int)solutions.GetNumSolutions();
#else
            // for IKFast 54
            unsigned int num_of_solutions = (int)vsolutions.size();
#endif
            printf("Found %d ik solutions:\n", num_of_solutions ); 
            */

            clock_gettime(CLOCK_REALTIME, &end_time); 
            elapsed_time = (unsigned int)(end_time.tv_nsec - start_time.tv_nsec);
            sum_time += elapsed_time;
        } // endfor

        unsigned int avg_time = (unsigned int)sum_time / (unsigned int)num_of_tests; 
        printf("avg time: %f ms   over %d tests \n", (float)avg_time/1000.0, num_of_tests );

        return 1;

    } else {
        printf("\n"
               "Usage: \n\n");
        printf("         ./compute fk j0 j1 ... j%d \n\n"
               "         Returns the forward kinematic solution given the joint angles (in radians). \n\n", num_of_joints-1 );
        printf("\n"
               "         ./compute ik  t0 t1 t2  qw qi qj qk  free0 ... \n\n"
               "         Returns the ik solutions given the transformation of the end effector specified by \n"
               "         a 3x1 translation (tX), and a 1x4 quaternion (w + i + j + k). \n"
               "         There are %d free parameters that have to be specified. \n\n", num_free_parameters );
        printf(" \n"
               "         ./compute ik  r00 r01 r02 t0  r10 r11 r12 t1  r20 r21 r22 t2  free0 ...\n\n"
               "         Returns the ik solutions given the transformation of the end effector specified by \n"
               "         a 3x3 rotation R (rXX), and a 3x1 translation (tX). \n"
               "         There are %d free parameters that have to be specified. \n\n", num_free_parameters );
        printf("\n"
               "         ./compute iktiming \n\n"
               "         For fixed number of iterations, generates random joint angles, then \n"
               "         calculates fk, calculates ik, measures average time taken. \n\n", num_of_joints-1 );
        printf("\n"
               "         ./compute iktiming2 \n\n"
               "         For fixed number of iterations, with one set of joint variables, this \n"
               "         finds the ik solutions and measures the average time taken. \n\n", num_of_joints-1 );

        return 1;
    }

    return 0;
}
Beispiel #2
0
int main(int argc, char *argv[])
{
  if (argc < 2){
    std::cerr << "Usage:" << argv[0] << "[-checkLimits]" 
	      << std::endl;
  }

  const char *url="file:///home/kanehiro/src/HRP2/model/HRP2main.wrl";
  int arm = 0;
  bool checkLimits=false;
  bool display=true;
  for (int i=1; i<argc; i++){
    if(strcmp(argv[i], "-checkLimits")==0){
      checkLimits = true;
    }else if(strcmp(argv[i], "-nodisplay")==0){
      display = false;
    }
  }
  std::cout << "arm=" << arm << std::endl;
  std::cout << "checkLimits=" << checkLimits << std::endl;


  HumanoidBodyPtr body = HumanoidBodyPtr(new HumanoidBody());
  if (!loadHumanoidBodyFromModelLoader(body, url, argc, argv)){
    std::cerr << "failed to load model[" << url << "]" 
	      << std::endl;
    return 1;
  }

  OpenHRP::OnlineViewer_var olv;
  if (display){
    olv = hrp::getOnlineViewer(argc, argv);
    olv->load(body->name().c_str(), url);

    olv->clearLog();
  }
  
  OpenHRP::WorldState wstate;
  wstate.time = 0.0;
  wstate.characterPositions.length(1);
  setupCharacterPosition(wstate.characterPositions[0], body);
  wstate.collisions.length(1);

  hrp::JointPathPtr jp;
  if (arm == 0){
    jp = body->getJointPath(body->link("CHEST_JOINT1"),
			    body->link("RARM_JOINT5"));
  }else{
    jp = body->getJointPath(body->link("CHEST_JOINT1"),
			    body->link("LARM_JOINT5"));
  }
  hrp::Vector3 p;
  hrp::Matrix33 R = hrp::rotFromRpy(0, -M_PI/2, 0);

  double startx=-0.3, starty=-1.0, startz=1.0;
  double endx=0.7, endy=0.5, endz=2.0;
  if (arm != 0){
    double tmp = starty;
    starty = -endy;
    endy = -tmp;
  }

  wstate.collisions[0].points.length(12);
  updateLineSegment(wstate.collisions[0].points[0], hrp::Vector3(startx, starty, startz), hrp::Vector3(endx, starty, startz));
  updateLineSegment(wstate.collisions[0].points[1], hrp::Vector3(startx, starty, startz), hrp::Vector3(startx, endy, startz));
  updateLineSegment(wstate.collisions[0].points[2], hrp::Vector3(startx, starty, startz), hrp::Vector3(startx, starty, endz));
  updateLineSegment(wstate.collisions[0].points[3], hrp::Vector3(endx, endy, startz), hrp::Vector3(startx, endy, startz));
  updateLineSegment(wstate.collisions[0].points[4], hrp::Vector3(endx, endy, startz), hrp::Vector3(endx, starty, startz));
  updateLineSegment(wstate.collisions[0].points[5], hrp::Vector3(endx, endy, startz), hrp::Vector3(endx, endy, endz));
  updateLineSegment(wstate.collisions[0].points[6], hrp::Vector3(endx, starty, endz), hrp::Vector3(endx, starty, startz));
  updateLineSegment(wstate.collisions[0].points[7], hrp::Vector3(endx, starty, endz), hrp::Vector3(startx, starty, endz));
  updateLineSegment(wstate.collisions[0].points[8], hrp::Vector3(endx, starty, endz), hrp::Vector3(endx, endy, endz));
  updateLineSegment(wstate.collisions[0].points[9], hrp::Vector3(startx, endy, endz), hrp::Vector3(endx, endy, endz));
  updateLineSegment(wstate.collisions[0].points[10], hrp::Vector3(startx, endy, endz), hrp::Vector3(startx, endy, startz));
  updateLineSegment(wstate.collisions[0].points[11], hrp::Vector3(startx, endy, endz), hrp::Vector3(startx, starty, endz));
  double step=0.05;
  int total=0, success=0;

  IkSolutionList<IkReal> solutions;
  IkReal eerot[9],eetrans[3];
  std::vector<IkReal> solvalues(GetNumJoints());
  double linErr=0, angErr=0;

  struct timeval begin, end;
  gettimeofday(&begin, NULL);

  for (double x=startx; x<endx; x+=step){
    for (double y=starty; y<endy; y+=step){
      for (double z=startz; z<endz; z+=step){
	total++;
	p << x,y,z;
	if (display) std::cout << "testing " << p.transpose() << " - ";
#if 0
	bool ret = jp->calcInverseKinematics(p, R);

	if (ret && checkLimits){
	  for (int i=0; i<jp->numJoints(); i++){
	    hrp::Link *j = jp->joint(i);
	    if (j->q > j->ulimit || j->q < j->llimit){
	      std::cout << "fail\r" << std::flush;
	      ret = false;
	      break;
	    }
	  }
	}
#else
	hrp::Vector3 relP;
	hrp::Matrix33 relR;
	relR = jp->baseLink()->R.transpose() * R;
	relP = jp->baseLink()->R.transpose() * (p - jp->baseLink()->p);
	for (int i=0; i<3; i++){
	  eetrans[i] = relP[i];
	  for (int j=0; j<3; j++){
	    eerot[i*3+j] = relR(i,j);
	  }
	}
	bool ret = ComputeIk(eetrans, eerot, NULL, solutions);
	if (ret) {
	  ret = false;
	  for (int j=0; j<solutions.GetNumSolutions(); j++){
	    const IkSolutionBase<IkReal>& sol = solutions.GetSolution(j);
  	    sol.GetSolution(&solvalues[0],NULL);
	    bool found=true;
	    for (int i=0; i<jp->numJoints(); i++){
	      hrp::Link *l = jp->joint(i);
	      if (solvalues[i] > l->ulimit || solvalues[i] < l->llimit) {
		found = false;
		break;
	      }else{
		l->q = solvalues[i];
	      }
	    }
	    if (found) {
	      ret = true;
	      jp->calcForwardKinematics();
	      double perr = (jp->endLink()->p - p).norm();
	      if (perr > linErr) linErr = perr;
	      double ang = hrp::omegaFromRot(jp->endLink()->R.transpose()*R).norm();
	      if (ang > angErr) angErr = ang;
	      break;
	    }
	  }
	}
	if (!ret && display){
	  std::cout << "fail\r" << std::flush;
	}
#endif
	if (ret) success++;

	if (display){
	  if (ret){
	    std::cout << "success\r" << std::flush;
	    unsigned int len = wstate.collisions[0].points.length();
	    wstate.collisions[0].points.length(len+1);
	    updateLineSegment(wstate.collisions[0].points[len],
			      p, R*hrp::Vector3(0,0,-0.01)+p);
	    updateView(olv, wstate, body);
	  }else{
	    std::cout << "fail\r" << std::flush;
	  }
	}
      }
    }
  }

  gettimeofday(&end, NULL);

  std::cout << std::endl;
  std::cout << "result:" << success << "/" << total << "(" 
	    << ((double)success)/total*100 << "%)" << std::endl;

  std::cout << "computation time:" << (end.tv_sec - begin.tv_sec)*1e3 + (end.tv_usec - begin.tv_usec)*1e-3 << "[ms]" << std::endl;
  std::cout << "maximum err:" << linErr << "[m], " << angErr << "[rad]" << std::endl; 

  return 0;
}