00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <ros/ros.h>
00031 #include <tf2/utils.h>
00032 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
00033 #include <tf2_ros/transform_listener.h>
00034 #include <nav_msgs/Path.h>
00035 #include <nav_msgs/GetPlan.h>
00036 #include <nav_msgs/OccupancyGrid.h>
00037
00038 #include <cstddef>
00039
00040 #include <gtest/gtest.h>
00041
00042 TEST(Navigate, Navigate)
00043 {
00044 nav_msgs::OccupancyGrid::ConstPtr map;
00045
00046 const boost::function<void(const nav_msgs::OccupancyGrid::ConstPtr&)> cb_map =
00047 [&map](const nav_msgs::OccupancyGrid::ConstPtr& msg) -> void
00048 {
00049 map = msg;
00050 std::cerr << "Map received." << std::endl;
00051 };
00052
00053 ros::NodeHandle nh("");
00054 tf2_ros::Buffer tfbuf;
00055 tf2_ros::TransformListener tfl(tfbuf);
00056 ros::Publisher pub_path = nh.advertise<nav_msgs::Path>("patrol_nodes", 1, true);
00057 ros::Subscriber sub_map = nh.subscribe("map", 1, cb_map);
00058
00059 ros::Duration(2.0).sleep();
00060 nav_msgs::Path path;
00061 path.poses.resize(2);
00062 path.header.frame_id = "map";
00063 path.poses[0].header.frame_id = path.header.frame_id;
00064 path.poses[0].pose.position.x = 1.7;
00065 path.poses[0].pose.position.y = 2.8;
00066 path.poses[0].pose.orientation = tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), -3.14));
00067 path.poses[1].header.frame_id = path.header.frame_id;
00068 path.poses[1].pose.position.x = 1.9;
00069 path.poses[1].pose.position.y = 2.8;
00070 path.poses[1].pose.orientation = tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), -1.57));
00071 pub_path.publish(path);
00072
00073 tf2::Transform goal;
00074 tf2::fromMsg(path.poses.back().pose, goal);
00075
00076 ros::Rate wait(10);
00077 while (ros::ok())
00078 {
00079 ros::spinOnce();
00080 wait.sleep();
00081
00082 tf2::Stamped<tf2::Transform> trans;
00083 try
00084 {
00085 const ros::Time now = ros::Time::now();
00086 geometry_msgs::TransformStamped trans_tmp =
00087 tfbuf.lookupTransform("map", "base_link", now, ros::Duration(0.5));
00088 tf2::fromMsg(trans_tmp, trans);
00089 }
00090 catch (tf2::TransformException& e)
00091 {
00092 std::cerr << e.what() << std::endl;
00093 continue;
00094 }
00095
00096 auto goal_rel = trans.inverse() * goal;
00097 if (goal_rel.getOrigin().length() < 0.2 &&
00098 fabs(tf2::getYaw(goal_rel.getRotation())) < 0.2)
00099 {
00100 std::cerr << "Navagation success." << std::endl;
00101 ros::Duration(2.0).sleep();
00102 return;
00103 }
00104
00105 if (!map)
00106 {
00107 std::cerr << "Waiting map." << std::endl;
00108 continue;
00109 }
00110
00111 for (int x = -2; x <= 2; ++x)
00112 {
00113 for (int y = -1; y <= 1; ++y)
00114 {
00115 const tf2::Vector3 pos =
00116 trans * tf2::Vector3(x * map->info.resolution, y * map->info.resolution, 0);
00117 const int map_x = pos.x() / map->info.resolution;
00118 const int map_y = pos.y() / map->info.resolution;
00119 const size_t addr = map_x + map_y * map->info.width;
00120 ASSERT_LT(addr, map->data.size());
00121 ASSERT_LT(map_x, static_cast<int>(map->info.width));
00122 ASSERT_LT(map_y, static_cast<int>(map->info.height));
00123 ASSERT_GE(map_x, 0);
00124 ASSERT_GE(map_y, 0);
00125 ASSERT_NE(map->data[addr], 100);
00126 }
00127 }
00128 }
00129 ASSERT_TRUE(false);
00130 }
00131
00132 TEST(Navigate, GlobalPlan)
00133 {
00134 nav_msgs::OccupancyGrid::ConstPtr map;
00135
00136 const boost::function<void(const nav_msgs::OccupancyGrid::ConstPtr&)> cb_map =
00137 [&map](const nav_msgs::OccupancyGrid::ConstPtr& msg) -> void
00138 {
00139 map = msg;
00140 std::cerr << "Map received." << std::endl;
00141 };
00142
00143 ros::NodeHandle nh("");
00144 tf2_ros::Buffer tfbuf;
00145 tf2_ros::TransformListener tfl(tfbuf);
00146 ros::ServiceClient srv_plan =
00147 nh.serviceClient<nav_msgs::GetPlanRequest, nav_msgs::GetPlanResponse>(
00148 "/planner_3d/make_plan");
00149 ros::Subscriber sub_map = nh.subscribe("map", 1, cb_map);
00150
00151 ros::Duration(2.0).sleep();
00152 ros::spinOnce();
00153 ASSERT_TRUE(static_cast<bool>(map));
00154
00155 nav_msgs::GetPlanRequest req;
00156 nav_msgs::GetPlanResponse res;
00157
00158 req.start.header.frame_id = "map";
00159 req.start.pose.position.x = 2.0;
00160 req.start.pose.position.y = 0.45;
00161 req.start.pose.orientation =
00162 tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), 3.14));
00163
00164 req.goal.header.frame_id = "map";
00165 req.goal.pose.position.x = 1.2;
00166 req.goal.pose.position.y = 1.9;
00167 req.goal.pose.orientation =
00168 tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), -3.14));
00169 ASSERT_FALSE(srv_plan.call(req, res));
00170
00171 req.goal.header.frame_id = "map";
00172 req.goal.pose.position.x = 1.9;
00173 req.goal.pose.position.y = 2.8;
00174 req.goal.pose.orientation =
00175 tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), -1.57));
00176 ASSERT_TRUE(srv_plan.call(req, res));
00177
00178 ASSERT_NEAR(req.start.pose.position.x, res.plan.poses.front().pose.position.x, 0.1);
00179 ASSERT_NEAR(req.start.pose.position.y, res.plan.poses.front().pose.position.y, 0.1);
00180 ASSERT_NEAR(req.goal.pose.position.x, res.plan.poses.back().pose.position.x, 0.1);
00181 ASSERT_NEAR(req.goal.pose.position.y, res.plan.poses.back().pose.position.y, 0.1);
00182
00183 for (const geometry_msgs::PoseStamped& p : res.plan.poses)
00184 {
00185 const int map_x = p.pose.position.x / map->info.resolution;
00186 const int map_y = p.pose.position.y / map->info.resolution;
00187 const size_t addr = map_x + map_y * map->info.width;
00188 ASSERT_LT(addr, map->data.size());
00189 ASSERT_LT(map_x, static_cast<int>(map->info.width));
00190 ASSERT_LT(map_y, static_cast<int>(map->info.height));
00191 ASSERT_GE(map_x, 0);
00192 ASSERT_GE(map_y, 0);
00193 ASSERT_NE(map->data[addr], 100);
00194 }
00195 }
00196
00197 int main(int argc, char** argv)
00198 {
00199 testing::InitGoogleTest(&argc, argv);
00200 ros::init(argc, argv, "test_navigate");
00201
00202 return RUN_ALL_TESTS();
00203 }