33 #include <gtest/gtest.h>
35 #include <dynamic_reconfigure/client.h>
36 #include <move_base_msgs/MoveBaseAction.h>
37 #include <nav_msgs/OccupancyGrid.h>
38 #include <nav_msgs/Odometry.h>
39 #include <planner_cspace/Planner3DConfig.h>
47 :
public ActionTestBase<move_base_msgs::MoveBaseAction, ACTION_TOPIC_MOVE_BASE>
54 new dynamic_reconfigure::Client<planner_cspace::Planner3DConfig>(
"/planner_3d/"));
100 void cbPath(
const nav_msgs::Path::ConstPtr& msg)
109 move_base_msgs::MoveBaseGoal goal;
111 goal.target_pose.header.frame_id =
"map";
112 goal.target_pose.pose.position.x = 1.25;
113 goal.target_pose.pose.position.y = 1.05;
114 goal.target_pose.pose.position.z = 0.0;
115 goal.target_pose.pose.orientation.x = 0.0;
116 goal.target_pose.pose.orientation.y = 0.0;
117 goal.target_pose.pose.orientation.z = std::sin(M_PI / 4);
118 goal.target_pose.pose.orientation.w = std::cos(M_PI / 4);
124 for (
size_t i = 0; i <
path_->poses.size() - 1; ++i)
126 const auto& pose1 =
path_->poses[i];
127 const auto& pose2 =
path_->poses[i + 1];
128 const double distance = std::hypot(pose1.pose.position.x - pose2.pose.position.x,
129 pose1.pose.position.y - pose2.pose.position.y);
130 const double yaw_diff = std::abs(
tf2::getYaw(pose1.pose.orientation) -
tf2::getYaw(pose2.pose.orientation));
131 if (distance > 1.0e-3 && yaw_diff > 1.0e-3)
139 ::testing::AssertionResult
comparePath(
const nav_msgs::Path& path1,
const nav_msgs::Path& path2)
141 if (path1.poses.size() != path2.poses.size())
143 return ::testing::AssertionFailure()
144 <<
"Path size different: " << path1.poses.size() <<
" != " << path2.poses.size();
146 for (
size_t i = 0; i < path1.poses.size(); ++i)
148 const geometry_msgs::Point& pos1 = path1.poses[i].pose.position;
149 const geometry_msgs::Point& pos2 = path2.poses[i].pose.position;
150 if (std::abs(pos1.x - pos2.x) > 1.0e-6)
152 return ::testing::AssertionFailure() <<
"X different at #" << i <<
": " << pos1.x <<
" != " << pos2.x;
154 if (std::abs(pos1.y - pos2.y) > 1.0e-6)
156 return ::testing::AssertionFailure() <<
"Y different at #" << i <<
": " << pos1.y <<
" != " << pos2.y;
158 const double yaw1 =
tf2::getYaw(path1.poses[i].pose.orientation);
159 const double yaw2 =
tf2::getYaw(path2.poses[i].pose.orientation);
160 if (std::abs(yaw1 - yaw2) > 1.0e-6)
162 return ::testing::AssertionFailure() <<
"Yaw different at #" << i <<
": " << yaw1 <<
" != " << yaw2;
165 return ::testing::AssertionSuccess();
181 if (
path_ && (
path_->header.stamp > start_time) && (
path_->poses.size() > 0))
193 geometry_msgs::TransformStamped trans;
194 trans.header.stamp = current_time;
195 trans.header.frame_id =
"odom";
196 trans.child_frame_id =
"base_link";
197 trans.transform.translation =
tf2::toMsg(tf2::Vector3(x, y, 0.0));
201 nav_msgs::Odometry odom;
202 odom.header.frame_id =
"odom";
203 odom.header.stamp = current_time;
204 odom.child_frame_id =
"base_link";
205 odom.pose.pose.position.x = x;
206 odom.pose.pose.position.y = y;
229 if ((
ros::Time::now() - last_costmap_publishing_time) > costmap_publishing_interval)
241 if ((
ros::Time::now() - last_costmap_publishing_time) > costmap_publishing_interval)
267 publishMapAndRobot(2.55, 0.45, M_PI);
270 sendGoalAndWaitForPath();
272 EXPECT_TRUE(isPathIncludingCurves());
274 planner_cspace::Planner3DConfig config = default_config_;
276 config.min_curve_radius = 10.0;
277 ASSERT_TRUE(planner_3d_client_->setConfiguration(config));
279 sendGoalAndWaitForPath();
281 EXPECT_FALSE(isPathIncludingCurves());
286 publishMapAndRobot(1.65, 0.65, M_PI);
288 sendGoalAndWaitForPath();
289 const nav_msgs::Path initial_path = *path_;
292 map_overlay_.data[13 + 5 * map_overlay_.info.width] = 100;
293 publishMapAndRobot(1.65, 0.65, M_PI);
295 sendGoalAndWaitForPath();
296 EXPECT_FALSE(comparePath(initial_path, *path_));
299 move_base_->cancelAllGoals();
300 planner_cspace::Planner3DConfig config = default_config_;
301 config.keep_a_part_of_previous_path =
true;
302 config.dist_stop_to_previous_path = 0.1;
303 ASSERT_TRUE(planner_3d_client_->setConfiguration(config));
306 map_overlay_.data[13 + 5 * map_overlay_.info.width] = 0;
307 publishMapAndRobot(1.65, 0.65, M_PI);
309 sendGoalAndWaitForPath();
310 EXPECT_TRUE(comparePath(initial_path, *path_));
314 map_overlay_.data[13 + 5 * map_overlay_.info.width] = 100;
315 publishMapAndRobot(1.65, 0.65, M_PI);
317 sendGoalAndWaitForPath();
318 EXPECT_TRUE(comparePath(initial_path, *path_));
321 move_base_->cancelAllGoals();
322 map_overlay_.data[13 + 5 * map_overlay_.info.width] = 0;
323 publishMapAndRobot(1.25, 0.95, M_PI / 2);
325 sendGoalAndWaitForPath();
326 const nav_msgs::Path short_path = *path_;
328 sendGoalAndWaitForPath();
329 EXPECT_TRUE(comparePath(short_path, *path_));
334 publishMapAndRobot(2.55, 0.45, M_PI);
336 sendGoalAndWaitForPath();
340 const double default_interval = getAveragePathInterval(costmap_publishing_interval);
341 EXPECT_NEAR(default_interval, 1.0 / default_config_.freq, (1.0 / default_config_.freq) * 0.1);
343 planner_cspace::Planner3DConfig config = default_config_;
344 config.trigger_plan_by_costmap_update =
true;
345 config.costmap_watchdog = 0.5;
346 ASSERT_TRUE(planner_3d_client_->setConfiguration(config));
350 const double interval_triggered_by_costmap = getAveragePathInterval(costmap_publishing_interval);
351 EXPECT_NEAR(interval_triggered_by_costmap, costmap_publishing_interval.
toSec(),
352 costmap_publishing_interval.
toSec() * 0.1);
355 const double interval_triggered_by_watchdog = getAveragePathInterval(
ros::Duration(100));
356 EXPECT_NEAR(interval_triggered_by_watchdog, config.costmap_watchdog, config.costmap_watchdog * 0.1);
359 int main(
int argc,
char** argv)
361 testing::InitGoogleTest(&argc, argv);
362 ros::init(argc, argv,
"test_dynamic_parameter_change");
363 return RUN_ALL_TESTS();