27 #include <boost/shared_ptr.hpp> 28 #include <boost/bind.hpp> 29 #include <boost/thread/mutex.hpp> 30 #include <boost/thread/locks.hpp> 31 #include <boost/function.hpp> 34 #include <std_msgs/Empty.h> 35 #include <geometry_msgs/Twist.h> 36 #include <sensor_msgs/Image.h> 37 #include <angles/angles.h> 38 #include <sensor_msgs/CameraInfo.h> 39 #include <nav_msgs/Odometry.h> 40 #include <sensor_msgs/NavSatFix.h> 44 #include <gtest/gtest.h> 46 #include <bebop_msgs/Ardrone3PilotingStateFlyingStateChanged.h> 47 #include <bebop_msgs/Ardrone3PilotingStateAttitudeChanged.h> 48 #include <bebop_msgs/Ardrone3CameraStateOrientation.h> 49 #include <bebop_msgs/Ardrone3PilotingStateFlyingStateChanged.h> 50 #include <bebop_msgs/Ardrone3PilotingStateSpeedChanged.h> 51 #include <bebop_msgs/Ardrone3PilotingStateAltitudeChanged.h> 52 #include <bebop_msgs/CommonCommonStateBatteryStateChanged.h> 54 #define TIMED_ASSERT(TIMEOUT, WAIT_UNTIL_TRUE, WAITING_TEXT) \ 57 const ros::Time start = ros::Time::now(); \ 58 while (((ros::Time::now() - start).toSec() < TIMEOUT) && (!(WAIT_UNTIL_TRUE))) \ 60 ROS_INFO_ONCE(WAITING_TEXT); \ 61 ros::Rate(5.0).sleep(); \ 63 ASSERT_TRUE(WAIT_UNTIL_TRUE); \ 76 typedef boost::function<void (const boost::shared_ptr<T const>& data)>
callback_t;
90 boost::lock_guard<boost::mutex> lock(mutex_);
99 const std::string& topic,
100 const std::size_t queue_size,
102 : nh(nh), active_(false), last_updated_(0), topic_(topic), user_callback_(user_callback)
109 boost::lock_guard<boost::mutex> lock(mutex_);
115 boost::lock_guard<boost::mutex> lock(mutex_);
129 boost::lock_guard<boost::mutex> lock(mutex_);
138 ROS_WARN(
"Information on topic (%s) is older than (%4.2lf) seconds. Deactivating.", topic_.c_str(), seconds);
145 boost::lock_guard<boost::mutex> lock(mutex_);
151 boost::lock_guard<boost::mutex> lock(mutex_);
157 boost::lock_guard<boost::mutex> lock(mutex_);
167 void dummy_cb(
const bebop_msgs::Ardrone3PilotingStateAttitudeChanged::ConstPtr& msg_ptr)
169 ROS_INFO(
"Roll: %0.2lf, Pitch: %0.2lf, Yaw: %0.2lf",
170 msg_ptr->roll, msg_ptr->pitch, msg_ptr->yaw);
183 geometry_msgs::Twist
tw;
196 land_pub_= nh_.
advertise<std_msgs::Empty>(
"land", 1);
197 cmdvel_pub_ = nh_.
advertise<geometry_msgs::Twist>(
"cmd_vel", 1);
201 nh_,
"image_raw", 10));
204 spinner_ptr_->start();
210 TIMED_ASSERT(15.0, image_->IsActive(),
"Waiting for Bebop ...");
234 spinner_ptr_->stop();
253 nh_,
"states/ardrone3/PilotingState/FlyingStateChanged", 10));
257 nh_,
"states/ardrone3/PilotingState/SpeedChanged", 10));
261 nh_,
"states/ardrone3/PilotingState/AltitudeChanged", 10));
265 nh_,
"states/ardrone3/PilotingState/AttitudeChanged", 10));
271 nh_,
"states/common/CommonState/BatteryStateChanged", 10));
281 ros::Publisher takeoff_pub = nh_.advertise<std_msgs::Empty>(
"takeoff", 1);
282 ros::Publisher reset_pub = nh_.advertise<std_msgs::Empty>(
"reset", 1);
286 TIMED_ASSERT(5.0, cmdvel_pub_.getNumSubscribers() > 0,
"Waiting for cmd_vel subscription ...");
287 TIMED_ASSERT(5.0, reset_pub.getNumSubscribers() > 0,
"Waiting for reset subscription ...");
292 flying_state->IsActive() && flying_state->GetMsgCopy().state ==
293 bebop_msgs::Ardrone3PilotingStateFlyingStateChanged::state_hovering,
294 "Waiting for takeoff to finish ..." 297 TIMED_ASSERT(5.0, speed_state->IsActive(),
"Waiting for Speed measurements ...");
298 TIMED_ASSERT(5.0, alt_state->IsActive(),
"Waiting for alt measurements ...");
299 TIMED_ASSERT(5.0, att_state->IsActive(),
"Waiting for attitude measurements ...");
300 TIMED_ASSERT(5.0, odom->IsActive(),
"Waiting for odom ...");
301 TIMED_ASSERT(5.0, gps->IsActive(),
"Waiting for GPS ...");
309 ROS_WARN(
"Moving forwared ...");
310 cmdvel_pub_.publish(tw);
312 TIMED_ASSERT(3.0, angles::to_degrees(att_state->GetMsgCopy().pitch) < -2.5 ,
"Measuring pitch ...");
313 TIMED_ASSERT(3.0, (odom->GetMsgCopy().twist.twist.linear.x > 0.2),
314 "Measuring the forward and lateral velocities from odom ...");
318 (fabs(speed_state->GetMsgCopy().speedX) < 0.05) &&
319 (fabs(speed_state->GetMsgCopy().speedY) < 0.05) &&
320 (fabs(speed_state->GetMsgCopy().speedZ) < 0.05)
321 ,
"Measuring the speed vector ...");
324 (fabs(odom->GetMsgCopy().twist.twist.linear.x) < 0.05) &&
325 (fabs(odom->GetMsgCopy().twist.twist.linear.y) < 0.05) &&
326 (fabs(odom->GetMsgCopy().twist.twist.linear.z) < 0.05)
327 ,
"Measuring the speed vector from odom...");
334 ROS_WARN(
"Moving Backward ...");
335 cmdvel_pub_.publish(tw);
337 TIMED_ASSERT(3.0, angles::to_degrees(att_state->GetMsgCopy().pitch) > 2.5,
"Measuring pitch ...");
338 TIMED_ASSERT(3.0, (odom->GetMsgCopy().twist.twist.linear.x < -0.2),
339 "Measuring the forward and lateral velocities from odom ...");
346 ROS_WARN(
"Moving left ...");
347 cmdvel_pub_.publish(tw);
348 TIMED_ASSERT(3.0, angles::to_degrees(att_state->GetMsgCopy().roll) < -2.5,
"Measuring roll ...");
349 TIMED_ASSERT(3.0, (odom->GetMsgCopy().twist.twist.linear.y > 0.1),
350 "Measuring the forward and lateral velocities from odom ...");
358 ROS_WARN(
"Moving right ...");
359 cmdvel_pub_.publish(tw);
360 TIMED_ASSERT(3.0, angles::to_degrees(att_state->GetMsgCopy().roll) > 2.5,
"Measuring roll ...");
361 TIMED_ASSERT(3.0, (odom->GetMsgCopy().twist.twist.linear.y < -0.1),
362 "Measuring the forward and lateral velocities from odom ...");
365 double alt_start, yaw_start, alt_start_odom, yaw_start_odom;
367 ASSERT_LT(alt_state->GetFreshness().toSec(), 0.5);
368 ASSERT_LT(odom->GetFreshness().toSec(), 0.5);
370 alt_start = alt_state->GetMsgCopy().altitude;
371 alt_start_odom = odom->GetMsgCopy().pose.pose.position.z;
376 ROS_WARN(
"Ascending for 0.5m ...");
377 cmdvel_pub_.publish(tw);
379 ((alt_state->GetMsgCopy().altitude - alt_start) >= 0.5) &&
380 ((odom->GetMsgCopy().pose.pose.position.z - alt_start_odom) >= 0.5) &&
381 (speed_state->GetMsgCopy().speedZ < -0.05) &&
382 (odom->GetMsgCopy().twist.twist.linear.z > 0.05),
383 "Measuring altitude, speed.z and vertical velocity from odom ...");
388 ASSERT_LT(alt_state->GetFreshness().toSec(), 0.5);
389 ASSERT_LT(odom->GetFreshness().toSec(), 0.5);
390 alt_start = alt_state->GetMsgCopy().altitude;
391 alt_start_odom = odom->GetMsgCopy().pose.pose.position.z;
396 ROS_WARN(
"Descending for 0.5m ...");
397 cmdvel_pub_.publish(tw);
399 ((alt_state->GetMsgCopy().altitude - alt_start) <= -0.5) &&
400 ((odom->GetMsgCopy().pose.pose.position.z - alt_start_odom) <= -0.5) &&
401 (speed_state->GetMsgCopy().speedZ > 0.05) &&
402 (odom->GetMsgCopy().twist.twist.linear.z < -0.05),
403 "Measuring altitude, speed.z and vertical velocity from odom ...");
408 ASSERT_LT(att_state->GetFreshness().toSec(), 0.5);
409 ASSERT_LT(odom->GetFreshness().toSec(), 0.5);
410 yaw_start = att_state->GetMsgCopy().yaw;
415 ROS_WARN(
"Rotating CW for 90 degrees ...");
416 cmdvel_pub_.publish(tw);
420 angles::normalize_angle(att_state->GetMsgCopy().yaw - yaw_start) >= 0.5 * 3.141596,
426 ASSERT_LT(att_state->GetFreshness().toSec(), 0.5);
427 yaw_start = att_state->GetMsgCopy().yaw;
432 ROS_WARN(
"Rotating CCW for 90 degrees ...");
433 cmdvel_pub_.publish(tw);
435 angles::normalize_angle(att_state->GetMsgCopy().yaw - yaw_start) <= -0.5 * 3.141596,
441 TIMED_ASSERT(20.0, bat_state->IsActive(),
"Measuring battery ...");
442 const uint8_t bat_percent = bat_state->GetMsgCopy().percent;
448 ROS_WARN(
"Stop ...");
449 cmdvel_pub_.publish(tw);
451 ROS_WARN(
"Landing ...");
452 land_pub_.publish(em);
455 flying_state->IsActive() && flying_state->GetMsgCopy().state ==
456 bebop_msgs::Ardrone3PilotingStateFlyingStateChanged::state_landed,
457 "Waiting for land to finish..." 470 ASSERT_GE(bat_percent - bat_state->GetMsgCopy().percent, 0);
490 geometry_msgs::TransformStamped base_to_optical = tf_buffer.
lookupTransform(
508 ASSERT_TRUE(
false) << ex.what();
517 TIMED_ASSERT(2.0, fix_sub->IsActive() ,
"Waiting for the GPS topic ...");
519 sensor_msgs::NavSatFix gps = fix_sub->GetMsgCopy();
521 ASSERT_GT(gps.header.frame_id.length(), 0);
522 ASSERT_NE(gps.status.service, 0);
524 const bool is_valid = gps.status.status >= sensor_msgs::NavSatStatus::STATUS_FIX;
528 ASSERT_DOUBLE_EQ(gps.latitude, 500.0);
529 ASSERT_DOUBLE_EQ(gps.longitude, 500.0);
530 ASSERT_DOUBLE_EQ(gps.altitude, 500.0);
534 ASSERT_NE(gps.latitude, 500.0);
535 ASSERT_NE(gps.longitude, 500.0);
536 ASSERT_NE(gps.altitude, 500.0);
545 TIMED_ASSERT(2.0, image_->IsActive() && camera_->IsActive() ,
"Waiting for front video stream ...");
547 sensor_msgs::Image img = image_->GetMsgCopy();
549 const std::size_t sz = img.step * img.height;
551 ASSERT_TRUE(img.header.frame_id.length());
552 ASSERT_GT(img.width, 0);
553 ASSERT_GT(img.height, 0);
554 ASSERT_GT(img.header.stamp.toSec(), 0.0);
557 ASSERT_GE(std::accumulate(img.data.begin(), img.data.end(), 0.0) , 0.0);
559 sensor_msgs::CameraInfo cam_msg = camera_->GetMsgCopy();
561 ASSERT_EQ(cam_msg.width, img.width);
562 ASSERT_EQ(cam_msg.height, img.height);
563 ASSERT_EQ(cam_msg.header.frame_id, img.header.frame_id);
564 ASSERT_GT(cam_msg.header.stamp.toSec(), 0.0);
565 ASSERT_FALSE(cam_msg.distortion_model.empty());
567 ASSERT_FALSE(cam_msg.D.empty());
568 ASSERT_FALSE(cam_msg.K.empty());
569 ASSERT_FALSE(cam_msg.R.empty());
570 ASSERT_FALSE(cam_msg.P.empty());
572 ASSERT_GT(fabs(cam_msg.D[0]), 0.0);
573 ASSERT_GT(fabs(cam_msg.K[0]), 0.0);
574 ASSERT_GT(fabs(cam_msg.R[0]), 0.0);
575 ASSERT_GT(fabs(cam_msg.P[0]), 0.0);
582 nh_,
"states/ardrone3/CameraState/Orientation", 10));
584 ros::Publisher twist_pub = nh_.advertise<geometry_msgs::Twist>(
"camera_control", 1);
592 ROS_WARN(
"Moving the virtual camera");
596 TIMED_ASSERT(5.0, camera_state->IsActive(),
"Waiting for camera state ...");
598 ASSERT_EQ(camera_state->GetMsgCopy().tilt, 13);
599 ASSERT_EQ(camera_state->GetMsgCopy().pan, -16);
608 nh_,
"states/ardrone3/PilotingState/FlyingStateChanged", 10));
609 ros::Publisher flattrim_pub = nh_.advertise<std_msgs::Empty>(
"flattrim", 1);
618 flattrim_state->IsActive(),
619 "Waiting for flattrim ack ..." 627 int main(
int argc,
char* argv[])
631 testing::InitGoogleTest(&argc, argv);
632 const int res = RUN_ALL_TESTS();
boost::shared_ptr< T const > msg_cptr_
void publish(const boost::shared_ptr< M > &message) const
void DeactivateIfOlderThan(const double seconds)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
callback_t user_callback_
void dummy_cb(const bebop_msgs::Ardrone3PilotingStateAttitudeChanged::ConstPtr &msg_ptr)
boost::shared_ptr< util::ASyncSub< sensor_msgs::Image > > image_
const ros::Time GetLastUpdated() const
#define TIMED_ASSERT(TIMEOUT, WAIT_UNTIL_TRUE, WAITING_TEXT)
boost::shared_ptr< ros::AsyncSpinner > spinner_ptr_
const boost::shared_ptr< T const > & GetMsgConstPtr() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void cb(const boost::shared_ptr< T const > &msg_cptr)
const ros::Duration GetFreshness() const
tf2_ros::Buffer * tf_buffer
uint32_t getNumSubscribers() const
ASyncSub(ros::NodeHandle &nh, const std::string &topic, const std::size_t queue_size, callback_t user_callback=0)
ROSCPP_DECL void shutdown()
TEST_F(BebopInTheLoopTest, DISABLED_FlatTrimTest)
ros::Publisher cmdvel_pub_
const boost::shared_ptr< T const > & operator()() const
boost::function< void(const boost::shared_ptr< T const > &data)> callback_t
int main(int argc, char *argv[])