test_constrained_ik.cpp
Go to the documentation of this file.
00001 
00028 #include <gtest/gtest.h>
00029 #include <ros/ros.h>
00030 #include "constrained_ik/constrained_ik.h"
00031 #include "constrained_ik/constraints/goal_pose.h"
00032 #include "constrained_ik/constraints/goal_position.h"
00033 #include "constrained_ik/constraints/goal_orientation.h"
00034 #include "constrained_ik/constraints/avoid_obstacles.h"
00035 #include "constrained_ik/constrained_ik_utils.h"
00036 #include <moveit/robot_model_loader/robot_model_loader.h>
00037 #include <moveit/robot_model/joint_model_group.h>
00038 #include <moveit/collision_plugin_loader/collision_plugin_loader.h>
00039 #include <boost/random/uniform_int_distribution.hpp>
00040 
00041 using constrained_ik::Constrained_IK;
00042 using constrained_ik::basic_kin::BasicKin;
00043 using Eigen::Affine3d;
00044 using Eigen::VectorXd;
00045 using Eigen::MatrixXd;
00046 using Eigen::JacobiSVD;
00047 
00048 
00049 const std::string GROUP_NAME = "manipulator"; 
00050 const std::string ROBOT_DESCRIPTION_PARAM = "robot_description"; 
00053 TEST(constrained_ik, nullspaceprojection)
00054 {
00055   int rows = 6;
00056   int cols = 8;
00057   MatrixXd A = MatrixXd::Random(rows, cols);
00058   
00059   JacobiSVD<MatrixXd> svd(A,Eigen::ComputeFullV | Eigen::ComputeFullU);
00060   MatrixXd V(svd.matrixV());
00061   MatrixXd U(svd.matrixU());
00062   Eigen::MatrixXd S(rows,cols);
00063   // TODO learn how to initialize eigen matrices with zero()
00064   for(int i=0; i<rows; i++)
00065   {
00066     for(int j=0; j<cols; j++) S(i,j) = 0.0;
00067   }
00068   VectorXd s = svd.singularValues();
00069   for(int i=0; i<rows-3; i++)
00070   {
00071     S(i,i) = s(i);
00072   }
00073 
00074   MatrixXd A2 = U * S * V.transpose();
00075 
00076   Constrained_IK CIK;
00077    
00078   MatrixXd P1 = CIK.calcNullspaceProjectionTheRightWay(A2);
00079   EXPECT_EQ(P1.rows(), cols);
00080   EXPECT_EQ(P1.cols(), cols);
00081   MatrixXd P2 = CIK.calcNullspaceProjection(A2);
00082   EXPECT_EQ(P2.rows(), cols);
00083   EXPECT_EQ(P2.cols(), cols);
00084   VectorXd testv1 = VectorXd::Random(cols);
00085   VectorXd P1v = P1*testv1;
00086   VectorXd P2v = P2*testv1;
00087   VectorXd AP1v = A2*P1v;
00088   VectorXd AP2v = A2*P2v;
00089   double norm1 = AP1v.norm();
00090   double norm2 = AP2v.norm();
00091   EXPECT_LT(norm1, .00000001);
00092   EXPECT_LT(norm2, .00000001);
00093 }
00094 
00099 class BasicIKTest : public ::testing::Test
00100 {
00101 protected:
00102 
00103   robot_model_loader::RobotModelLoaderPtr loader_;  
00104   moveit::core::RobotModelPtr robot_model_; 
00105   planning_scene::PlanningScenePtr planning_scene_; 
00106   BasicKin kin; 
00107   Constrained_IK ik; 
00108   Affine3d homePose; 
00109   constrained_ik::ConstrainedIKConfiguration config; 
00112   virtual void SetUp()
00113   {
00114     loader_.reset(new robot_model_loader::RobotModelLoader(ROBOT_DESCRIPTION_PARAM));
00115     robot_model_ = loader_->getModel();
00116 
00117 
00118     ASSERT_TRUE(robot_model_ != nullptr);
00119     ASSERT_TRUE(kin.init(robot_model_->getJointModelGroup(GROUP_NAME)));
00120     ASSERT_TRUE(kin.calcFwdKin(VectorXd::Zero(6), homePose));
00121     ASSERT_NO_THROW(ik.init(kin));
00122     ASSERT_NO_THROW(planning_scene_.reset(new planning_scene::PlanningScene(robot_model_)));
00123     ASSERT_NO_THROW(config = ik.getSolverConfiguration());
00124 
00125     //Now assign collision detection plugin
00126     collision_detection::CollisionPluginLoader cd_loader;
00127     std::string class_name = "IndustrialFCL";
00128     ASSERT_TRUE(cd_loader.activate(class_name, planning_scene_, true));
00129   }
00130 };
00131 
00133 TEST_F(BasicIKTest, inputValidation)
00134 {
00135   EXPECT_ANY_THROW(Constrained_IK().init(BasicKin()));
00136   EXPECT_NO_THROW(Constrained_IK().init(kin));
00137 
00138   EXPECT_EQ(Constrained_IK().checkInitialized(), constrained_ik::initialization_state::NothingInitialized);
00139   constrained_ik::Constraint *goal_ptr = new  constrained_ik::constraints::GoalPosition();
00140   ik.addConstraint(goal_ptr, constrained_ik::constraint_types::Primary);
00141   EXPECT_NE(ik.checkInitialized(), constrained_ik::initialization_state::NothingInitialized);
00142 }
00143 
00145 TEST_F(BasicIKTest, calcInvKinInputValidation)
00146 {
00147   VectorXd seed = VectorXd::Zero(6);
00148   VectorXd joints;
00149   constrained_ik::Constraint *goal_ptr = new  constrained_ik::constraints::GoalPosition();
00150   ik.addConstraint(goal_ptr, constrained_ik::constraint_types::Primary);
00151   EXPECT_NE(ik.checkInitialized(), constrained_ik::initialization_state::NothingInitialized);
00152   EXPECT_ANY_THROW(Constrained_IK().calcInvKin(Affine3d::Identity(), seed, joints));      // un-init Constrained_IK
00153   EXPECT_ANY_THROW(ik.calcInvKin(Affine3d(Eigen::Matrix4d::Zero()), seed, joints)); // empty Pose (zeros in matrix because unitary rotation matrix is often in memory)
00154   EXPECT_ANY_THROW(ik.calcInvKin(homePose, VectorXd(), joints));                    // un-init Seed
00155   EXPECT_ANY_THROW(ik.calcInvKin(homePose, VectorXd::Zero(99), joints));            // wrong-sized Seed
00156 
00157   // valid input
00158   //   - GTest doesn't print exception info.  This method allows us to print that info, for easier troubleshooting
00159   try 
00160   {
00161     ik.calcInvKin(homePose, seed, joints);
00162     SUCCEED();
00163   } catch (const std::exception &ex) 
00164   {
00165     ADD_FAILURE() << ex.what();
00166   }
00167 }
00168 
00170 TEST_F(BasicIKTest, knownPoses)
00171 {
00172   Affine3d pose, rslt_pose;
00173   VectorXd seed, expected(6), joints;
00174   ik.loadDefaultSolverConfiguration();
00175   config = ik.getSolverConfiguration();
00176 
00177   // seed position *at* expected solution
00178   expected << M_PI_2, -M_PI_2, -M_PI_2, -M_PI_2, M_PI_2, -M_PI_2;
00179   seed = expected;
00180   EXPECT_TRUE(kin.calcFwdKin(expected, pose)); // expect the pose to remain unchanged
00181 
00182   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00183     "*at* from expected: " << expected.transpose() << std::endl;
00184 
00185   // adding primary constraints to move to a pose
00186   ik.clearConstraintList();
00187   constrained_ik::Constraint *goal_pose_ptr = new  constrained_ik::constraints::GoalPose();
00188   ik.addConstraint(goal_pose_ptr, constrained_ik::constraint_types::Primary);
00189 
00190   // seed = expected, pose = fwdK(expected)
00191   EXPECT_NO_THROW(ik.calcInvKin(pose, seed, joints));
00192   std::cout << "joint values returned" << joints << std::endl;
00193   EXPECT_TRUE(joints.isApprox(expected, 1e-10));
00194 
00195   // seed position *near* expected solution
00196   seed = expected + 0.01 * VectorXd::Random(expected.size());
00197   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00198                "*near* from expected: " << expected.transpose() << std::endl;
00199   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00200   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00201   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00202   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00203 
00204   // *near* #2
00205   seed = expected + 0.05 * VectorXd::Random(expected.size());
00206   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00207                "*near* from expected: " << expected.transpose() << std::endl;
00208   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00209   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00210   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00211   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00212 
00213   // seed position *near* expected solution
00214   seed = expected + 0.1 * VectorXd::Random(expected.size());
00215   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00216                "*near* from expected: " << expected.transpose() << std::endl;
00217   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00218   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00219   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00220   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00221 
00222   // test with seed far from expected position
00223   expected << M_PI_2, 0, 0, 0, 0, 0;
00224   kin.calcFwdKin(expected, pose);
00225   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00226                "*far1* from expected: " << expected.transpose() << std::endl;
00227   config.primary_gain = 0.5;
00228   config.limit_primary_motion = false;
00229   ik.setSolverConfiguration(config);
00230   EXPECT_TRUE(ik.calcInvKin(pose, VectorXd::Zero(expected.size()), joints));
00231   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00232   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00233   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00234 
00235   // *far* #2
00236   expected << 0, -M_PI_2, 0, 0, 0, 0;
00237   kin.calcFwdKin(expected, pose);
00238   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00239                "*far2* from expected: " << expected.transpose() << std::endl;
00240   EXPECT_TRUE(ik.calcInvKin(pose, VectorXd::Zero(expected.size()), joints));
00241   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00242   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00243   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00244 
00245   // *farther*
00246   expected << M_PI_4, -M_PI_4, 0, 0, 0, 0;
00247   kin.calcFwdKin(expected, pose);
00248   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00249                "*farther* from expected: " << expected.transpose() << std::endl;
00250   seed = VectorXd::Zero(expected.size());
00251   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00252   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00253   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00254   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00255 
00256   // *very far*
00257   expected << M_PI_2, -M_PI_2, 0, 0, 0, 0;
00258   kin.calcFwdKin(expected, pose);
00259   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00260                "*very far* from expected: " << expected.transpose() << std::endl;
00261   seed = VectorXd::Zero(expected.size());
00262   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00263   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00264   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00265   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00266 }
00267 
00269 TEST_F(BasicIKTest, NullMotion)
00270 {
00271   Affine3d pose, rslt_pose;
00272   VectorXd seed, expected(6), joints;
00273   boost::random::mt19937 rng;  
00274   ik.loadDefaultSolverConfiguration();
00275   config = ik.getSolverConfiguration();
00276   config.limit_auxiliary_interations = false;
00277   config.limit_auxiliary_motion = false;
00278   config.limit_primary_motion = false;
00279   ik.setSolverConfiguration(config);
00280 
00281   // adding primary constraints to move to a position, and auxillary constraints to move to pose
00282   ik.clearConstraintList();
00283   constrained_ik::Constraint *goal_position_ptr = new  constrained_ik::constraints::GoalPosition();
00284   ik.addConstraint(goal_position_ptr, constrained_ik::constraint_types::Primary);
00285   constrained_ik::Constraint *goal_orientation_ptr = new  constrained_ik::constraints::GoalOrientation();
00286   ik.addConstraint(goal_orientation_ptr, constrained_ik::constraint_types::Auxiliary);
00287 
00288   // seed position *at* expected solution
00289   expected << M_PI_2, -M_PI_2, -M_PI_2, -M_PI_2, M_PI_2, -M_PI_2;
00290 
00291   kin.calcFwdKin(expected, pose);
00292   config.primary_gain = 0.5;
00293   config.auxiliary_gain = 0.5;
00294   ik.setSolverConfiguration(config);
00295   seed = expected;
00296   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00297                "*at* from expected: " << expected.transpose() << std::endl;
00298   ik.calcInvKin(pose, seed, joints);
00299   EXPECT_TRUE(joints.isApprox(expected, 1e-10));
00300 
00301   // seed position *near* expected solution
00302   expected << M_PI_2, -M_PI_2, -M_PI_2, -M_PI_2, M_PI_2, -M_PI_2;
00303   kin.calcFwdKin(expected, pose);
00304   seed = expected + 0.01 * VectorXd::Random(expected.size());
00305   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00306                "*near* from expected: " << expected.transpose() << std::endl;
00307   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00308   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00309   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00310   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00311 
00312   // *near* #2
00313   for(int j=0; j<3; j++) // do 3 random examples of near starts
00314   {
00315     for(int i=0; i<6; i++)  // find a random pose
00316     {
00317       boost::random::uniform_int_distribution<int> angle_degrees(-177, 177) ;
00318       boost::random::uniform_int_distribution<int> small_angle_degrees(-3, 3) ;
00319       expected[i] = angle_degrees(rng)* 3.14/180.0;
00320       seed[i] = expected[i] + small_angle_degrees(rng)*3.14/180.0;
00321     }
00322     kin.calcFwdKin(expected, pose);
00323     config.primary_gain = 0.15;
00324     config.auxiliary_gain = 0.05;
00325     ik.setSolverConfiguration(config);
00326     EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00327     EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00328     EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00329     EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00330   }
00331 
00332   // *far*
00333   int num_success=0;
00334   for(int j=0; j<20; j++) // do 3 random examples of far starts
00335   {
00336     for(int i=0; i<6; i++)  // find a random pose
00337     {
00338       boost::random::uniform_int_distribution<int> angle_degrees(-180+50, 180-50) ;
00339       boost::random::uniform_int_distribution<int> small_angle_degrees(-50, 50) ;
00340       expected[i] = angle_degrees(rng)* 3.14/180.0;
00341       seed[i] = expected[i] + small_angle_degrees(rng)*3.14/180.0;
00342     }
00343     kin.calcFwdKin(expected, pose);
00344     config.primary_gain = 0.15;
00345     config.auxiliary_gain = 0.05;
00346     ik.setSolverConfiguration(config);
00347     ik.calcInvKin(pose, seed, joints);
00348     kin.calcFwdKin(joints, rslt_pose);
00349     if(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3) && rslt_pose.translation().isApprox(pose.translation(), 1e-3)) num_success++;
00350   }
00351   EXPECT_GE(num_success, 15);
00352   
00353   // *farther*
00354   num_success=0;
00355   for(int j=0; j<20; j++) // do 20 random examples of farther starts
00356   {
00357     for(int i=0; i<6; i++)  // find a random pose
00358     {
00359       boost::random::uniform_int_distribution<int> angle_degrees(-180+90, 180-90) ;
00360       boost::random::uniform_int_distribution<int> small_angle_degrees(-90, 90) ;
00361       expected[i] = angle_degrees(rng)* 3.14/180.0;
00362       seed[i] = expected[i] + small_angle_degrees(rng)*3.14/180.0;
00363     }
00364     kin.calcFwdKin(expected, pose);
00365     config.primary_gain = 0.15;
00366     config.auxiliary_gain = 0.05;
00367     ik.setSolverConfiguration(config);
00368     ik.calcInvKin(pose, seed, joints);
00369     kin.calcFwdKin(joints, rslt_pose);
00370     if(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3) && rslt_pose.translation().isApprox(pose.translation(), 1e-3)) num_success++;
00371   }
00372   EXPECT_GE(num_success, 10);
00373 }
00374 
00376 TEST_F(BasicIKTest, NullMotionPose)
00377 {
00378   Affine3d pose, rslt_pose;
00379   VectorXd seed, expected(6), joints;
00380   ik.loadDefaultSolverConfiguration();
00381   config = ik.getSolverConfiguration();
00382 
00383   // adding primary constraints to move to an orientation, and auxillary constraints to move to position
00384   ik.clearConstraintList();
00385   constrained_ik::Constraint *goal_orientation_ptr = new  constrained_ik::constraints::GoalOrientation();
00386   ik.addConstraint(goal_orientation_ptr, constrained_ik::constraint_types::Primary);
00387   constrained_ik::Constraint *goal_position_ptr = new  constrained_ik::constraints::GoalPosition();
00388   ik.addConstraint(goal_position_ptr, constrained_ik::constraint_types::Auxiliary);
00389 
00390   // seed position *at* expected solution
00391   expected << M_PI_2, -M_PI_2, -M_PI_2, -M_PI_2, M_PI_2, -M_PI_2;
00392   kin.calcFwdKin(expected, pose);
00393   seed = expected;
00394   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00395                "*at* from expected: " << expected.transpose() << std::endl;
00396   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00397   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00398   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00399   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00400 
00401   // seed position *near* expected solution
00402   seed = expected + 0.01 * VectorXd::Random(expected.size());
00403   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00404                "*near* expected: " << expected.transpose() << std::endl;
00405   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00406   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00407   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00408   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00409   // *near* #2
00410   seed = expected + 0.05 * VectorXd::Random(expected.size());
00411   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00412                "*near* expected: " << expected.transpose() << std::endl;
00413   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00414   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00415   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00416   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00417 
00418   // seed position *near* expected solution
00419   seed = expected + 0.1 * VectorXd::Random(expected.size());
00420   std::cout << "Testing seed vector " << seed.transpose() << std::endl <<
00421                "*near* from expected: " << expected.transpose() << std::endl;
00422   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00423   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00424   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00425   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00426 
00427   // test with seed far from expected position
00428   expected << M_PI_2, 0, 0, 0, 0, 0;
00429   kin.calcFwdKin(expected, pose);
00430   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00431                "*far1* from expected: " << expected.transpose() << std::endl;
00432   config.primary_gain = 0.1;
00433   config.auxiliary_gain = 0.1;
00434   config.limit_auxiliary_interations = false;
00435   config.limit_auxiliary_motion = false;
00436   config.limit_primary_motion = false;
00437   ik.setSolverConfiguration(config);
00438   seed = VectorXd::Zero(expected.size());
00439   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00440   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00441   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00442   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00443 
00444   // *far* #2
00445   expected << 0, -M_PI_2, 0, 0, 0, 0;
00446   kin.calcFwdKin(expected, pose);
00447   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00448                "*far2* from expected: " << expected.transpose() << std::endl;
00449   seed = VectorXd::Zero(expected.size());
00450   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00451   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00452   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00453   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00454 
00455   // *farther*
00456   expected << M_PI_4, -M_PI_4, 0, 0, 0, 0;
00457   kin.calcFwdKin(expected, pose);
00458   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00459                "*farther* from expected: " << expected.transpose() << std::endl;
00460   seed = VectorXd::Zero(expected.size());
00461   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00462   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00463   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00464   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00465 
00466   // *very far*
00467   expected << M_PI_2, -M_PI_2, 0, 0, 0, 0;
00468   kin.calcFwdKin(expected, pose);
00469   std::cout << "Testing seed vector " << VectorXd::Zero(expected.size()).transpose() << std::endl <<
00470                "*very far* from expected: " << expected.transpose() << std::endl;
00471   config.primary_gain = 0.1;
00472   config.auxiliary_gain = 0.001;
00473   config.solver_max_iterations = 10000;
00474   ik.setSolverConfiguration(config);
00475   seed = VectorXd::Zero(expected.size());
00476   EXPECT_TRUE(ik.calcInvKin(pose, seed, joints));
00477   EXPECT_TRUE(kin.calcFwdKin(joints, rslt_pose));
00478   EXPECT_TRUE(rslt_pose.rotation().isApprox(pose.rotation(), 9e-3));
00479   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00480 }
00481 
00491 TEST_F(BasicIKTest, obstacleAvoidanceAuxiliaryConstraint)
00492 {
00493   Affine3d pose, rslt_pose;
00494   VectorXd seed, expected(6), joints;
00495   ik.loadDefaultSolverConfiguration();
00496   config = ik.getSolverConfiguration();
00497   config.solver_min_iterations = 1;
00498   config.limit_auxiliary_interations = true;
00499   ik.setSolverConfiguration(config);
00500 
00501   // adding primary constraints to move to an orientation, and Auxiliary constraints to move to position
00502   ik.clearConstraintList();
00503   constrained_ik::Constraint *goal_position_ptr = new  constrained_ik::constraints::GoalPosition();
00504 
00505   std::vector<std::string> link_names;
00506   ik.getLinkNames(link_names);
00507   int link_id = link_names.size()/2;
00508   std::vector<std::string> obstacle_avoidance_link_name;
00509   constrained_ik::constraints::AvoidObstacles *avoid_obstacles_ptr =  new constrained_ik::constraints::AvoidObstacles();
00510 
00511   obstacle_avoidance_link_name.push_back(link_names[link_id]);
00512   avoid_obstacles_ptr->setAvoidanceLinks(obstacle_avoidance_link_name);
00513   avoid_obstacles_ptr->setMinDistance(link_names[link_id], 0.01);
00514   avoid_obstacles_ptr->setAmplitude(link_names[link_id], 1.0);
00515   avoid_obstacles_ptr->setAvoidanceDistance(link_names[link_id], 1.0);
00516 
00517   // add the constraints
00518   ik.addConstraint(goal_position_ptr, constrained_ik::constraint_types::Primary);
00519   ik.addConstraint(avoid_obstacles_ptr, constrained_ik::constraint_types::Auxiliary);
00520 
00521   // perform inverse kinematics but the position should not change, just the orientation
00522   expected << M_PI_2, -M_PI_2, -M_PI_2, -M_PI_2, M_PI_2, -M_PI_2;
00523   kin.calcFwdKin(expected, pose);
00524   seed = expected;
00525   config.auxiliary_max_iterations = 1;
00526   ik.setSolverConfiguration(config);
00527   EXPECT_TRUE(ik.calcInvKin(pose, seed, planning_scene_, joints));
00528   EXPECT_TRUE(kin.calcFwdKin(joints,rslt_pose));
00529   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00530   EXPECT_NE(expected, joints);
00531 
00532   // do it again, but his time allow 100 iterations on the auxiliary constriants
00533   // this allows more obstacle avoidance after the position has converged
00534   config.auxiliary_max_iterations = 100;
00535   ik.setSolverConfiguration(config);
00536   EXPECT_TRUE(ik.calcInvKin(pose, seed, planning_scene_, joints));
00537   EXPECT_TRUE(kin.calcFwdKin(joints,rslt_pose));
00538   EXPECT_TRUE(rslt_pose.translation().isApprox(pose.translation(), 1e-3));
00539   EXPECT_NE(expected, joints);
00540 }
00541 
00546 TEST_F(BasicIKTest, consistancy)
00547 {
00548     Eigen::Vector3d k(Eigen::Vector3d::UnitZ());
00549     for (double theta=-7.0; theta<7.0; theta+=1.0)
00550     {
00551         Eigen::Vector4d expected; expected << k, ik.rangedAngle(theta);
00552 
00553         //create angle-axis representation of theta @ k
00554         Eigen::AngleAxisd aa(theta, k);
00555         Eigen::Quaterniond q(aa);
00556         Eigen::AngleAxisd aa_q(q);
00557 
00558         //stuff results into vectorrd for direct comparison
00559         Eigen::Vector4d rslt; rslt << aa_q.axis(), aa_q.angle();
00560         rslt(3) = ik.rangedAngle(aa_q.angle());
00561 
00562         //if theta ~= 0, angleAxis/Quaternion operations will give [1,0,0] as vector
00563         if (fabs(theta) < 1e-6)
00564         {
00565             expected(0) = 1;
00566             expected(1) = 0;
00567             expected(2) = 0;
00568         }
00569 
00570         //rslt may be reverse vector & angle, which is still a valid representation
00571         EXPECT_TRUE(rslt.isApprox(expected, 1e-5) or rslt.isApprox(-expected, 1e-5));
00572     }
00573 }
00575 int main(int argc, char **argv)
00576 {
00577   testing::InitGoogleTest(&argc, argv);
00578   ros::init(argc,argv,"test_constrained_ik");
00579   ros::NodeHandle nh;
00580   return RUN_ALL_TESTS();
00581 }
00582 


constrained_ik
Author(s): Chris Lewis , Jeremy Zoss , Dan Solomon
autogenerated on Sat Jun 8 2019 19:23:45