36 #include <diagnostic_msgs/DiagnosticStatus.h> 37 #include <geometry_msgs/Twist.h> 38 #include <sensor_msgs/PointCloud2.h> 42 #include <gtest/gtest.h> 48 for (
int with_cloud = 0; with_cloud < 3; ++with_cloud)
50 for (
int with_watchdog_reset = 0; with_watchdog_reset < 2; ++with_watchdog_reset)
52 const std::string test_condition =
53 "with_watchdog_reset: " + std::to_string(with_watchdog_reset) +
54 ", with_cloud: " + std::to_string(with_cloud);
58 for (
int i = 0; i < 20; ++i)
62 if (with_watchdog_reset > 0)
63 publishWatchdogReset();
69 publishSinglePointPointcloud2(1000, 1000, 0,
"base_link",
ros::Time::now());
71 publishSinglePointPointcloud2(1000, 1000, 0,
"base_link",
ros::Time());
74 const float vel = 0.1;
75 const float ang_vel = 0.2;
76 publishTwist(vel, ang_vel);
77 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
82 if (i > 5 && cmd_vel_)
84 if (with_watchdog_reset > 0 && with_cloud > 1)
86 ASSERT_EQ(cmd_vel_->linear.x, vel) << test_condition;
87 ASSERT_EQ(cmd_vel_->linear.y, 0.0) << test_condition;
88 ASSERT_EQ(cmd_vel_->linear.z, 0.0) << test_condition;
89 ASSERT_EQ(cmd_vel_->angular.x, 0.0) << test_condition;
90 ASSERT_EQ(cmd_vel_->angular.y, 0.0) << test_condition;
91 ASSERT_EQ(cmd_vel_->angular.z, ang_vel) << test_condition;
95 ASSERT_EQ(cmd_vel_->linear.x, 0.0) << test_condition;
96 ASSERT_EQ(cmd_vel_->linear.y, 0.0) << test_condition;
97 ASSERT_EQ(cmd_vel_->linear.z, 0.0) << test_condition;
98 ASSERT_EQ(cmd_vel_->angular.x, 0.0) << test_condition;
99 ASSERT_EQ(cmd_vel_->angular.y, 0.0) << test_condition;
100 ASSERT_EQ(cmd_vel_->angular.z, 0.0) << test_condition;
105 ASSERT_TRUE(hasStatus()) << test_condition;
106 EXPECT_EQ(with_cloud > 1, status_->is_cloud_available) << test_condition;
107 EXPECT_EQ(status_->stuck_started_since,
ros::Time(0)) << test_condition;
109 if (with_watchdog_reset > 0 && with_cloud > 1)
111 ASSERT_TRUE(hasDiag()) << test_condition;
112 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::OK, diag_->status[0].level)
113 << test_condition <<
", " 114 <<
"message: " << diag_->status[0].message;
116 EXPECT_FALSE(status_->has_watchdog_timed_out) << test_condition;
120 ASSERT_TRUE(hasDiag()) << test_condition;
121 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::ERROR, diag_->status[0].level)
122 << test_condition <<
", " 123 <<
"message: " << diag_->status[0].message;
124 if (with_watchdog_reset == 0)
126 EXPECT_TRUE(status_->has_watchdog_timed_out) << test_condition;
138 for (
int i = 0; i < 30 &&
ros::ok(); ++i)
140 publishSinglePointPointcloud2(0.5, 0, 0,
"base_link",
ros::Time::now());
141 publishWatchdogReset();
147 bool received =
false;
151 for (
int i = 0; i < 60 * 6 &&
ros::ok(); ++i)
160 publishSinglePointPointcloud2(10, 0, 0,
"base_link",
ros::Time::now());
162 publishSinglePointPointcloud2(0.5, 0, 0,
"base_link",
ros::Time::now());
164 publishWatchdogReset();
165 publishTwist(2.0, 0);
166 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
173 ASSERT_NEAR(cmd_vel_->linear.x, 1.0, 1e-1);
176 ASSERT_TRUE(received);
184 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
186 publishSinglePointPointcloud2(0.5, 0, 0,
"base_link",
ros::Time::now());
187 publishWatchdogReset();
193 for (
float vel = 0.0; vel < 2.0; vel += 0.4)
196 bool received =
false;
199 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
203 publishSinglePointPointcloud2(0.5, 0, 0,
"base_link",
ros::Time::now());
204 publishWatchdogReset();
205 publishTwist(vel, ((i % 5) - 2.0) * 0.01);
206 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
213 const float expected_vel = std::min<float>(vel, 1.0);
214 ASSERT_NEAR(cmd_vel_->linear.x, expected_vel, 1e-1);
217 ASSERT_TRUE(hasDiag());
218 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::OK, diag_->status[0].level)
219 <<
"message: " << diag_->status[0].message;
221 ASSERT_TRUE(hasStatus());
222 EXPECT_TRUE(status_->is_cloud_available);
223 EXPECT_FALSE(status_->has_watchdog_timed_out);
224 EXPECT_EQ(status_->stuck_started_since,
ros::Time(0));
226 ASSERT_TRUE(received);
235 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
237 publishSinglePointPointcloud2(-2.5, 0, 0,
"base_link",
ros::Time::now());
238 publishWatchdogReset();
244 for (
float vel = 0.0; vel > -2.0; vel -= 0.4)
247 bool received =
false;
250 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
254 publishSinglePointPointcloud2(-2.5, 0, 0,
"base_link",
ros::Time::now());
255 publishWatchdogReset();
256 publishTwist(vel, ((i % 5) - 2.0) * 0.01);
257 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
264 const float expected_vel = std::max<float>(vel, -1.0);
265 ASSERT_NEAR(cmd_vel_->linear.x, expected_vel, 1e-1);
268 ASSERT_TRUE(hasDiag());
269 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::OK, diag_->status[0].level)
270 <<
"message: " << diag_->status[0].message;
272 ASSERT_TRUE(hasStatus());
273 EXPECT_TRUE(status_->is_cloud_available);
274 EXPECT_FALSE(status_->has_watchdog_timed_out);
275 EXPECT_EQ(status_->stuck_started_since,
ros::Time(0));
277 ASSERT_TRUE(received);
286 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
288 publishSinglePointPointcloud2(-0.05, 0, 0,
"base_link",
ros::Time::now());
289 publishWatchdogReset();
295 const float vel_ref[] = { -0.2, -0.4, 0.2, 0.4 };
296 for (
const float vel : vel_ref)
299 bool received =
false;
302 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
306 publishSinglePointPointcloud2(-0.05, 0, 0,
"base_link",
ros::Time::now());
307 publishWatchdogReset();
308 publishTwist(vel, 0.0);
309 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
319 ASSERT_NEAR(cmd_vel_->linear.x, vel, 1e-1);
324 ASSERT_NEAR(cmd_vel_->linear.x, 0.0, 1e-1);
330 ASSERT_TRUE(hasDiag());
331 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::OK, diag_->status[0].level)
332 <<
"message: " << diag_->status[0].message;
336 ASSERT_TRUE(hasDiag());
337 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::WARN, diag_->status[0].level)
338 <<
"message: " << diag_->status[0].message;
341 ASSERT_TRUE(hasStatus());
342 EXPECT_TRUE(status_->is_cloud_available);
343 EXPECT_FALSE(status_->has_watchdog_timed_out);
344 EXPECT_NE(status_->stuck_started_since,
ros::Time(0));
346 ASSERT_TRUE(received);
355 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
357 publishSinglePointPointcloud2(-1, -1, 0,
"base_link",
ros::Time::now());
358 publishWatchdogReset();
364 for (
float vel = 0.0; vel < M_PI; vel += M_PI / 10)
367 bool received =
false;
370 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
374 publishSinglePointPointcloud2(-1, -1.1, 0,
"base_link",
ros::Time::now());
375 publishWatchdogReset();
376 publishTwist((i % 3) * 0.01, vel);
377 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
384 const float expected_vel = std::min<float>(vel, M_PI / 2);
385 ASSERT_NEAR(cmd_vel_->angular.z, expected_vel, M_PI / 20);
388 ASSERT_TRUE(hasDiag());
389 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::OK, diag_->status[0].level)
390 <<
"message: " << diag_->status[0].message;
392 ASSERT_TRUE(hasStatus());
393 EXPECT_TRUE(status_->is_cloud_available);
394 EXPECT_FALSE(status_->has_watchdog_timed_out);
395 EXPECT_EQ(status_->stuck_started_since,
ros::Time(0));
397 ASSERT_TRUE(received);
406 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
408 publishSinglePointPointcloud2(-1, -0.09, 0,
"base_link",
ros::Time::now());
409 publishWatchdogReset();
415 const float vel_ref[] = { -0.2, -0.4, 0.2, 0.4 };
416 for (
const float vel : vel_ref)
419 bool received =
false;
422 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
426 publishSinglePointPointcloud2(-1, -0.09, 0,
"base_link",
ros::Time::now());
427 publishWatchdogReset();
428 publishTwist(0.0, vel);
429 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
439 ASSERT_NEAR(cmd_vel_->angular.z, vel, 1e-1);
444 ASSERT_NEAR(cmd_vel_->angular.z, 0.0, 1e-1);
450 ASSERT_TRUE(hasDiag());
451 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::OK, diag_->status[0].level)
452 <<
"message: " << diag_->status[0].message;
456 ASSERT_TRUE(hasDiag());
457 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::WARN, diag_->status[0].level)
458 <<
"message: " << diag_->status[0].message;
461 ASSERT_TRUE(hasStatus());
462 EXPECT_TRUE(status_->is_cloud_available);
463 EXPECT_FALSE(status_->has_watchdog_timed_out);
464 EXPECT_NE(status_->stuck_started_since,
ros::Time(0));
466 ASSERT_TRUE(received);
474 for (
float vel = 0.0; vel < 1.0; vel += 0.2)
476 for (
float ang_vel = 0.0; ang_vel < 1.0; ang_vel += 0.2)
478 bool received =
false;
481 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
485 publishSinglePointPointcloud2(1000, 1000, 0,
"base_link",
ros::Time::now());
486 publishWatchdogReset();
487 publishTwist(vel, ang_vel);
488 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
495 ASSERT_NEAR(cmd_vel_->linear.x, vel, 1e-3);
496 ASSERT_NEAR(cmd_vel_->angular.z, ang_vel, 1e-3);
499 ASSERT_TRUE(received);
501 ASSERT_TRUE(hasDiag());
502 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::OK, diag_->status[0].level)
503 <<
"message: " << diag_->status[0].message;
505 ASSERT_TRUE(hasStatus());
506 EXPECT_EQ(1.0, status_->limit_ratio);
507 EXPECT_TRUE(status_->is_cloud_available);
508 EXPECT_FALSE(status_->has_watchdog_timed_out);
509 EXPECT_EQ(status_->stuck_started_since,
ros::Time(0));
516 const float dt = 0.02;
519 const float velocities[] =
523 for (
const float vel : velocities)
528 for (
int i = 0; i < std::lround(10.0 / dt) &&
ros::ok() && !stop; ++i)
531 publishSinglePointPointcloud2(1.0 - x, 0, 0,
"base_link",
ros::Time::now());
533 publishSinglePointPointcloud2(-3.0 - x, 0, 0,
"base_link",
ros::Time::now());
535 publishWatchdogReset();
536 publishTwist(vel, 0.0);
537 broadcastTF(
"odom",
"base_link", x, 0.0);
543 if (std::abs(cmd_vel_->linear.x) < 1e-4 && x > 0.5)
546 x += dt * cmd_vel_->linear.x;
566 const float linear_velocities[] =
567 {-1.7, -1.5, 0.0, 1.5, 1.7 };
568 const float angular_velocities[] =
569 {-2.7, -2.5, 0.0, 2.5, 2.7 };
570 const float expected_linear_velocities[] =
571 {-1.5, -1.5, 0.0, 1.5, 1.5 };
572 const float expected_angular_velocities[] =
573 {-2.5, -2.5, 0.0, 2.5, 2.5 };
575 for (
int linear_index = 0; linear_index < 5; linear_index++)
577 for (
int angular_index = 0; angular_index < 5; angular_index++)
579 bool received =
false;
582 for (
int i = 0; i < 10 &&
ros::ok(); ++i)
584 if (i > 5) en =
true;
585 publishSinglePointPointcloud2(1000, 1000, 0,
"base_link",
ros::Time::now());
586 publishWatchdogReset();
587 publishTwist(linear_velocities[linear_index], angular_velocities[angular_index]);
588 broadcastTF(
"odom",
"base_link", 0.0, 0.0);
595 ASSERT_NEAR(expected_linear_velocities[linear_index], cmd_vel_->linear.x, 1e-3);
596 ASSERT_NEAR(expected_angular_velocities[angular_index], cmd_vel_->angular.z, 1e-3);
599 ASSERT_TRUE(received);
601 ASSERT_TRUE(hasDiag());
602 EXPECT_EQ(diagnostic_msgs::DiagnosticStatus::OK, diag_->status[0].level)
603 <<
"message: " << diag_->status[0].message;
605 ASSERT_TRUE(hasStatus());
606 EXPECT_EQ(1.0, status_->limit_ratio);
607 EXPECT_TRUE(status_->is_cloud_available);
608 EXPECT_FALSE(status_->has_watchdog_timed_out);
609 EXPECT_EQ(status_->stuck_started_since,
ros::Time(0));
615 int main(
int argc,
char** argv)
617 testing::InitGoogleTest(&argc, argv);
618 ros::init(argc, argv,
"test_safety_limiter");
620 return RUN_ALL_TESTS();
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
int main(int argc, char **argv)
TFSIMD_FORCE_INLINE const tfScalar & x() const
TEST_F(SafetyLimiterTest, Timeouts)
ROSCPP_DECL void spinOnce()