00001
00025 #include <string>
00026 #include <numeric>
00027 #include <boost/shared_ptr.hpp>
00028 #include <boost/bind.hpp>
00029 #include <boost/thread/mutex.hpp>
00030 #include <boost/thread/locks.hpp>
00031 #include <boost/function.hpp>
00032
00033 #include <ros/ros.h>
00034 #include <std_msgs/Empty.h>
00035 #include <geometry_msgs/Twist.h>
00036 #include <sensor_msgs/Image.h>
00037 #include <angles/angles.h>
00038 #include <sensor_msgs/CameraInfo.h>
00039 #include <nav_msgs/Odometry.h>
00040 #include <sensor_msgs/NavSatFix.h>
00041 #include <tf2_ros/transform_listener.h>
00042 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
00043
00044 #include <gtest/gtest.h>
00045
00046 #include <bebop_msgs/Ardrone3PilotingStateFlyingStateChanged.h>
00047 #include <bebop_msgs/Ardrone3PilotingStateAttitudeChanged.h>
00048 #include <bebop_msgs/Ardrone3CameraStateOrientation.h>
00049 #include <bebop_msgs/Ardrone3PilotingStateFlyingStateChanged.h>
00050 #include <bebop_msgs/Ardrone3PilotingStateSpeedChanged.h>
00051 #include <bebop_msgs/Ardrone3PilotingStateAltitudeChanged.h>
00052 #include <bebop_msgs/CommonCommonStateBatteryStateChanged.h>
00053
00054 #define TIMED_ASSERT(TIMEOUT, WAIT_UNTIL_TRUE, WAITING_TEXT) \
00055 do \
00056 { \
00057 const ros::Time start = ros::Time::now(); \
00058 while (((ros::Time::now() - start).toSec() < TIMEOUT) && (!(WAIT_UNTIL_TRUE))) \
00059 { \
00060 ROS_INFO_ONCE(WAITING_TEXT); \
00061 ros::Rate(5.0).sleep(); \
00062 } \
00063 ASSERT_TRUE(WAIT_UNTIL_TRUE); \
00064 } \
00065 while (0) \
00066
00067 namespace bebop_driver
00068 {
00069 namespace util
00070 {
00071
00072 template<typename T>
00073 class ASyncSub
00074 {
00075 private:
00076 typedef boost::function<void (const boost::shared_ptr<T const>& data)> callback_t;
00077
00078 ros::NodeHandle nh;
00079 bool active_;
00080 ros::Time last_updated_;
00081 std::string topic_;
00082 std::size_t queue_size_;
00083 callback_t user_callback_;
00084 ros::Subscriber sub_;
00085 boost::shared_ptr<T const> msg_cptr_;
00086 mutable boost::mutex mutex_;
00087
00088 void cb(const boost::shared_ptr<T const> &msg_cptr)
00089 {
00090 boost::lock_guard<boost::mutex> lock(mutex_);
00091 active_ = true;
00092 last_updated_ = ros::Time::now();
00093 msg_cptr_ = msg_cptr;
00094 if (user_callback_) user_callback_(msg_cptr_);
00095 }
00096
00097 public:
00098 ASyncSub(ros::NodeHandle& nh,
00099 const std::string& topic,
00100 const std::size_t queue_size,
00101 callback_t user_callback = 0)
00102 : nh(nh), active_(false), last_updated_(0), topic_(topic), user_callback_(user_callback)
00103 {
00104 sub_ = nh.subscribe<T>(topic_, queue_size, boost::bind(&ASyncSub<T>::cb, this, _1));
00105 }
00106
00107 T GetMsgCopy() const
00108 {
00109 boost::lock_guard<boost::mutex> lock(mutex_);
00110 return *msg_cptr_;
00111 }
00112
00113 const boost::shared_ptr<T const>& GetMsgConstPtr() const
00114 {
00115 boost::lock_guard<boost::mutex> lock(mutex_);
00116 return msg_cptr_;
00117 }
00118
00119
00120
00121 const boost::shared_ptr<T const>& operator()() const
00122 {
00123
00124 return GetMsgConstPtr();
00125 }
00126
00127 void Deactivate()
00128 {
00129 boost::lock_guard<boost::mutex> lock(mutex_);
00130 active_ = false;
00131 }
00132
00133 void DeactivateIfOlderThan(const double seconds)
00134 {
00135 if (!IsActive()) return;
00136 if (GetFreshness().toSec() > seconds)
00137 {
00138 ROS_WARN("Information on topic (%s) is older than (%4.2lf) seconds. Deactivating.", topic_.c_str(), seconds);
00139 Deactivate();
00140 }
00141 }
00142
00143 bool IsActive() const
00144 {
00145 boost::lock_guard<boost::mutex> lock(mutex_);
00146 return active_;
00147 }
00148
00149 const ros::Time GetLastUpdated() const
00150 {
00151 boost::lock_guard<boost::mutex> lock(mutex_);
00152 return last_updated_;
00153 }
00154
00155 const ros::Duration GetFreshness() const
00156 {
00157 boost::lock_guard<boost::mutex> lock(mutex_);
00158 return ros::Time::now() - last_updated_;
00159 }
00160 };
00161
00162 }
00163
00164 namespace test
00165 {
00166
00167 void dummy_cb(const bebop_msgs::Ardrone3PilotingStateAttitudeChanged::ConstPtr& msg_ptr)
00168 {
00169 ROS_INFO("Roll: %0.2lf, Pitch: %0.2lf, Yaw: %0.2lf",
00170 msg_ptr->roll, msg_ptr->pitch, msg_ptr->yaw);
00171 }
00172
00173 class BebopInTheLoopTest: public ::testing::Test
00174 {
00175 protected:
00176 ros::NodeHandle nh_;
00177 boost::shared_ptr<ros::AsyncSpinner> spinner_ptr_;
00178
00179 ros::Publisher land_pub_;
00180 ros::Publisher cmdvel_pub_;
00181
00182 std_msgs::Empty em;
00183 geometry_msgs::Twist tw;
00184
00185 boost::shared_ptr<util::ASyncSub<sensor_msgs::Image> > image_;
00186
00187
00188
00189 virtual void SetUp()
00190 {
00191 ros::NodeHandle priv_nh("~");
00192
00193 ROS_INFO("In SetUp()");
00194
00195
00196 land_pub_= nh_.advertise<std_msgs::Empty>("land", 1);
00197 cmdvel_pub_ = nh_.advertise<geometry_msgs::Twist>("cmd_vel", 1);
00198
00199
00200 image_.reset(new util::ASyncSub<sensor_msgs::Image>(
00201 nh_, "image_raw", 10));
00202
00203 spinner_ptr_.reset(new ros::AsyncSpinner(4));
00204 spinner_ptr_->start();
00205
00206
00207 ros::Time start = ros::Time::now();
00208
00209
00210 TIMED_ASSERT(15.0, image_->IsActive(), "Waiting for Bebop ...");
00211 TIMED_ASSERT(5.0, land_pub_.getNumSubscribers() > 0, "Waiting for land subscription ...");
00212
00213 ROS_INFO("End SetUp()");
00214 }
00215
00216 void StopBebop()
00217 {
00218 tw.linear.x = 0.0;
00219 tw.linear.y = 0.0;
00220 tw.linear.z = 0.0;
00221 tw.angular.z = 0.0;
00222 ROS_WARN("Stopping ...");
00223 cmdvel_pub_.publish(tw);
00224 ros::Duration(1.0).sleep();
00225 }
00226
00227 virtual void TearDown()
00228 {
00229 ROS_INFO("In teardown()");
00230 StopBebop();
00231 std_msgs::Empty em;
00232 land_pub_.publish(em);
00233 ros::Rate(ros::Duration(2.0)).sleep();
00234 spinner_ptr_->stop();
00235 }
00236
00237 };
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 TEST_F(BebopInTheLoopTest, Piloting)
00250 {
00251 boost::shared_ptr<util::ASyncSub<bebop_msgs::Ardrone3PilotingStateFlyingStateChanged> >
00252 flying_state(new util::ASyncSub<bebop_msgs::Ardrone3PilotingStateFlyingStateChanged>(
00253 nh_, "states/ardrone3/PilotingState/FlyingStateChanged", 10));
00254
00255 boost::shared_ptr<util::ASyncSub<bebop_msgs::Ardrone3PilotingStateSpeedChanged> >
00256 speed_state(new util::ASyncSub<bebop_msgs::Ardrone3PilotingStateSpeedChanged>(
00257 nh_, "states/ardrone3/PilotingState/SpeedChanged", 10));
00258
00259 boost::shared_ptr<util::ASyncSub<bebop_msgs::Ardrone3PilotingStateAltitudeChanged> >
00260 alt_state(new util::ASyncSub<bebop_msgs::Ardrone3PilotingStateAltitudeChanged>(
00261 nh_, "states/ardrone3/PilotingState/AltitudeChanged", 10));
00262
00263 boost::shared_ptr<util::ASyncSub<bebop_msgs::Ardrone3PilotingStateAttitudeChanged> >
00264 att_state(new util::ASyncSub<bebop_msgs::Ardrone3PilotingStateAttitudeChanged>(
00265 nh_, "states/ardrone3/PilotingState/AttitudeChanged", 10));
00266
00267
00268
00269 boost::shared_ptr<util::ASyncSub<bebop_msgs::CommonCommonStateBatteryStateChanged> >
00270 bat_state(new util::ASyncSub<bebop_msgs::CommonCommonStateBatteryStateChanged>(
00271 nh_, "states/common/CommonState/BatteryStateChanged", 10));
00272
00273 boost::shared_ptr<util::ASyncSub<nav_msgs::Odometry> >
00274 odom(new util::ASyncSub<nav_msgs::Odometry>(
00275 nh_, "odom", 10));
00276
00277 boost::shared_ptr<util::ASyncSub<sensor_msgs::NavSatFix> >
00278 gps(new util::ASyncSub<sensor_msgs::NavSatFix>(
00279 nh_, "fix", 10));
00280
00281 ros::Publisher takeoff_pub = nh_.advertise<std_msgs::Empty>("takeoff", 1);
00282 ros::Publisher reset_pub = nh_.advertise<std_msgs::Empty>("reset", 1);
00283
00284
00285 TIMED_ASSERT(5.0, takeoff_pub.getNumSubscribers() > 0, "Waiting for takeoff subscription ...");
00286 TIMED_ASSERT(5.0, cmdvel_pub_.getNumSubscribers() > 0, "Waiting for cmd_vel subscription ...");
00287 TIMED_ASSERT(5.0, reset_pub.getNumSubscribers() > 0, "Waiting for reset subscription ...");
00288
00289 ROS_WARN("Taking off ...");
00290 takeoff_pub.publish(em);
00291 TIMED_ASSERT(10.0,
00292 flying_state->IsActive() && flying_state->GetMsgCopy().state ==
00293 bebop_msgs::Ardrone3PilotingStateFlyingStateChanged::state_hovering,
00294 "Waiting for takeoff to finish ..."
00295 );
00296
00297 TIMED_ASSERT(5.0, speed_state->IsActive(), "Waiting for Speed measurements ...");
00298 TIMED_ASSERT(5.0, alt_state->IsActive(), "Waiting for alt measurements ...");
00299 TIMED_ASSERT(5.0, att_state->IsActive(), "Waiting for attitude measurements ...");
00300 TIMED_ASSERT(5.0, odom->IsActive(), "Waiting for odom ...");
00301 TIMED_ASSERT(5.0, gps->IsActive(), "Waiting for GPS ...");
00302
00303
00304
00305 tw.linear.x = 0.4;
00306 tw.linear.y = 0.0;
00307 tw.linear.z = 0.0;
00308 tw.angular.z = 0.0;
00309 ROS_WARN("Moving forwared ...");
00310 cmdvel_pub_.publish(tw);
00311
00312 TIMED_ASSERT(3.0, angles::to_degrees(att_state->GetMsgCopy().pitch) < -2.5 , "Measuring pitch ...");
00313 TIMED_ASSERT(3.0, (odom->GetMsgCopy().twist.twist.linear.x > 0.2),
00314 "Measuring the forward and lateral velocities from odom ...");
00315
00316 StopBebop();
00317 TIMED_ASSERT(5.0,
00318 (fabs(speed_state->GetMsgCopy().speedX) < 0.05) &&
00319 (fabs(speed_state->GetMsgCopy().speedY) < 0.05) &&
00320 (fabs(speed_state->GetMsgCopy().speedZ) < 0.05)
00321 , "Measuring the speed vector ...");
00322
00323 TIMED_ASSERT(5.0,
00324 (fabs(odom->GetMsgCopy().twist.twist.linear.x) < 0.05) &&
00325 (fabs(odom->GetMsgCopy().twist.twist.linear.y) < 0.05) &&
00326 (fabs(odom->GetMsgCopy().twist.twist.linear.z) < 0.05)
00327 , "Measuring the speed vector from odom...");
00328
00329
00330 tw.linear.x = -0.4;
00331 tw.linear.y = 0.0;
00332 tw.linear.z = 0.0;
00333 tw.angular.z = 0.0;
00334 ROS_WARN("Moving Backward ...");
00335 cmdvel_pub_.publish(tw);
00336
00337 TIMED_ASSERT(3.0, angles::to_degrees(att_state->GetMsgCopy().pitch) > 2.5, "Measuring pitch ...");
00338 TIMED_ASSERT(3.0, (odom->GetMsgCopy().twist.twist.linear.x < -0.2),
00339 "Measuring the forward and lateral velocities from odom ...");
00340 StopBebop();
00341
00342 tw.linear.x = 0.0;
00343 tw.linear.y = 0.4;
00344 tw.linear.z = 0.0;
00345 tw.angular.z = 0.0;
00346 ROS_WARN("Moving left ...");
00347 cmdvel_pub_.publish(tw);
00348 TIMED_ASSERT(3.0, angles::to_degrees(att_state->GetMsgCopy().roll) < -2.5, "Measuring roll ...");
00349 TIMED_ASSERT(3.0, (odom->GetMsgCopy().twist.twist.linear.y > 0.1),
00350 "Measuring the forward and lateral velocities from odom ...");
00351
00352 StopBebop();
00353
00354 tw.linear.x = 0.0;
00355 tw.linear.y = -0.4;
00356 tw.linear.z = 0.0;
00357 tw.angular.z = 0.0;
00358 ROS_WARN("Moving right ...");
00359 cmdvel_pub_.publish(tw);
00360 TIMED_ASSERT(3.0, angles::to_degrees(att_state->GetMsgCopy().roll) > 2.5, "Measuring roll ...");
00361 TIMED_ASSERT(3.0, (odom->GetMsgCopy().twist.twist.linear.y < -0.1),
00362 "Measuring the forward and lateral velocities from odom ...");
00363 StopBebop();
00364
00365 double alt_start, yaw_start, alt_start_odom, yaw_start_odom;
00366
00367 ASSERT_LT(alt_state->GetFreshness().toSec(), 0.5);
00368 ASSERT_LT(odom->GetFreshness().toSec(), 0.5);
00369
00370 alt_start = alt_state->GetMsgCopy().altitude;
00371 alt_start_odom = odom->GetMsgCopy().pose.pose.position.z;
00372 tw.linear.x = 0.0;
00373 tw.linear.y = 0.0;
00374 tw.linear.z = 0.2;
00375 tw.angular.z = 0.0;
00376 ROS_WARN("Ascending for 0.5m ...");
00377 cmdvel_pub_.publish(tw);
00378 TIMED_ASSERT(10.0,
00379 ((alt_state->GetMsgCopy().altitude - alt_start) >= 0.5) &&
00380 ((odom->GetMsgCopy().pose.pose.position.z - alt_start_odom) >= 0.5) &&
00381 (speed_state->GetMsgCopy().speedZ < -0.05) &&
00382 (odom->GetMsgCopy().twist.twist.linear.z > 0.05),
00383 "Measuring altitude, speed.z and vertical velocity from odom ...");
00384
00385 StopBebop();
00386
00387
00388 ASSERT_LT(alt_state->GetFreshness().toSec(), 0.5);
00389 ASSERT_LT(odom->GetFreshness().toSec(), 0.5);
00390 alt_start = alt_state->GetMsgCopy().altitude;
00391 alt_start_odom = odom->GetMsgCopy().pose.pose.position.z;
00392 tw.linear.x = 0.0;
00393 tw.linear.y = 0.0;
00394 tw.linear.z = -0.2;
00395 tw.angular.z = 0.0;
00396 ROS_WARN("Descending for 0.5m ...");
00397 cmdvel_pub_.publish(tw);
00398 TIMED_ASSERT(10.0,
00399 ((alt_state->GetMsgCopy().altitude - alt_start) <= -0.5) &&
00400 ((odom->GetMsgCopy().pose.pose.position.z - alt_start_odom) <= -0.5) &&
00401 (speed_state->GetMsgCopy().speedZ > 0.05) &&
00402 (odom->GetMsgCopy().twist.twist.linear.z < -0.05),
00403 "Measuring altitude, speed.z and vertical velocity from odom ...");
00404
00405 StopBebop();
00406
00407
00408 ASSERT_LT(att_state->GetFreshness().toSec(), 0.5);
00409 ASSERT_LT(odom->GetFreshness().toSec(), 0.5);
00410 yaw_start = att_state->GetMsgCopy().yaw;
00411 tw.linear.x = 0.0;
00412 tw.linear.y = 0.0;
00413 tw.linear.z = 0.0;
00414 tw.angular.z = -0.5;
00415 ROS_WARN("Rotating CW for 90 degrees ...");
00416 cmdvel_pub_.publish(tw);
00417
00418
00419 TIMED_ASSERT(10.0,
00420 angles::normalize_angle(att_state->GetMsgCopy().yaw - yaw_start) >= 0.5 * 3.141596,
00421 "Measuring Yaw");
00422
00423 StopBebop();
00424
00425
00426 ASSERT_LT(att_state->GetFreshness().toSec(), 0.5);
00427 yaw_start = att_state->GetMsgCopy().yaw;
00428 tw.linear.x = 0.0;
00429 tw.linear.y = 0.0;
00430 tw.linear.z = 0.0;
00431 tw.angular.z = 0.5;
00432 ROS_WARN("Rotating CCW for 90 degrees ...");
00433 cmdvel_pub_.publish(tw);
00434 TIMED_ASSERT(10.0,
00435 angles::normalize_angle(att_state->GetMsgCopy().yaw - yaw_start) <= -0.5 * 3.141596,
00436 "Measuring Yaw");
00437
00438 StopBebop();
00439
00440
00441 TIMED_ASSERT(20.0, bat_state->IsActive(), "Measuring battery ...");
00442 const uint8_t bat_percent = bat_state->GetMsgCopy().percent;
00443
00444 tw.linear.x = 0.0;
00445 tw.linear.y = 0.0;
00446 tw.linear.z = 0.0;
00447 tw.angular.z = 0.0;
00448 ROS_WARN("Stop ...");
00449 cmdvel_pub_.publish(tw);
00450
00451 ROS_WARN("Landing ...");
00452 land_pub_.publish(em);
00453
00454 TIMED_ASSERT(10.0,
00455 flying_state->IsActive() && flying_state->GetMsgCopy().state ==
00456 bebop_msgs::Ardrone3PilotingStateFlyingStateChanged::state_landed,
00457 "Waiting for land to finish..."
00458 );
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 ASSERT_GE(bat_percent - bat_state->GetMsgCopy().percent, 0);
00471 }
00472
00473
00474
00475 TEST_F(BebopInTheLoopTest, StaticTFTest)
00476 {
00477 tf2_ros::Buffer tf_buffer;
00478 tf2_ros::TransformListener tf_listener(tf_buffer, nh_);
00479
00480
00481 ASSERT_THROW(tf_buffer.lookupTransform("odom", "base_link", ros::Time(0), ros::Duration(2.0)), tf2::TransformException);
00482 try
00483 {
00484 geometry_msgs::TransformStamped odom_to_base = tf_buffer.lookupTransform("odom_custom", "base_link", ros::Time(0), ros::Duration(5.0));
00485
00486
00487
00488
00489
00490 geometry_msgs::TransformStamped base_to_optical = tf_buffer.lookupTransform(
00491 "base_link", "camera_optical", ros::Time(0), ros::Duration(5.0));
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 }
00506 catch (const tf2::TransformException& ex)
00507 {
00508 ASSERT_TRUE(false) << ex.what();
00509 }
00510 }
00511
00512 TEST_F(BebopInTheLoopTest, GPSTest)
00513 {
00514 boost::shared_ptr<util::ASyncSub<sensor_msgs::NavSatFix> > fix_sub(
00515 new util::ASyncSub<sensor_msgs::NavSatFix>(nh_, "fix", 10));
00516
00517 TIMED_ASSERT(2.0, fix_sub->IsActive() , "Waiting for the GPS topic ...");
00518
00519 sensor_msgs::NavSatFix gps = fix_sub->GetMsgCopy();
00520
00521 ASSERT_GT(gps.header.frame_id.length(), 0);
00522 ASSERT_NE(gps.status.service, 0);
00523
00524 const bool is_valid = gps.status.status >= sensor_msgs::NavSatStatus::STATUS_FIX;
00525
00526 if (!is_valid)
00527 {
00528 ASSERT_DOUBLE_EQ(gps.latitude, 500.0);
00529 ASSERT_DOUBLE_EQ(gps.longitude, 500.0);
00530 ASSERT_DOUBLE_EQ(gps.altitude, 500.0);
00531 }
00532 else
00533 {
00534 ASSERT_NE(gps.latitude, 500.0);
00535 ASSERT_NE(gps.longitude, 500.0);
00536 ASSERT_NE(gps.altitude, 500.0);
00537 }
00538 }
00539
00540 TEST_F(BebopInTheLoopTest, VisionTest)
00541 {
00542 boost::shared_ptr<util::ASyncSub<sensor_msgs::CameraInfo> > camera_(
00543 new util::ASyncSub<sensor_msgs::CameraInfo>(nh_, "camera_info", 10));
00544
00545 TIMED_ASSERT(2.0, image_->IsActive() && camera_->IsActive() , "Waiting for front video stream ...");
00546
00547 sensor_msgs::Image img = image_->GetMsgCopy();
00548
00549 const std::size_t sz = img.step * img.height;
00550
00551 ASSERT_TRUE(img.header.frame_id.length());
00552 ASSERT_GT(img.width, 0);
00553 ASSERT_GT(img.height, 0);
00554 ASSERT_GT(img.header.stamp.toSec(), 0.0);
00555 ASSERT_GT(sz, 0);
00556
00557 ASSERT_GE(std::accumulate(img.data.begin(), img.data.end(), 0.0) , 0.0);
00558
00559 sensor_msgs::CameraInfo cam_msg = camera_->GetMsgCopy();
00560
00561 ASSERT_EQ(cam_msg.width, img.width);
00562 ASSERT_EQ(cam_msg.height, img.height);
00563 ASSERT_EQ(cam_msg.header.frame_id, img.header.frame_id);
00564 ASSERT_GT(cam_msg.header.stamp.toSec(), 0.0);
00565 ASSERT_FALSE(cam_msg.distortion_model.empty());
00566
00567 ASSERT_FALSE(cam_msg.D.empty());
00568 ASSERT_FALSE(cam_msg.K.empty());
00569 ASSERT_FALSE(cam_msg.R.empty());
00570 ASSERT_FALSE(cam_msg.P.empty());
00571
00572 ASSERT_GT(fabs(cam_msg.D[0]), 0.0);
00573 ASSERT_GT(fabs(cam_msg.K[0]), 0.0);
00574 ASSERT_GT(fabs(cam_msg.R[0]), 0.0);
00575 ASSERT_GT(fabs(cam_msg.P[0]), 0.0);
00576 }
00577
00578 TEST_F(BebopInTheLoopTest, CameraMoveTest)
00579 {
00580 boost::shared_ptr<util::ASyncSub<bebop_msgs::Ardrone3CameraStateOrientation> >
00581 camera_state(new util::ASyncSub<bebop_msgs::Ardrone3CameraStateOrientation>(
00582 nh_, "states/ardrone3/CameraState/Orientation", 10));
00583
00584 ros::Publisher twist_pub = nh_.advertise<geometry_msgs::Twist>("camera_control", 1);
00585 TIMED_ASSERT(5.0, twist_pub.getNumSubscribers() > 0, "Waiting for camera control subscription ...");
00586
00587
00588 tw.angular.y = 13;
00589
00590 tw.angular.z = -16;
00591
00592 ROS_WARN("Moving the virtual camera");
00593 twist_pub.publish(tw);
00594 ros::Rate(ros::Duration(2)).sleep();
00595
00596 TIMED_ASSERT(5.0, camera_state->IsActive(), "Waiting for camera state ...");
00597
00598 ASSERT_EQ(camera_state->GetMsgCopy().tilt, 13);
00599 ASSERT_EQ(camera_state->GetMsgCopy().pan, -16);
00600
00601
00602 }
00603
00604 TEST_F(BebopInTheLoopTest, DISABLED_FlatTrimTest)
00605 {
00606 boost::shared_ptr<util::ASyncSub<bebop_msgs::Ardrone3PilotingStateFlyingStateChanged> >
00607 flattrim_state(new util::ASyncSub<bebop_msgs::Ardrone3PilotingStateFlyingStateChanged>(
00608 nh_, "states/ardrone3/PilotingState/FlyingStateChanged", 10));
00609 ros::Publisher flattrim_pub = nh_.advertise<std_msgs::Empty>("flattrim", 1);
00610
00611
00612 TIMED_ASSERT(5.0, flattrim_pub.getNumSubscribers() > 0, "Waiting for flattrim subscription ...");
00613
00614 ROS_WARN("Flat trim ...");
00615 flattrim_pub.publish(em);
00616
00617 TIMED_ASSERT(10.0,
00618 flattrim_state->IsActive(),
00619 "Waiting for flattrim ack ..."
00620 );
00621 }
00622 }
00623 }
00624
00625
00626
00627 int main(int argc, char* argv[])
00628 {
00629 ros::init(argc, argv, "bebop_itl_test");
00630 ros::NodeHandle keep_me_awake;
00631 testing::InitGoogleTest(&argc, argv);
00632 const int res = RUN_ALL_TESTS();
00633 ros::shutdown();
00634 return res;
00635 }