38 #include <costmap_cspace_msgs/CSpace3D.h> 39 #include <nav_msgs/GetPlan.h> 40 #include <nav_msgs/OccupancyGrid.h> 41 #include <nav_msgs/Path.h> 42 #include <planner_cspace_msgs/PlannerStatus.h> 43 #include <std_srvs/Empty.h> 48 #include <gtest/gtest.h> 52 std::ostream&
operator<<(std::ostream& os,
const PlannerStatus::ConstPtr& msg)
61 <<
" header: " << msg->header.stamp <<
" " << msg->header.frame_id << std::endl
62 <<
" status: " <<
static_cast<int>(msg->status) << std::endl
63 <<
" error: " << static_cast<int>(msg->error);
75 nav_msgs::OccupancyGrid::ConstPtr
map_;
78 costmap_cspace_msgs::CSpace3D::ConstPtr
costmap_;
90 std::vector<tf2::Stamped<tf2::Transform>>
traj_;
95 , local_map_apply_cnt_(0)
104 nh_.
serviceClient<std_srvs::EmptyRequest, std_srvs::EmptyResponse>(
105 "forget_planning_cost");
106 pub_map_ = nh_.
advertise<nav_msgs::OccupancyGrid>(
"map", 1,
true);
107 pub_map_local_ = nh_.
advertise<nav_msgs::OccupancyGrid>(
"overlay", 1,
true);
109 nh_.
advertise<geometry_msgs::PoseWithCovarianceStamped>(
"initialpose", 1,
true);
114 test_scope_ =
"[" + std::to_string(getpid()) +
"] ";
119 geometry_msgs::PoseWithCovarianceStamped pose;
120 pose.header.frame_id =
"map";
121 pose.pose.pose.position.x = 2.5;
122 pose.pose.pose.position.y = 0.45;
123 pose.pose.pose.orientation.z = 1.0;
124 pub_initial_pose_.
publish(pose);
135 FAIL() << test_scope_ << now <<
" SetUp: transform timeout" << std::endl;
150 FAIL() << test_scope_ << now <<
" SetUp: map timeout" << std::endl;
154 std::cerr << test_scope_ <<
ros::Time::now() <<
" Map applied." << std::endl;
163 FAIL() << test_scope_ << now <<
" SetUp: costmap timeout" << std::endl;
167 std_srvs::EmptyRequest req;
168 std_srvs::EmptyResponse res;
169 srv_forget_.
call(req, res);
173 void cbCostmap(
const costmap_cspace_msgs::CSpace3D::ConstPtr& msg)
176 std::cerr << test_scope_ << msg->header.stamp <<
" Costmap received." << std::endl;
178 void cbMap(
const nav_msgs::OccupancyGrid::ConstPtr& msg)
181 std::cerr << test_scope_ << msg->header.stamp <<
" Map received." << std::endl;
183 void cbMapLocal(
const nav_msgs::OccupancyGrid::ConstPtr& msg)
186 std::cerr << test_scope_ << msg->header.stamp <<
" Local map received." << std::endl;
188 void cbStatus(
const planner_cspace_msgs::PlannerStatus::ConstPtr& msg)
190 if (!planner_status_ || planner_status_->status != msg->status || planner_status_->error != msg->error)
192 std::cerr << test_scope_ << msg->header.stamp <<
" Status updated." << msg << std::endl;
194 planner_status_ = msg;
196 void cbPath(
const nav_msgs::Path::ConstPtr& msg)
198 if (!path_ || path_->poses.size() != msg->poses.size())
200 if (msg->poses.size() == 0)
202 std::cerr << test_scope_ << msg->header.stamp <<
" Path updated. (empty)" << std::endl;
207 << test_scope_ << msg->header.stamp <<
" Path updated." << std::endl
208 << msg->poses.front().pose.position.x <<
", " << msg->poses.front().pose.position.y << std::endl
209 << msg->poses.back().pose.position.x <<
", " << msg->poses.back().pose.position.y << std::endl;
218 pub_map_local_.
publish(map_local_);
219 if ((local_map_apply_cnt_++) % 30 == 0)
220 std::cerr << test_scope_ <<
" Local map applied." << std::endl;
225 geometry_msgs::TransformStamped trans_tmp =
229 traj_.push_back(trans);
234 double x_prev(0), y_prev(0);
237 std::cerr << test_scope_ << traj_.size() <<
" points recorded" << std::endl;
239 for (
const auto&
t : traj_)
241 const double x =
t.getOrigin().getX();
242 const double y =
t.getOrigin().getY();
245 if (std::abs(x - x_prev) > 0.1 || std::abs(y - y_prev) > 0.1 || std::abs(yaw_diff) > 0.2)
250 std::cerr <<
t.stamp_ <<
" " << x <<
" " << y <<
" " <<
tf2::getYaw(rot) << std::endl;
258 ros::Publisher pub_path = nh_.advertise<nav_msgs::Path>(
"patrol_nodes", 1,
true);
261 ASSERT_TRUE(static_cast<bool>(map_));
264 path.poses.resize(2);
265 path.header.frame_id =
"map";
266 path.poses[0].header.frame_id = path.header.frame_id;
267 path.poses[0].pose.position.x = 1.7;
268 path.poses[0].pose.position.y = 2.8;
270 path.poses[1].header.frame_id = path.header.frame_id;
271 path.poses[1].pose.position.x = 1.9;
272 path.poses[1].pose.position.y = 2.8;
290 dumpRobotTrajectory();
292 << test_scope_ <<
"Navigation timeout." << std::endl
293 <<
"now: " << now << std::endl
294 <<
"status: " << planner_status_;
301 trans = lookupRobotTrans(now);
305 std::cerr << test_scope_ << e.what() << std::endl;
309 auto goal_rel = trans.inverse() * goal;
310 if (goal_rel.getOrigin().length() < 0.2 &&
311 std::abs(
tf2::getYaw(goal_rel.getRotation())) < 0.2)
313 std::cerr << test_scope_ <<
"Navigation success." << std::endl;
318 for (
int x = -2; x <= 2; ++x)
320 for (
int y = -1; y <= 1; ++y)
322 const tf2::Vector3 pos =
323 trans * tf2::Vector3(x * map_->info.resolution, y * map_->info.resolution, 0);
324 const int map_x = pos.x() / map_->info.resolution;
325 const int map_y = pos.y() / map_->info.resolution;
326 const size_t addr = map_x + map_y * map_->info.width;
327 ASSERT_LT(addr, map_->data.size());
328 ASSERT_LT(map_x, static_cast<int>(map_->info.width));
329 ASSERT_LT(map_y, static_cast<int>(map_->info.height));
332 ASSERT_NE(map_->data[addr], 100);
341 ros::Publisher pub_path = nh_.advertise<nav_msgs::Path>(
"patrol_nodes", 1,
true);
344 ASSERT_TRUE(static_cast<bool>(map_));
345 ASSERT_TRUE(static_cast<bool>(map_local_));
350 path.poses.resize(1);
351 path.header.frame_id =
"map";
352 path.poses[0].header.frame_id = path.header.frame_id;
353 path.poses[0].pose.position.x = 1.7;
354 path.poses[0].pose.position.y = 2.8;
373 dumpRobotTrajectory();
375 << test_scope_ <<
"Navigation timeout." << std::endl
376 <<
"now: " << now << std::endl
377 <<
"status: " << planner_status_;
384 trans = lookupRobotTrans(now);
388 std::cerr << test_scope_ << e.what() << std::endl;
392 auto goal_rel = trans.inverse() * goal;
393 if (goal_rel.getOrigin().length() < 0.2 &&
394 std::abs(
tf2::getYaw(goal_rel.getRotation())) < 0.2)
396 std::cerr << test_scope_ <<
"Navagation success." << std::endl;
401 for (
int x = -2; x <= 2; ++x)
403 for (
int y = -1; y <= 1; ++y)
405 const tf2::Vector3 pos =
406 trans * tf2::Vector3(x * map_->info.resolution, y * map_->info.resolution, 0);
407 const int map_x = pos.x() / map_->info.resolution;
408 const int map_y = pos.y() / map_->info.resolution;
409 const size_t addr = map_x + map_y * map_->info.width;
410 ASSERT_LT(addr, map_->data.size());
411 ASSERT_LT(map_x, static_cast<int>(map_->info.width));
412 ASSERT_LT(map_y, static_cast<int>(map_->info.height));
415 ASSERT_NE(map_->data[addr], 100);
416 ASSERT_NE(map_local_->data[addr], 100);
426 nh_.serviceClient<nav_msgs::GetPlanRequest, nav_msgs::GetPlanResponse>(
427 "/planner_3d/make_plan");
430 ASSERT_TRUE(static_cast<bool>(map_));
432 nav_msgs::GetPlanRequest req;
433 nav_msgs::GetPlanResponse res;
436 req.start.header.frame_id =
"map";
437 req.start.pose.position.x = 1.95;
438 req.start.pose.position.y = 0.45;
439 req.start.pose.orientation =
442 req.goal.header.frame_id =
"map";
443 req.goal.pose.position.x = 1.25;
444 req.goal.pose.position.y = 2.15;
445 req.goal.pose.orientation =
448 ASSERT_FALSE(srv_plan.
call(req, res));
452 ASSERT_TRUE(srv_plan.
call(req, res));
453 EXPECT_NEAR(1.25, res.plan.poses.back().pose.position.x, 1.0e-5);
454 EXPECT_NEAR(2.25, res.plan.poses.back().pose.position.y, 1.0e-5);
457 req.tolerance = 0.2f;
458 ASSERT_TRUE(srv_plan.
call(req, res));
459 EXPECT_NEAR(1.25, res.plan.poses.back().pose.position.x, 1.0e-5);
460 EXPECT_NEAR(2.35, res.plan.poses.back().pose.position.y, 1.0e-5);
463 req.goal.header.frame_id =
"map";
464 req.goal.pose.position.x = 1.85;
465 req.goal.pose.position.y = 2.75;
466 req.goal.pose.orientation =
468 ASSERT_TRUE(srv_plan.
call(req, res));
470 EXPECT_NEAR(req.start.pose.position.x, res.plan.poses.front().pose.position.x, 1.0e-5);
471 EXPECT_NEAR(req.start.pose.position.y, res.plan.poses.front().pose.position.y, 1.0e-5);
472 EXPECT_NEAR(req.goal.pose.position.x, res.plan.poses.back().pose.position.x, 1.0e-5);
473 EXPECT_NEAR(req.goal.pose.position.y, res.plan.poses.back().pose.position.y, 1.0e-5);
475 for (
const geometry_msgs::PoseStamped& p : res.plan.poses)
477 const int map_x = p.pose.position.x / map_->info.resolution;
478 const int map_y = p.pose.position.y / map_->info.resolution;
479 const size_t addr = map_x + map_y * map_->info.width;
480 ASSERT_LT(addr, map_->data.size());
481 ASSERT_LT(map_x, static_cast<int>(map_->info.width));
482 ASSERT_LT(map_y, static_cast<int>(map_->info.height));
485 ASSERT_NE(map_->data[addr], 100);
491 ros::Publisher pub_path = nh_.advertise<nav_msgs::Path>(
"patrol_nodes", 1,
true);
494 ASSERT_TRUE(static_cast<bool>(map_));
495 ASSERT_TRUE(static_cast<bool>(map_local_));
500 path.poses.resize(1);
501 path.header.frame_id =
"map";
502 path.poses[0].header.frame_id = path.header.frame_id;
503 path.poses[0].pose.position.x = 1.19;
504 path.poses[0].pose.position.y = 1.90;
505 path.poses[0].pose.orientation.w = 1.0;
523 dumpRobotTrajectory();
525 << test_scope_ <<
"Navigation timeout." << std::endl
526 <<
"now: " << now << std::endl
527 <<
"status: " << planner_status_;
531 if (planner_status_->error == planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND)
539 int main(
int argc,
char** argv)
541 testing::InitGoogleTest(&argc, argv);
544 return RUN_ALL_TESTS();
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
void cbStatus(const planner_cspace_msgs::PlannerStatus::ConstPtr &msg)
void cbMap(const nav_msgs::OccupancyGrid::ConstPtr &msg)
nav_msgs::OccupancyGrid::ConstPtr map_
TEST_F(Navigate, Navigate)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::vector< tf2::Stamped< tf2::Transform > > traj_
void cbCostmap(const costmap_cspace_msgs::CSpace3D::ConstPtr &msg)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
bool call(MReq &req, MRes &res)
nav_msgs::Path::ConstPtr path_
costmap_cspace_msgs::CSpace3D::ConstPtr costmap_
ros::Subscriber sub_map_local_
geometry_msgs::TransformStamped t
ros::Subscriber sub_path_
tf2::Stamped< tf2::Transform > lookupRobotTrans(const ros::Time &now)
planner_cspace_msgs::PlannerStatus::ConstPtr planner_status_
nav_msgs::OccupancyGrid::ConstPtr map_local_
tf2_ros::TransformListener tfl_
virtual bool canTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &target_time, const ros::Duration timeout, std::string *errstr=NULL) const
std::ostream & operator<<(std::ostream &os, const PlannerStatus::ConstPtr &msg)
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
ros::Subscriber sub_costmap_
void publish(const boost::shared_ptr< M > &message) const
ros::Publisher pub_initial_pose_
bool waitForExistence(ros::Duration timeout=ros::Duration(-1))
void dumpRobotTrajectory()
void fromMsg(const A &, B &b)
ros::ServiceClient srv_forget_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
double getYaw(const A &a)
ros::Subscriber sub_status_
ros::Publisher pub_map_local_
tf2Scalar angleShortestPath(const Quaternion &q) const
ROSCPP_DECL void spinOnce()
void cbPath(const nav_msgs::Path::ConstPtr &msg)
size_t local_map_apply_cnt_
void cbMapLocal(const nav_msgs::OccupancyGrid::ConstPtr &msg)
int main(int argc, char **argv)