00001
00002
00003
00004
00005
00006
00007
00008 #include <iostream>
00009 #include <gtest/gtest.h>
00010 #include "robodyn_controllers/MinJerkTrajectoryFactory.h"
00011 #include <tf/tf.h>
00012
00013 class TrajectoryGeneratorTest : public ::testing::Test
00014 {
00015 protected:
00016 virtual void SetUp()
00017 {
00018 ctg = new MinJerkCartesianTrajectoryFactory();
00019 jtg = new MinJerkJointTrajectoryFactory();
00020 }
00021
00022 virtual void TearDown()
00023 {
00024
00025 delete ctg;
00026 delete jtg;
00027 }
00028
00029 MinJerkCartesianTrajectoryFactory* ctg;
00030 MinJerkJointTrajectoryFactory* jtg;
00031 boost::shared_ptr<CartesianTrajectory> ctptr;
00032 boost::shared_ptr<JointTrajectory> jtptr;
00033 };
00034
00035
00036
00037 TEST_F(TrajectoryGeneratorTest, minJerkCartGetSetTest)
00038 {
00039
00040
00041
00042
00043
00044
00045
00046 const double linVel = 0.05;
00047 const double rotVel = 0.3;
00048
00049
00050 EXPECT_THROW(ctg->setVelocityLimits(-linVel, rotVel), std::invalid_argument);
00051 EXPECT_THROW(ctg->setVelocityLimits(linVel, -rotVel), std::invalid_argument);
00052
00053 ctg->setVelocityLimits(linVel, rotVel);
00054 EXPECT_EQ(linVel, ctg->getLinearVelocityLimit());
00055 EXPECT_EQ(rotVel, ctg->getRotationalVelocityLimit());
00056 }
00057
00058 TEST_F(TrajectoryGeneratorTest, minJerkCartTrajTest)
00059 {
00060 const double linVel = 0.05;
00061 const double rotVel = 0.3;
00062
00063 ctg->setVelocityLimits(linVel, rotVel);
00064
00065
00066 KDL::FrameAcc currPose, desPose, startTest, endTest, testPose, testPose2;
00067 currPose.p.p.x(0.);
00068 currPose.p.p.y(0.);
00069 currPose.p.p.z(0.);
00070 currPose.M.R = KDL::Rotation::Quaternion(0, 0, 0, 1);
00071 desPose.p.p.x(1.);
00072 desPose.p.p.y(2.);
00073 desPose.p.p.z(3.);
00074 desPose.M.R = currPose.M.R;
00075 desPose.M.R.DoRotX(.3);
00076 desPose.M.R.DoRotY(.2);
00077 desPose.M.R.DoRotZ(.1);
00078 std::vector<KDL::FrameAcc> traj;
00079
00080 ctptr = ctg->getTrajectory(currPose, desPose);
00081 ctptr->getPose(ctptr->getDuration(), endTest);
00082 EXPECT_EQ(desPose.GetFrame(), endTest.GetFrame());
00083 ctptr->getPose(0., startTest);
00084 EXPECT_EQ(currPose.GetFrame(), startTest.GetFrame());
00085
00086 double x, y, z, w;
00087 double prevLinDist = 0.;
00088 double totLinDist = (endTest.p.p - startTest.p.p).Norm();
00089 startTest.M.R.GetQuaternion(x, y, z, w);
00090 tf::Quaternion startQuat(x, y, z, w);
00091 endTest.M.R.GetQuaternion(x, y, z, w);
00092 tf::Quaternion endQuat(x, y, z, w);
00093 double totRotDist = std::fabs(endQuat.angleShortestPath(startQuat));
00094 double prevRotDist = 0.;
00095
00096 double timeStep = 0.01;
00097 ctptr->getPose(0., testPose);
00098
00099 for (double time = timeStep; time < ctptr->getDuration(); time += timeStep)
00100 {
00101
00102 testPose2 = testPose;
00103 ctptr->getPose(time, testPose);
00104 EXPECT_LE((testPose.p.p - testPose2.p.p).Norm() / timeStep, linVel);
00105 EXPECT_LE(testPose.p.v.Norm(), linVel);
00106
00107
00108 testPose2.M.R.GetQuaternion(x, y, z, w);
00109 tf::Quaternion quat1(x, y, z, w);
00110 testPose.M.R.GetQuaternion(x, y, z, w);
00111 tf::Quaternion quat2(x, y, z, w);
00112 EXPECT_LE(std::fabs(quat2.angleShortestPath(quat1) / timeStep), rotVel);
00113 EXPECT_LE(testPose.M.w.Norm(), rotVel);
00114
00115
00116 double linDist = (testPose.p.p - startTest.p.p).Norm();
00117 EXPECT_GE(linDist, prevLinDist);
00118
00119 if (totLinDist > 0)
00120 {
00121 EXPECT_GE(linDist / totLinDist, 0);
00122 EXPECT_LE(linDist / totLinDist, 1);
00123 }
00124
00125 double linDistToEnd = (endTest.p.p - testPose.p.p).Norm();
00126 EXPECT_LE(totLinDist - linDistToEnd - linDist, 0.0001);
00127 prevLinDist = linDist;
00128
00129
00130 double rotDist = std::fabs(quat2.angleShortestPath(startQuat));
00131 EXPECT_GE(rotDist, prevRotDist);
00132
00133 if (totRotDist > 0)
00134 {
00135 EXPECT_GE(rotDist / totRotDist, 0);
00136 EXPECT_LE(rotDist / totRotDist, 1);
00137 }
00138
00139 double rotDistToEnd = std::fabs(quat2.angleShortestPath(endQuat));
00140 EXPECT_LE(totRotDist - rotDistToEnd - rotDist, 0.0001);
00141 prevRotDist = rotDist;
00142 }
00143
00144
00145 double timeToFinish = ctptr->getDuration() * 2.;
00146 ctptr = ctg->getTrajectory(currPose, desPose, timeToFinish);
00147 EXPECT_EQ(timeToFinish, ctptr->getDuration());
00148 }
00149
00150 TEST_F(TrajectoryGeneratorTest, minJerkCartZeroVelTrajTest)
00151 {
00152 const double linVel = 0.05;
00153 const double rotVel = 0.3;
00154
00155 ctg->setVelocityLimits(0., rotVel);
00156
00157
00158 KDL::FrameAcc currPose, desPose;
00159 currPose.p.p.x(0.);
00160 currPose.p.p.y(0.);
00161 currPose.p.p.z(0.);
00162 currPose.M.R = KDL::Rotation::Quaternion(0, 0, 0, 1);
00163 desPose.p.p.x(1.);
00164 desPose.p.p.y(2.);
00165 desPose.p.p.z(3.);
00166 desPose.M.R = currPose.M.R;
00167 desPose.M.R.DoRotX(.3);
00168 desPose.M.R.DoRotY(.2);
00169 desPose.M.R.DoRotZ(.1);
00170 std::vector<KDL::FrameAcc> traj;
00171
00172 EXPECT_THROW(ctg->getTrajectory(currPose, desPose), std::runtime_error);
00173
00174 ctg->setVelocityLimits(linVel, 0.);
00175
00176 EXPECT_THROW(ctg->getTrajectory(currPose, desPose), std::runtime_error);
00177 }
00178
00179 TEST_F(TrajectoryGeneratorTest, minJerkJointGetSetTest)
00180 {
00181 std::vector<double> jntLimits(3);
00182 jntLimits.at(0) = .1;
00183 jntLimits.at(1) = .2;
00184 jntLimits.at(2) = .3;
00185
00186
00187 jtg->setLimits(jntLimits, std::vector<double>(3));
00188 EXPECT_EQ(jntLimits, jtg->getVelocityLimits());
00189
00190 for (unsigned int i = 0; i < jntLimits.size(); ++i)
00191 {
00192 EXPECT_EQ(jntLimits.at(i), jtg->getVelocityLimit(i));
00193 }
00194
00195 EXPECT_ANY_THROW(jtg->getVelocityLimit(jntLimits.size()));
00196 }
00197
00198 TEST_F(TrajectoryGeneratorTest, minJerkJointTrajTest)
00199 {
00200 std::vector<double> jntLimits(5);
00201 jntLimits.at(0) = .1;
00202 jntLimits.at(1) = .2;
00203 jntLimits.at(2) = .3;
00204 jntLimits.at(3) = .15;
00205 jntLimits.at(4) = .25;
00206
00207 KDL::JntArrayAcc jntStart(5);
00208 jntStart.q(0) = 0;
00209 jntStart.q(1) = 0;
00210 jntStart.q(2) = 0;
00211 jntStart.q(3) = 0;
00212 jntStart.q(4) = 0;
00213
00214 KDL::JntArrayAcc jntEnd(5);
00215 jntEnd.q(0) = 15.*3.14 / 180;
00216 jntEnd.q(1) = 20.*3.14 / 180;
00217 jntEnd.q(2) = 30.*3.14 / 180;
00218 jntEnd.q(3) = 25.*3.14 / 180;
00219 jntEnd.q(4) = 10.*3.14 / 180;
00220
00221 jtg->setLimits(jntLimits, std::vector<double>(5));
00222
00223
00224 KDL::JntArrayAcc startTest, endTest, testPose, testPose2;
00225 jtptr = jtg->getTrajectory(jntStart, jntEnd);
00226 jtptr->getPose(0., startTest);
00227 jtptr->getPose(jtptr->getDuration(), endTest);
00228 EXPECT_EQ(jntEnd.q, endTest.q);
00229 EXPECT_EQ(jntStart.q, startTest.q);
00230
00231 KDL::JntArray prevDist(5);
00232 KDL::JntArray totDist(jntStart.q.rows());
00233
00234 for (unsigned int i = 0; i < totDist.rows(); ++i)
00235 {
00236 totDist(i) = std::fabs(endTest.q(i) - startTest.q(i));
00237 }
00238
00239 double timeStep = 0.01;
00240 jtptr->getPose(0., testPose);
00241
00242 for (double time = timeStep; time < jtptr->getDuration(); time += timeStep)
00243 {
00244 testPose2 = testPose;
00245 jtptr->getPose(time, testPose);
00246
00247
00248 for (unsigned int j = 0; j < jntStart.q.rows(); ++j)
00249 {
00250
00251 EXPECT_LE((testPose.q(j) - testPose2.q(j)) / timeStep, jntLimits.at(j));
00252
00253
00254 double dist = std::fabs(testPose.q(j) - jntStart.q(j));
00255 EXPECT_GE(dist, prevDist(j));
00256
00257 if (totDist(j) > 0)
00258 {
00259 EXPECT_GE(dist / totDist(j), 0);
00260 EXPECT_LE(dist / totDist(j), 1);
00261 }
00262
00263 double distToEnd = std::fabs(endTest.q(j) - testPose.q(j));
00264 EXPECT_FLOAT_EQ(dist, totDist(j) - distToEnd);
00265 prevDist(j) = dist;
00266 }
00267 }
00268 }
00269
00270 TEST_F(TrajectoryGeneratorTest, minJerkJointZeroVelTrajTest)
00271 {
00272 std::vector<double> jntLimits(5);
00273 jntLimits.at(0) = .1;
00274 jntLimits.at(1) = .2;
00275 jntLimits.at(2) = .3;
00276 jntLimits.at(3) = .15;
00277 jntLimits.at(4) = .25;
00278
00279 KDL::JntArrayAcc jntStart(5);
00280 jntStart.q(0) = 0;
00281 jntStart.q(1) = 0;
00282 jntStart.q(2) = 0;
00283 jntStart.q(3) = 0;
00284 jntStart.q(4) = 0;
00285
00286 KDL::JntArrayAcc jntEnd(4);
00287 jntEnd.q(0) = 15.*3.14 / 180;
00288 jntEnd.q(1) = 20.*3.14 / 180;
00289 jntEnd.q(2) = 30.*3.14 / 180;
00290 jntEnd.q(3) = 25.*3.14 / 180;
00291
00292 jtg->setLimits(jntLimits, std::vector<double>(5));
00293
00294
00295 EXPECT_THROW(jtg->getTrajectory(jntStart, jntEnd), std::runtime_error);
00296
00297
00298 jntEnd.resize(5);
00299 jntEnd.q(0) = 15.*3.14 / 180;
00300 jntEnd.q(1) = 20.*3.14 / 180;
00301 jntEnd.q(2) = 30.*3.14 / 180;
00302 jntEnd.q(3) = 25.*3.14 / 180;
00303 jntEnd.q(4) = 10.*3.14 / 180;
00304 jntLimits.at(3) = 0.;
00305 jtg->setLimits(jntLimits, std::vector<double>(5));
00306 EXPECT_THROW(jtg->getTrajectory(jntStart, jntEnd), std::runtime_error);
00307 }
00308
00309 int main(int argc, char** argv)
00310 {
00311 testing::InitGoogleTest(&argc, argv);
00312 return RUN_ALL_TESTS();
00313 }