test_BasicIK.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Apache License)
00003  *
00004  * Copyright (c) 2013, Southwest Research Institute
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *   http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 #include <gtest/gtest.h>
00020 #include <constrained_ik/ik/basic_ik.h>
00021 
00022 using constrained_ik::basic_ik::Basic_IK;
00023 using constrained_ik::basic_kin::BasicKin;
00024 using Eigen::Affine3d;
00025 using Eigen::VectorXd;
00026 
00027 /* ----------------------------------------------------------------
00028  * Test Fixtures
00029  *   consolidate variable-definitions and init functions
00030  *   for use by multiple tests.
00031  * ----------------------------------------------------------------
00032  */
00033 
00034 class BasicIKTest : public ::testing::Test
00035 {
00036 protected:
00037   urdf::Model model;
00038   BasicKin kin;
00039   Basic_IK ik;
00040   Affine3d homePose;
00041 
00042   virtual void SetUp()
00043   {
00044     ASSERT_TRUE(model.initFile(urdf_file));
00045     ASSERT_TRUE(kin.init(model, "base_link", "link_6"));
00046     ASSERT_TRUE(kin.calcFwdKin(VectorXd::Zero(6), homePose));
00047     ASSERT_NO_THROW(ik.init(kin));
00048   }
00049 private:
00050   static const std::string urdf_file;
00051 };
00052 const std::string BasicIKTest::urdf_file = "puma_560.urdf";
00053 
00054 
00055 typedef BasicIKTest init;
00056 typedef BasicIKTest calcInvKin;
00057 typedef BasicIKTest axisAngleCheck;
00058 /* ---------------------------------------------------------------- */
00059 
00060 TEST_F(init, inputValidation)
00061 {
00062   EXPECT_ANY_THROW(Basic_IK().init(urdf::Model(), "", ""));
00063   EXPECT_NO_THROW(Basic_IK().init(model, "base_link", "link_6"));
00064   EXPECT_ANY_THROW(Basic_IK().init(BasicKin()));
00065   EXPECT_NO_THROW(Basic_IK().init(kin));
00066 
00067   EXPECT_FALSE(Basic_IK().checkInitialized());
00068   EXPECT_TRUE(ik.checkInitialized());
00069 }
00070 
00071 TEST_F(calcInvKin, inputValidation)
00072 {
00073   VectorXd seed = VectorXd::Zero(6);
00074   VectorXd joints;
00075 
00076 //  try {
00077 //      Affine3d btest0, btest2(Eigen::Matrix4d::Zero());
00078 //      ik.calcInvKin(btest2, seed, joints);
00079 //      ADD_FAILURE();
00080 //  } catch (const std::exception &ex) {
00081 //      SUCCEED();
00082 //  }
00083 
00084   EXPECT_TRUE(ik.checkInitialized());
00085   EXPECT_ANY_THROW(Basic_IK().calcInvKin(Affine3d::Identity(), seed, joints));      // un-init Basic_IK
00086   EXPECT_ANY_THROW(ik.calcInvKin(Affine3d(Eigen::Matrix4d::Zero()), seed, joints)); // empty Pose (zeros in matrix because unitary rotation matrix is often in memory)
00087   EXPECT_ANY_THROW(ik.calcInvKin(homePose, VectorXd(), joints));                    // un-init Seed
00088   EXPECT_ANY_THROW(ik.calcInvKin(homePose, VectorXd::Zero(99), joints));            // wrong-sized Seed
00089 
00090   // valid input
00091   //   - GTest doesn't print exception info.  This method allows us to print that info, for easier troubleshooting
00092   try {
00093     ik.calcInvKin(homePose, seed, joints);
00094     SUCCEED();
00095   } catch (const std::exception &ex) {
00096     ADD_FAILURE() << ex.what();
00097   }
00098 }
00099 
00100 TEST_F(calcInvKin, knownPoses)
00101 {
00102   Affine3d pose, rslt_pose;
00103   VectorXd seed, expected(6), joints;
00104 
00105   // seed position *at* expected solution
00106   expected << M_PI_2, -M_PI_2, -M_PI_2, -M_PI_2, M_PI_2, -M_PI_2;
00107   pose.translation().matrix() << -0.1245, 0.0203, 0.6740;
00108   pose.matrix().topLeftCorner(3,3) << 0,0,1,
00109                                       1,0,0,
00110                                       0,1,0;
00111   seed = expected;
00112   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00113                "*at* from expected: " << expected.transpose() << std::endl;
00114   ik.calcInvKin(pose, seed, joints);
00115   EXPECT_TRUE(joints.isApprox(expected, 1e-10));
00116 
00117   // seed position *near* expected solution
00118   seed = expected + 0.01 * VectorXd::Random(expected.size());
00119   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00120                "*near* from expected: " << expected.transpose() << std::endl;
00121   ik.calcInvKin(pose, seed, joints);
00122 //  EXPECT_TRUE(joints.isApprox(expected, 0.01));
00123   kin.calcFwdKin(joints, rslt_pose);
00124 //  std::cout << rslt_pose.matrix() << std::endl << pose.matrix() << std::endl;
00125   EXPECT_TRUE(rslt_pose.isApprox(pose, 0.005));
00126 
00127   // *near* #2
00128   seed = expected + 0.05 * VectorXd::Random(expected.size());
00129   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00130                "*near* from expected: " << expected.transpose() << std::endl;
00131   ik.calcInvKin(pose, seed, joints);
00132   kin.calcFwdKin(joints, rslt_pose);
00133   //  std::cout << rslt_pose.matrix() << std::endl << pose.matrix() << std::endl;
00134   EXPECT_TRUE(rslt_pose.isApprox(pose, 0.005));
00135 
00136   // seed position *near* expected solution
00137   seed = expected + 0.1 * VectorXd::Random(expected.size());
00138   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00139                "*near* from expected: " << expected.transpose() << std::endl;
00140   ik.calcInvKin(pose, seed, joints);
00141   kin.calcFwdKin(joints, rslt_pose);
00142   //  std::cout << rslt_pose.matrix() << std::endl << pose.matrix() << std::endl;
00143   EXPECT_TRUE(rslt_pose.isApprox(pose, 0.005));
00144 
00145   // test with seed far from expected position
00146   expected << M_PI_2, 0, 0, 0, 0, 0;
00147   pose.translation().matrix() << -0.1245, 0.4115, 1.1058;
00148   pose.matrix().topLeftCorner(3,3) << 0,-1, 0,
00149                                       1, 0, 0,
00150                                       0, 0, 1;
00151   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00152                "*far* from expected: " << expected.transpose() << std::endl;
00153   ik.calcInvKin(pose, VectorXd::Zero(expected.size()), joints);
00154   kin.calcFwdKin(joints, rslt_pose);
00155 //  std::cout << rslt_pose.matrix() << std::endl << pose.matrix() << std::endl;
00156   EXPECT_TRUE(rslt_pose.isApprox(pose, 0.005));
00157 
00158   // *far* #2
00159   expected << 0, -M_PI_2, 0, 0, 0, 0;
00160   pose.translation().matrix() << -0.4318, 0.1245, 1.0855;
00161   pose.matrix().topLeftCorner(3,3) << 0, 0,-1,
00162                                       0, 1, 0,
00163                                       1, 0, 0;
00164   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00165                "*far* from expected: " << expected.transpose() << std::endl;
00166   ik.calcInvKin(pose, VectorXd::Zero(expected.size()), joints);
00167   kin.calcFwdKin(joints, rslt_pose);
00168 //  std::cout << rslt_pose.matrix() << std::endl << pose.matrix() << std::endl;
00169   EXPECT_TRUE(rslt_pose.isApprox(pose, 0.005));
00170 
00171   // *farther*
00172   expected << M_PI_4, -M_PI_4, 0, 0, 0, 0;
00173   pose.translation().matrix() << -0.0982, 0.0778, 1.2703;
00174   pose.matrix().topLeftCorner(3,3) << 0.5, -0.707107,-0.5,
00175                                       0.5,  0.707107,-0.5,
00176                                       0.707107, 0,    0.707107;
00177   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00178                "*farther* from expected: " << expected.transpose() << std::endl;
00179   ik.calcInvKin(pose, VectorXd::Zero(expected.size()), joints);
00180   kin.calcFwdKin(joints, rslt_pose);
00181 //  std::cout << rslt_pose.matrix() << std::endl << pose.matrix() << std::endl;
00182   EXPECT_FALSE(rslt_pose.isApprox(pose, 0.005));
00183 
00184   // *very far*
00185   expected << M_PI_2, -M_PI_2, 0, 0, 0, 0;
00186   pose.translation().matrix() << -0.1245, -0.4318, 1.0855;
00187   pose.matrix().topLeftCorner(3,3) << 0, -1, 0,
00188                                       0,  0,-1,
00189                                       1,  0, 0;
00190   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00191                "*very far* from expected: " << expected.transpose() << std::endl;
00192   ik.calcInvKin(pose, VectorXd::Zero(expected.size()), joints);
00193   kin.calcFwdKin(joints, rslt_pose);
00194 //  std::cout << rslt_pose.matrix() << std::endl << pose.matrix() << std::endl;
00195   EXPECT_FALSE(rslt_pose.isApprox(pose, 0.005));
00196 }
00197 
00198 /*This test checks the consistancy of the axisAngle calculations from a quaternion value,
00199   namely does it always return an angle in +/-pi range?
00200   (The answer should be yes)
00201   */
00202 TEST_F(axisAngleCheck, consistancy)
00203 {
00204     Eigen::Vector3d k(Eigen::Vector3d::UnitZ());
00205     for (double theta=-7.0; theta<7.0; theta+=1.0)
00206     {
00207         Eigen::Vector4d expected; expected << k, ik.rangedAngle(theta);
00208 
00209         //create angle-axis representation of theta @ k
00210         Eigen::AngleAxisd aa(theta, k);
00211         Eigen::Quaterniond q(aa);
00212         Eigen::AngleAxisd aa_q(q);
00213 
00214         //stuff results into vectorrd for direct comparison
00215         Eigen::Vector4d rslt; rslt << aa_q.axis(), aa_q.angle();
00216         rslt(3) = ik.rangedAngle(aa_q.angle());
00217 
00218         //if theta ~= 0, angleAxis/Quaternion operations will give [1,0,0] as vector
00219         if (fabs(theta) < 1e-6)
00220         {
00221             expected(0) = 1;
00222             expected(1) = 0;
00223             expected(2) = 0;
00224         }
00225 
00226         //rslt may be reverse vector & angle, which is still a valid representation
00227         EXPECT_TRUE(rslt.isApprox(expected, 1e-5) or rslt.isApprox(-expected, 1e-5));
00228 //        std::cout << rslt.transpose() << std::endl;
00229     }
00230 }
00231 
00232 int main(int argc, char **argv)
00233 {
00234   testing::InitGoogleTest(&argc, argv);
00235   return RUN_ALL_TESTS();
00236 }
00237 


constrained_ik
Author(s): Chris Lewis , Jeremy Zoss , Dan Solomon
autogenerated on Mon Oct 6 2014 00:52:26