37 #include <gtest/gtest.h>
39 #include <nav_msgs/Path.h>
42 #include <trajectory_tracker_msgs/PathWithVelocity.h>
48 const auto nearest = path.
findNearest(path.begin(), path.end(), p);
49 const Eigen::Vector2d pos_on_line =
51 return path.
remainedDistance(path.begin(), nearest, path.end(), pos_on_line);
55 TEST(Path2D, RemainedDistance)
58 for (
double x = 0.0; x < 10.0 - 1e-3; x += 0.2)
63 for (
size_t l = 2; l < path_full.size(); ++l)
67 std::copy(path_full.end() - l, path_full.end(), path.begin());
69 std::string err_msg =
"failed for " + std::to_string(l) +
" pose(s) path";
71 ASSERT_NEAR(getRemainedDistance(path, Eigen::Vector2d(0, 0)), 10.0, 1e-2) << err_msg;
73 ASSERT_NEAR(getRemainedDistance(path, Eigen::Vector2d(8.25, 0)), 1.75, 1e-2) << err_msg;
74 ASSERT_NEAR(getRemainedDistance(path, Eigen::Vector2d(10.25, 0)), -0.25, 1e-2) << err_msg;
76 ASSERT_NEAR(getRemainedDistance(path, Eigen::Vector2d(8.25, 0.1)), 1.75, 1e-2) << err_msg;
77 ASSERT_NEAR(getRemainedDistance(path, Eigen::Vector2d(8.25, -0.1)), 1.75, 1e-2) << err_msg;
78 ASSERT_NEAR(getRemainedDistance(path, Eigen::Vector2d(10.25, 0.1)), -0.25, 1e-2) << err_msg;
79 ASSERT_NEAR(getRemainedDistance(path, Eigen::Vector2d(10.25, -0.1)), -0.25, 1e-2) << err_msg;
85 for (
float c = 1.0; c < 4.0; c += 0.4)
88 for (
double a = 0; a < 1.57; a += 0.1)
90 ASSERT_NEAR(path.
getCurvature(path.begin(), path.end(), path[0].pos_, 10.0), 1.0 / c, 1e-2);
93 for (
float c = 1.0; c < 4.0; c += 0.4)
96 for (
double a = 0; a < 0.2; a += 0.1)
98 ASSERT_NEAR(path.
getCurvature(path.begin(), path.end(), path[0].pos_, 10.0), 1.0 / c, 1e-2);
102 TEST(Path2D, LocalGoalWithoutSwitchBack)
104 for (
int yaw_i = -1; yaw_i <= 1; ++yaw_i)
106 const double yaw_diff = yaw_i * 0.1;
109 Eigen::Vector2d p(0, 0);
111 for (
int i = 0; i < 10; ++i)
113 p -= Eigen::Vector2d(std::cos(yaw), std::sin(yaw)) * 0.1;
117 ASSERT_EQ(path.
findLocalGoal(path.begin(), path.end(),
true), path.end());
118 ASSERT_EQ(path.
findLocalGoal(path.begin(), path.end(),
false), path.end());
122 TEST(Path2D, LocalGoalWithSwitchBack)
124 for (
int yaw_i = -1; yaw_i <= 1; ++yaw_i)
126 const double yaw_diff = yaw_i * 0.1;
129 Eigen::Vector2d p(0, 0);
131 for (
int i = 0; i < 5; ++i)
133 p -= Eigen::Vector2d(std::cos(yaw), std::sin(yaw)) * 0.1;
137 for (
int i = 0; i < 5; ++i)
139 p += Eigen::Vector2d(std::cos(yaw), std::sin(yaw)) * 0.1;
145 const auto it_local_goal = path.
findLocalGoal(path.begin(), path.end(),
true,
true);
146 ASSERT_EQ(it_local_goal, path.begin() + 5);
147 ASSERT_EQ(path.
findLocalGoal(it_local_goal, path.end(),
true,
true), path.end());
150 const auto it_local_goal = path.
findLocalGoal(path.begin(), path.end(),
true,
false);
151 ASSERT_EQ(it_local_goal, path.begin() + 5);
152 ASSERT_EQ(path.
findLocalGoal(it_local_goal, path.end(),
true,
false), path.end());
155 ASSERT_EQ(path.
findLocalGoal(path.begin(), path.end(),
false,
true), path.end());
162 Eigen::Vector2d p(0, 0);
163 for (
size_t i = 0; i <= 10; ++i)
165 const double yaw = M_PI / 2 / 10;
166 p.x() = std::sin(i * yaw);
167 p.y() = 1.0 - std::cos(i * yaw);
171 for (
size_t i = 0; i <= 10; ++i)
176 const auto it_local_goal = path.
findLocalGoal(path.begin(), path.end(),
true,
true);
177 ASSERT_EQ(it_local_goal, path.begin() + 11);
178 ASSERT_EQ(path.
findLocalGoal(it_local_goal, path.end(),
true,
true), path.end());
181 ASSERT_EQ(path.
findLocalGoal(path.begin(), path.end(),
true,
false), path.end());
185 TEST(Path2D, EnumerateLocalGoals)
188 const std::vector<float> yaws = {0.5, -0.2, 1.0};
191 for (
const float yaw : yaws)
193 for (
size_t i = 0; i < 10; ++i)
196 x += std::cos(yaw) * 0.1;
197 y += std::sin(yaw) * 0.1;
204 ASSERT_EQ(local_goals.size(), 3);
205 ASSERT_EQ(local_goals.at(0) - path.begin(), 11);
206 ASSERT_EQ(local_goals.at(1) - path.begin(), 22);
207 ASSERT_EQ(local_goals.at(2) - path.begin(), 33);
210 TEST(Path2D, FindNearestWithDistance)
223 const auto nearest_with_dist = path.
findNearestWithDistance(path.begin(), path.end(), Eigen::Vector2d(1.0, 0.5));
224 EXPECT_EQ(nearest_with_dist.first, path.begin() + 4);
225 EXPECT_NEAR(nearest_with_dist.second, std::sqrt(std::pow(1.0 - 0.85, 2) + std::pow(0.5 - 0.65, 2)), 1.0e-6);
229 const auto nearest_with_dist =
231 EXPECT_EQ(nearest_with_dist.first, path.begin() + 2);
232 EXPECT_NEAR(nearest_with_dist.second, std::sqrt(std::pow(1.0 - 0.7, 2) + std::pow(0.5 - 0.5, 2)), 1.0e-6);
236 const auto nearest_with_dist =
238 EXPECT_EQ(nearest_with_dist.first, path.begin() + 5);
239 EXPECT_NEAR(nearest_with_dist.second, std::sqrt(std::pow(1.0 - 0.9, 2) + std::pow(0.5 - 0.8, 2)), 1.0e-6);
241 const auto invalid_result =
243 EXPECT_EQ(invalid_result.first, path.end());
244 EXPECT_EQ(invalid_result.second, std::numeric_limits<double>::max());
250 nav_msgs::Path path_msg_org;
251 path_msg_org.poses.resize(8);
252 path_msg_org.poses[0].pose.position.x = 0.0;
253 path_msg_org.poses[0].pose.position.y = 0.0;
254 path_msg_org.poses[0].pose.orientation.w = 1.0;
255 path_msg_org.poses[1].pose.position.x = 1.0;
256 path_msg_org.poses[1].pose.position.y = 0.0;
257 path_msg_org.poses[1].pose.orientation.w = 1.0;
258 path_msg_org.poses[2].pose.position.x = 1.0;
259 path_msg_org.poses[2].pose.position.y = 0.0;
260 path_msg_org.poses[2].pose.orientation.z = std::sin(M_PI / 8);
261 path_msg_org.poses[2].pose.orientation.w = std::cos(M_PI / 8);
262 path_msg_org.poses[3].pose.position.x = 1.0;
263 path_msg_org.poses[3].pose.position.y = 0.0;
264 path_msg_org.poses[3].pose.orientation.z = std::sin(M_PI / 4);
265 path_msg_org.poses[3].pose.orientation.w = std::cos(M_PI / 4);
266 path_msg_org.poses[4].pose.position.x = 1.0;
267 path_msg_org.poses[4].pose.position.y = 1.0;
268 path_msg_org.poses[4].pose.orientation.z = std::sin(M_PI / 4);
269 path_msg_org.poses[4].pose.orientation.w = std::cos(M_PI / 4);
270 path_msg_org.poses[5].pose.position.x = 1.0;
271 path_msg_org.poses[5].pose.position.y = 2.0;
272 path_msg_org.poses[5].pose.orientation.z = std::sin(M_PI / 4);
273 path_msg_org.poses[5].pose.orientation.w = std::cos(M_PI / 4);
274 path_msg_org.poses[6].pose.position.x = 1.0;
275 path_msg_org.poses[6].pose.position.y = 2.0;
276 path_msg_org.poses[6].pose.orientation.z = std::sin(M_PI / 4 + M_PI / 6);
277 path_msg_org.poses[6].pose.orientation.w = std::cos(M_PI / 4 + M_PI / 6);
278 path_msg_org.poses[7].pose.position.x = 1.0;
279 path_msg_org.poses[7].pose.position.y = 2.0;
280 path_msg_org.poses[7].pose.orientation.z = std::sin(M_PI / 4 + M_PI / 3);
281 path_msg_org.poses[7].pose.orientation.w = std::cos(M_PI / 4 + M_PI / 3);
286 const std::vector<size_t> expected_org_indexes = {0, 1, 3, 4, 5, 7};
287 ASSERT_EQ(path.size(), 6);
288 for (
size_t i = 0; i < path.size(); ++i)
290 const size_t org_index = expected_org_indexes[i];
291 EXPECT_EQ(path[i].pos_.x(), path_msg_org.poses[org_index].pose.position.x) <<
"i: " << i <<
" org: " << org_index;
292 EXPECT_EQ(path[i].pos_.y(), path_msg_org.poses[org_index].pose.position.y) <<
"i: " << i <<
" org: " << org_index;
293 EXPECT_NEAR(path[i].yaw_,
tf2::getYaw(path_msg_org.poses[org_index].pose.orientation), 1.0e-6)
294 <<
"i: " << i <<
" org: " << org_index;
295 EXPECT_TRUE(std::isnan(path[i].velocity_));
298 nav_msgs::Path path_msg;
299 path_msg.header.frame_id =
"map";
300 path_msg.header.stamp =
ros::Time(123.456);
301 path.
toMsg(path_msg);
302 ASSERT_EQ(path_msg.poses.size(), 6);
303 for (
size_t i = 0; i < path.size(); ++i)
305 EXPECT_EQ(path[i].pos_.x(), path_msg.poses[i].pose.position.x) <<
"i: " << i;
306 EXPECT_EQ(path[i].pos_.y(), path_msg.poses[i].pose.position.y) <<
"i: " << i;
307 EXPECT_NEAR(path[i].yaw_,
tf2::getYaw(path_msg.poses[i].pose.orientation), 1.0e-6) <<
"i: " << i;
308 EXPECT_EQ(path_msg.poses[i].header.frame_id, path_msg.header.frame_id);
309 EXPECT_EQ(path_msg.poses[i].header.stamp, path_msg.header.stamp);
312 trajectory_tracker_msgs::PathWithVelocity path_with_vel_msg_org;
313 path_with_vel_msg_org.poses.resize(path_msg_org.poses.size());
314 for (
size_t i = 0; i < path_msg_org.poses.size(); ++i)
316 path_with_vel_msg_org.poses[i].pose = path_msg_org.poses[i].pose;
317 path_with_vel_msg_org.poses[i].linear_velocity.x = i * 0.1;
321 path_with_vel.
fromMsg(path_with_vel_msg_org);
323 ASSERT_EQ(path_with_vel.size(), 6);
324 for (
size_t i = 0; i < path_with_vel.size(); ++i)
326 const size_t org_index = expected_org_indexes[i];
327 EXPECT_EQ(path_with_vel[i].pos_.x(), path_with_vel_msg_org.poses[org_index].pose.position.x)
328 <<
"i: " << i <<
" org: " << org_index;
329 EXPECT_EQ(path_with_vel[i].pos_.y(), path_with_vel_msg_org.poses[org_index].pose.position.y)
330 <<
"i: " << i <<
" org: " << org_index;
331 EXPECT_NEAR(path_with_vel[i].yaw_,
tf2::getYaw(path_with_vel_msg_org.poses[org_index].pose.orientation), 1.0e-6)
332 <<
"i: " << i <<
" org: " << org_index;
333 EXPECT_NEAR(path_with_vel[i].velocity_, org_index * 0.1, 1.0e-6) <<
"i: " << i <<
" org: " << org_index;
336 trajectory_tracker_msgs::PathWithVelocity path_with_vel_msg;
337 path_with_vel_msg.header.frame_id =
"map";
338 path_with_vel_msg.header.stamp =
ros::Time(123.456);
339 path_with_vel.
toMsg(path_with_vel_msg);
340 ASSERT_EQ(path_with_vel_msg.poses.size(), 6);
341 for (
size_t i = 0; i < path_with_vel.size(); ++i)
343 EXPECT_EQ(path_with_vel[i].pos_.x(), path_with_vel_msg.poses[i].pose.position.x) <<
"i: " << i;
344 EXPECT_EQ(path_with_vel[i].pos_.y(), path_with_vel_msg.poses[i].pose.position.y) <<
"i: " << i;
345 EXPECT_NEAR(path_with_vel[i].yaw_,
tf2::getYaw(path_with_vel_msg.poses[i].pose.orientation), 1.0e-6)
347 EXPECT_EQ(path_with_vel_msg.poses[i].header.frame_id, path_with_vel_msg.header.frame_id);
348 EXPECT_EQ(path_with_vel_msg.poses[i].header.stamp, path_with_vel_msg.header.stamp);
352 TEST(Path2D, EstimatedTimeOfArrivals)
362 for (
int i = 1; i <= 4; ++i)
364 const double angle = M_PI / 8 * i;
366 Eigen::Vector2d(0.2 * std::cos(
angle), -0.2 + 0.2 * std::sin(
angle)), -M_PI / 2 -
angle, 0));
368 const double linear_speed = 0.5;
369 const double angular_speed = M_PI;
370 const std::vector<double> etas =
372 ASSERT_EQ(etas.size(), 8);
373 double expected_eta = 1.0;
374 EXPECT_NEAR(etas[0], expected_eta, 1.0e-6);
375 expected_eta += std::hypot(0.1, 0.1) / linear_speed;
376 EXPECT_NEAR(etas[1], expected_eta, 1.0e-6);
377 expected_eta += std::hypot(0.1, 0.1) / linear_speed;
378 EXPECT_NEAR(etas[2], expected_eta, 1.0e-6);
379 expected_eta += 135.0 / (180.0 / M_PI) / angular_speed;
380 EXPECT_NEAR(etas[3], expected_eta, 1.0e-6);
381 const double turn_dist = std::hypot(0.2 - 0.2 * std::cos(M_PI / 8), 0.2 * std::sin(M_PI / 8));
382 for (
size_t p = 4; p < etas.size(); ++p)
384 EXPECT_NEAR(etas[p], expected_eta + (p - 3) * turn_dist / linear_speed, 1.0e-6);
388 int main(
int argc,
char** argv)
390 testing::InitGoogleTest(&argc, argv);
392 return RUN_ALL_TESTS();