00001 #include <ros/ros.h>
00002 #include <nav_msgs/Odometry.h>
00003 #include <geometry_msgs/PoseWithCovarianceStamped.h>
00004 #include <geometry_msgs/TwistWithCovarianceStamped.h>
00005
00006 #include <gtest/gtest.h>
00007 #include <iostream>
00008
00009 #include <tf/tf.h>
00010
00011 nav_msgs::Odometry filtered_;
00012
00013 void resetFilter()
00014 {
00015 ros::NodeHandle nh;
00016 ros::Publisher setPosePub = nh.advertise<geometry_msgs::PoseWithCovarianceStamped>("/set_pose", 5);
00017
00018 bool poseChanged = false;
00019
00020 geometry_msgs::PoseWithCovarianceStamped pose;
00021 pose.pose.pose.orientation.w = 1;
00022 pose.header.frame_id = "odom";
00023 for(size_t ind = 0; ind < 36; ind+=7)
00024 {
00025 pose.pose.covariance[ind] = 1e-6;
00026 }
00027
00028
00029
00030 while(!poseChanged)
00031 {
00032 pose.header.stamp = ros::Time::now();
00033 setPosePub.publish(pose);
00034 pose.header.seq++;
00035 ros::spinOnce();
00036
00037 poseChanged = (filtered_.pose.pose.position.x == pose.pose.pose.position.x) &&
00038 (filtered_.pose.pose.position.y == pose.pose.pose.position.y) &&
00039 (filtered_.pose.pose.position.z == pose.pose.pose.position.z) &&
00040 (filtered_.pose.pose.orientation.x == pose.pose.pose.orientation.x) &&
00041 (filtered_.pose.pose.orientation.y == pose.pose.pose.orientation.y) &&
00042 (filtered_.pose.pose.orientation.z == pose.pose.pose.orientation.z) &&
00043 (filtered_.pose.pose.orientation.w == pose.pose.pose.orientation.w);
00044
00045 ros::Duration(0.1).sleep();
00046 }
00047
00048 }
00049
00050 void filterCallback(const nav_msgs::OdometryConstPtr &msg)
00051 {
00052 filtered_ = *msg;
00053 }
00054
00055 TEST (InterfacesTest, OdomPoseBasicIO)
00056 {
00057 ros::NodeHandle nh;
00058 ros::Publisher odomPub = nh.advertise<nav_msgs::Odometry>("/odom_input0", 5);
00059
00060 ros::Subscriber filteredSub = nh.subscribe("/odometry/filtered", 1, &filterCallback);
00061
00062 nav_msgs::Odometry odom;
00063 odom.pose.pose.position.x = 20.0;
00064 odom.pose.pose.position.y = 10.0;
00065 odom.pose.pose.position.z = -40.0;
00066
00067 odom.pose.covariance[0] = 2.0;
00068 odom.pose.covariance[7] = 2.0;
00069 odom.pose.covariance[14] = 2.0;
00070
00071 odom.header.frame_id = "odom";
00072 odom.child_frame_id = "base_link";
00073
00074 for(size_t i = 0; i < 10; ++i)
00075 {
00076 odom.header.stamp = ros::Time::now();
00077 odomPub.publish(odom);
00078 ros::spinOnce();
00079
00080 ros::Duration(0.1).sleep();
00081
00082 odom.header.seq++;
00083
00084
00085
00086
00087
00088
00089
00090 }
00091
00092
00093
00094 EXPECT_EQ(filtered_.pose.pose.position.x, odom.pose.pose.position.x);
00095 EXPECT_EQ(filtered_.pose.pose.position.y, 0);
00096 EXPECT_EQ(filtered_.pose.pose.position.z, odom.pose.pose.position.z);
00097
00098 EXPECT_LT(filtered_.pose.covariance[0], 0.5);
00099 EXPECT_LT(filtered_.pose.covariance[7], 0.25);
00100 EXPECT_LT(filtered_.pose.covariance[14], 0.5);
00101
00102 resetFilter();
00103 }
00104
00105 TEST (InterfacesTest, OdomTwistBasicIO)
00106 {
00107 ros::NodeHandle nh;
00108 ros::Publisher odomPub = nh.advertise<nav_msgs::Odometry>("/odom_input2", 5);
00109 ros::Publisher setPosePub = nh.advertise<geometry_msgs::PoseWithCovarianceStamped>("/set_pose", 5);
00110 ros::Subscriber filteredSub = nh.subscribe("/odometry/filtered", 1, &filterCallback);
00111
00112 nav_msgs::Odometry odom;
00113 odom.twist.twist.linear.x = 0;
00114 odom.twist.twist.linear.y = 0;
00115 odom.twist.twist.linear.z = 0;
00116 odom.twist.twist.angular.x = 0;
00117 odom.twist.twist.angular.y = 0;
00118 odom.twist.twist.angular.z = M_PI / 2.0;
00119
00120 odom.twist.covariance[0] = 1e-6;
00121 odom.twist.covariance[7] = 1e-6;
00122 odom.twist.covariance[14] = 1e-6;
00123 odom.twist.covariance[21] = 1e-6;
00124 odom.twist.covariance[28] = 1e-6;
00125 odom.twist.covariance[35] = 1e-6;
00126
00127 odom.header.frame_id = "odom";
00128 odom.child_frame_id = "base_link";
00129
00130 for(size_t i = 0; i < 10; ++i)
00131 {
00132 odom.header.stamp = ros::Time::now();
00133 odomPub.publish(odom);
00134 ros::spinOnce();
00135
00136 ros::Duration(0.1).sleep();
00137
00138 odom.header.seq++;
00139
00140
00141
00142
00143
00144
00145
00146 }
00147
00148 odom.twist.twist.linear.x = 0.5;
00149 odom.twist.twist.linear.y = 0;
00150 odom.twist.twist.linear.z = 0;
00151 odom.twist.twist.angular.x = 0;
00152 odom.twist.twist.angular.y = 0;
00153 odom.twist.twist.angular.z = 0;
00154
00155 for(size_t i = 0; i < 10; ++i)
00156 {
00157 odom.header.stamp = ros::Time::now();
00158 odomPub.publish(odom);
00159 ros::spinOnce();
00160
00161 ros::Duration(0.1).sleep();
00162
00163 odom.header.seq++;
00164 }
00165
00166
00167 EXPECT_LT(::fabs(filtered_.pose.pose.position.x), 0.2);
00168 EXPECT_LT(::fabs(filtered_.pose.pose.position.y - 0.5), 0.2);
00169
00170 resetFilter();
00171 }
00172
00173 TEST (InterfacesTest, PoseBasicIO)
00174 {
00175 ros::NodeHandle nh;
00176 ros::Publisher posePub = nh.advertise<geometry_msgs::PoseWithCovarianceStamped>("/pose_input0", 5);
00177 ros::Subscriber filteredSub = nh.subscribe("/odometry/filtered", 1, &filterCallback);
00178
00179 geometry_msgs::PoseWithCovarianceStamped pose;
00180 pose.pose.pose.position.x = 20.0;
00181 pose.pose.pose.position.y = 10.0;
00182 pose.pose.pose.position.z = -40.0;
00183 pose.pose.pose.orientation.x = 0;
00184 pose.pose.pose.orientation.y = 0;
00185 pose.pose.pose.orientation.z = 0;
00186 pose.pose.pose.orientation.w = 1;
00187
00188 for(size_t ind = 0; ind < 36; ind+=7)
00189 {
00190 pose.pose.covariance[ind] = 1e-6;
00191 }
00192
00193 pose.header.frame_id = "odom";
00194
00195 bool poseChanged = false;
00196
00197
00198
00199 while(!poseChanged)
00200 {
00201 pose.header.stamp = ros::Time::now();
00202 posePub.publish(pose);
00203 pose.header.seq++;
00204 ros::spinOnce();
00205
00206 poseChanged = ::fabs(filtered_.pose.pose.position.x - pose.pose.pose.position.x) < 1e-5 &&
00207 ::fabs(filtered_.pose.pose.position.z - pose.pose.pose.position.z) < 1e-5;
00208
00209 ros::Duration(0.1).sleep();
00210 }
00211
00212
00213 EXPECT_LT(filtered_.pose.pose.position.y, 1e-7);
00214 EXPECT_LT(filtered_.pose.covariance[0], 0.1);
00215 EXPECT_LT(filtered_.pose.covariance[7], 2.0);
00216 EXPECT_LT(filtered_.pose.covariance[14], 0.1);
00217
00218 poseChanged = false;
00219
00220 resetFilter();
00221 }
00222
00223 TEST (InterfacesTest, TwistBasicIO)
00224 {
00225 ros::NodeHandle nh;
00226 ros::Publisher twistPub = nh.advertise<geometry_msgs::TwistWithCovarianceStamped>("/twist_input0", 5);
00227 ros::Subscriber filteredSub = nh.subscribe("/odometry/filtered", 1, &filterCallback);
00228
00229 geometry_msgs::TwistWithCovarianceStamped twist;
00230 twist.twist.twist.linear.x = 0;
00231 twist.twist.twist.linear.y = 0;
00232 twist.twist.twist.linear.z = 0;
00233 twist.twist.twist.angular.x = M_PI / 2.0;
00234 twist.twist.twist.angular.y = 0;
00235 twist.twist.twist.angular.z = 0;
00236
00237 twist.twist.covariance[0] = 1e-6;
00238 twist.twist.covariance[7] = 1e-6;
00239 twist.twist.covariance[14] = 1e-6;
00240 twist.twist.covariance[21] = 1e-6;
00241 twist.twist.covariance[28] = 1e-6;
00242 twist.twist.covariance[35] = 1e-6;
00243
00244 twist.header.frame_id = "base_link";
00245
00246 for(size_t i = 0; i < 10; ++i)
00247 {
00248 twist.header.stamp = ros::Time::now();
00249 twistPub.publish(twist);
00250 ros::spinOnce();
00251
00252 ros::Duration(0.1).sleep();
00253
00254 twist.header.seq++;
00255
00256
00257
00258
00259
00260
00261
00262 }
00263
00264 twist.twist.twist.linear.x = 0;
00265 twist.twist.twist.linear.y = -0.5;
00266 twist.twist.twist.linear.z = 0;
00267 twist.twist.twist.angular.x = 0;
00268 twist.twist.twist.angular.y = 0;
00269 twist.twist.twist.angular.z = 0;
00270
00271 for(size_t i = 0; i < 10; ++i)
00272 {
00273 twist.header.stamp = ros::Time::now();
00274 twistPub.publish(twist);
00275 ros::spinOnce();
00276
00277 ros::Duration(0.1).sleep();
00278
00279 twist.header.seq++;
00280 }
00281
00282 EXPECT_LT(::fabs(filtered_.pose.pose.position.y), 0.2);
00283 EXPECT_LT(::fabs(filtered_.pose.pose.position.z + 0.5), 0.2);
00284
00285 resetFilter();
00286 }
00287
00288 TEST (InterfacesTest, OdomDifferentialIO)
00289 {
00290 ros::NodeHandle nh;
00291 ros::Publisher odomPub = nh.advertise<nav_msgs::Odometry>("/odom_input1", 5);
00292 ros::Subscriber filteredSub = nh.subscribe("/odometry/filtered", 1, &filterCallback);
00293
00294 nav_msgs::Odometry odom;
00295 odom.pose.pose.position.x = 20.0;
00296 odom.pose.pose.position.y = 10.0;
00297 odom.pose.pose.position.z = -40.0;
00298
00299 odom.pose.covariance[0] = 2.0;
00300 odom.pose.covariance[7] = 2.0;
00301 odom.pose.covariance[14] = 2.0;
00302
00303 odom.pose.pose.orientation.w = 1;
00304
00305 odom.pose.covariance[21] = 0.2;
00306 odom.pose.covariance[28] = 0.2;
00307 odom.pose.covariance[35] = 0.2;
00308
00309 odom.header.frame_id = "odom";
00310 odom.child_frame_id = "base_link";
00311
00312
00313
00314
00315
00316 size_t zeroCount = 0;
00317 while(zeroCount++ < 10)
00318 {
00319 odom.header.stamp = ros::Time::now();
00320 odomPub.publish(odom);
00321 ros::spinOnce();
00322
00323 EXPECT_EQ(filtered_.pose.pose.position.x, 0);
00324 EXPECT_EQ(filtered_.pose.pose.position.y, 0);
00325 EXPECT_EQ(filtered_.pose.pose.position.z, 0);
00326 EXPECT_EQ(filtered_.pose.pose.orientation.x, 0);
00327 EXPECT_EQ(filtered_.pose.pose.orientation.y, 0);
00328 EXPECT_EQ(filtered_.pose.pose.orientation.z, 0);
00329 EXPECT_EQ(filtered_.pose.pose.orientation.w, 1);
00330
00331 ros::Duration(0.1).sleep();
00332
00333 odom.header.seq++;
00334 }
00335
00336
00337
00338
00339 odom.pose.pose.position.x = 21;
00340 odom.pose.pose.position.y = 12.0;
00341 odom.pose.pose.position.z = -43.0;
00342
00343
00344 for(size_t ind = 0; ind < 36; ind+=7)
00345 {
00346 odom.pose.covariance[ind] = 1e-6;
00347 }
00348
00349 bool poseChanged = false;
00350
00351 while(!poseChanged)
00352 {
00353 odom.header.stamp = ros::Time::now();
00354 odomPub.publish(odom);
00355
00356 ros::spinOnce();
00357
00358 poseChanged = (::fabs(filtered_.pose.pose.position.x - 1) < 1e-4) &&
00359 (::fabs(filtered_.pose.pose.position.y - 2) < 1e-4) &&
00360 (::fabs(filtered_.pose.pose.position.z + 3) < 1e-4) &&
00361 (filtered_.pose.pose.orientation.x == 0) &&
00362 (filtered_.pose.pose.orientation.y == 0) &&
00363 (filtered_.pose.pose.orientation.z == 0) &&
00364 (filtered_.pose.pose.orientation.w == 1);
00365
00366 ros::Duration(0.1).sleep();
00367 odom.header.seq++;
00368 }
00369
00370 poseChanged = false;
00371
00372 resetFilter();
00373 }
00374
00375 TEST (InterfacesTest, PoseDifferentialIO)
00376 {
00377 ros::NodeHandle nh;
00378 ros::Publisher posePub = nh.advertise<geometry_msgs::PoseWithCovarianceStamped>("/pose_input1", 5);
00379 ros::Subscriber filteredSub = nh.subscribe("/odometry/filtered", 1, &filterCallback);
00380
00381 geometry_msgs::PoseWithCovarianceStamped pose;
00382 pose.pose.pose.position.x = 20.0;
00383 pose.pose.pose.position.y = 10.0;
00384 pose.pose.pose.position.z = -40.0;
00385 pose.pose.pose.orientation.x = 0;
00386 pose.pose.pose.orientation.y = 0;
00387 pose.pose.pose.orientation.z = 0;
00388 pose.pose.pose.orientation.w = 1;
00389
00390 for(size_t ind = 0; ind < 36; ind+=7)
00391 {
00392 pose.pose.covariance[ind] = 1e-6;
00393 }
00394
00395 pose.header.frame_id = "odom";
00396
00397 bool poseChanged = false;
00398
00399
00400
00401
00402
00403 size_t zeroCount = 0;
00404 while(zeroCount++ < 10)
00405 {
00406 pose.header.stamp = ros::Time::now();
00407 posePub.publish(pose);
00408 pose.header.seq++;
00409 ros::spinOnce();
00410
00411 EXPECT_EQ(filtered_.pose.pose.position.x, 0);
00412 EXPECT_EQ(filtered_.pose.pose.position.y, 0);
00413 EXPECT_EQ(filtered_.pose.pose.position.z, 0);
00414 EXPECT_EQ(filtered_.pose.pose.orientation.x, 0);
00415 EXPECT_EQ(filtered_.pose.pose.orientation.y, 0);
00416 EXPECT_EQ(filtered_.pose.pose.orientation.z, 0);
00417 EXPECT_EQ(filtered_.pose.pose.orientation.w, 1);
00418
00419 ros::Duration(0.1).sleep();
00420 }
00421
00422 resetFilter();
00423 }
00424
00425 int main(int argc, char **argv)
00426 {
00427 testing::InitGoogleTest(&argc, argv);
00428
00429 ros::init(argc, argv, "ekf_navigation_node-test-interfaces");
00430 ros::Time::init();
00431
00432
00433 ros::Duration(2.0).sleep();
00434
00435 return RUN_ALL_TESTS();
00436 }