bebop_itl_test.cpp
Go to the documentation of this file.
1 
25 #include <string>
26 #include <numeric>
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>
32 
33 #include <ros/ros.h>
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>
43 
44 #include <gtest/gtest.h>
45 
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>
53 
54 #define TIMED_ASSERT(TIMEOUT, WAIT_UNTIL_TRUE, WAITING_TEXT) \
55 do \
56 { \
57  const ros::Time start = ros::Time::now(); \
58  while (((ros::Time::now() - start).toSec() < TIMEOUT) && (!(WAIT_UNTIL_TRUE))) \
59  { \
60  ROS_INFO_ONCE(WAITING_TEXT); \
61  ros::Rate(5.0).sleep(); \
62  } \
63  ASSERT_TRUE(WAIT_UNTIL_TRUE); \
64 } \
65 while (0) \
66 
67 namespace bebop_driver
68 {
69 namespace util
70 {
71 
72 template<typename T>
73 class ASyncSub
74 {
75 private:
76  typedef boost::function<void (const boost::shared_ptr<T const>& data)> callback_t;
77 
79  bool active_;
81  std::string topic_;
82  std::size_t queue_size_;
86  mutable boost::mutex mutex_;
87 
88  void cb(const boost::shared_ptr<T const> &msg_cptr)
89  {
90  boost::lock_guard<boost::mutex> lock(mutex_);
91  active_ = true;
92  last_updated_ = ros::Time::now();
93  msg_cptr_ = msg_cptr;
94  if (user_callback_) user_callback_(msg_cptr_);
95  }
96 
97 public:
99  const std::string& topic,
100  const std::size_t queue_size,
101  callback_t user_callback = 0)
102  : nh(nh), active_(false), last_updated_(0), topic_(topic), user_callback_(user_callback)
103  {
104  sub_ = nh.subscribe<T>(topic_, queue_size, boost::bind(&ASyncSub<T>::cb, this, _1));
105  }
106 
107  T GetMsgCopy() const
108  {
109  boost::lock_guard<boost::mutex> lock(mutex_);
110  return *msg_cptr_;
111  }
112 
114  {
115  boost::lock_guard<boost::mutex> lock(mutex_);
116  return msg_cptr_;
117  }
118 
119  // T operator ()() const {return GetMsgCopy();}
120 
122  {
123  // no need to acquire the lock here, since the underlying function does that
124  return GetMsgConstPtr();
125  }
126 
127  void Deactivate()
128  {
129  boost::lock_guard<boost::mutex> lock(mutex_);
130  active_ = false;
131  }
132 
133  void DeactivateIfOlderThan(const double seconds)
134  {
135  if (!IsActive()) return;
136  if (GetFreshness().toSec() > seconds)
137  {
138  ROS_WARN("Information on topic (%s) is older than (%4.2lf) seconds. Deactivating.", topic_.c_str(), seconds);
139  Deactivate();
140  }
141  }
142 
143  bool IsActive() const
144  {
145  boost::lock_guard<boost::mutex> lock(mutex_);
146  return active_;
147  }
148 
149  const ros::Time GetLastUpdated() const
150  {
151  boost::lock_guard<boost::mutex> lock(mutex_);
152  return last_updated_;
153  }
154 
156  {
157  boost::lock_guard<boost::mutex> lock(mutex_);
158  return ros::Time::now() - last_updated_;
159  }
160 };
161 
162 } // namespace util
163 
164 namespace test
165 {
166 
167 void dummy_cb(const bebop_msgs::Ardrone3PilotingStateAttitudeChanged::ConstPtr& msg_ptr)
168 {
169  ROS_INFO("Roll: %0.2lf, Pitch: %0.2lf, Yaw: %0.2lf",
170  msg_ptr->roll, msg_ptr->pitch, msg_ptr->yaw);
171 }
172 
173 class BebopInTheLoopTest: public ::testing::Test
174 {
175 protected:
178 
181 
182  std_msgs::Empty em;
183  geometry_msgs::Twist tw;
184 
186 
187 // boost::shared_ptr<util::ASyncSub<bebop_msgs::Ardrone3PilotingStateAttitudeChanged> > attitude_state_;
188 
189  virtual void SetUp()
190  {
191  ros::NodeHandle priv_nh("~");
192 
193  ROS_INFO("In SetUp()");
194 
195  // Common Publishers
196  land_pub_= nh_.advertise<std_msgs::Empty>("land", 1);
197  cmdvel_pub_ = nh_.advertise<geometry_msgs::Twist>("cmd_vel", 1);
198 
199  // Common Subs
200  image_.reset(new util::ASyncSub<sensor_msgs::Image>(
201  nh_, "image_raw", 10));
202 
203  spinner_ptr_.reset(new ros::AsyncSpinner(4));
204  spinner_ptr_->start();
205 
206  // Wait 10s for Bebop to come up
207  ros::Time start = ros::Time::now();
208 
209  // Check image_ (when image_ is being published, everything else is ready)
210  TIMED_ASSERT(15.0, image_->IsActive(), "Waiting for Bebop ...");
211  TIMED_ASSERT(5.0, land_pub_.getNumSubscribers() > 0, "Waiting for land subscription ...");
212 
213  ROS_INFO("End SetUp()");
214  }
215 
216  void StopBebop()
217  {
218  tw.linear.x = 0.0;
219  tw.linear.y = 0.0;
220  tw.linear.z = 0.0;
221  tw.angular.z = 0.0;
222  ROS_WARN("Stopping ...");
223  cmdvel_pub_.publish(tw);
224  ros::Duration(1.0).sleep();
225  }
226 
227  virtual void TearDown()
228  {
229  ROS_INFO("In teardown()");
230  StopBebop();
231  std_msgs::Empty em;
232  land_pub_.publish(em);
233  ros::Rate(ros::Duration(2.0)).sleep();
234  spinner_ptr_->stop();
235  }
236 
237 };
238 
239 /*
240  * Parrot's coordinate system for velocities:
241  * +x: forward
242  * +y: right
243  * +z: downward
244  *
245  * (not ROS compatible)
246  *
247  * odom on the other hand is REP-103 compatible
248  */
250 {
253  nh_, "states/ardrone3/PilotingState/FlyingStateChanged", 10));
254 
257  nh_, "states/ardrone3/PilotingState/SpeedChanged", 10));
258 
261  nh_, "states/ardrone3/PilotingState/AltitudeChanged", 10));
262 
265  nh_, "states/ardrone3/PilotingState/AttitudeChanged", 10));
266 
267  // The problem with the battery state is that it is only updated when its values changes,
268  // this is more likely to happen when flying than sitting on the ground
271  nh_, "states/common/CommonState/BatteryStateChanged", 10));
272 
275  nh_, "odom", 10));
276 
279  nh_, "fix", 10));
280 
281  ros::Publisher takeoff_pub = nh_.advertise<std_msgs::Empty>("takeoff", 1);
282  ros::Publisher reset_pub = nh_.advertise<std_msgs::Empty>("reset", 1);
283 
284  // Wait 5s time for connections to establish
285  TIMED_ASSERT(5.0, takeoff_pub.getNumSubscribers() > 0, "Waiting for takeoff subscription ...");
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 ...");
288 
289  ROS_WARN("Taking off ...");
290  takeoff_pub.publish(em);
291  TIMED_ASSERT(10.0,
292  flying_state->IsActive() && flying_state->GetMsgCopy().state ==
293  bebop_msgs::Ardrone3PilotingStateFlyingStateChanged::state_hovering,
294  "Waiting for takeoff to finish ..."
295  );
296 
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 ...");
302 
303  // TODO(mani-monaj): Use proper values for pitch/roll test thresholds based on cmd_vel
304 
305  tw.linear.x = 0.4;
306  tw.linear.y = 0.0;
307  tw.linear.z = 0.0;
308  tw.angular.z = 0.0;
309  ROS_WARN("Moving forwared ...");
310  cmdvel_pub_.publish(tw);
311 
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 ...");
315 
316  StopBebop();
317  TIMED_ASSERT(5.0,
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 ...");
322 
323  TIMED_ASSERT(5.0,
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...");
328 
329 
330  tw.linear.x = -0.4;
331  tw.linear.y = 0.0;
332  tw.linear.z = 0.0;
333  tw.angular.z = 0.0;
334  ROS_WARN("Moving Backward ...");
335  cmdvel_pub_.publish(tw);
336 
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 ...");
340  StopBebop();
341 
342  tw.linear.x = 0.0;
343  tw.linear.y = 0.4;
344  tw.linear.z = 0.0;
345  tw.angular.z = 0.0;
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 ...");
351 
352  StopBebop();
353 
354  tw.linear.x = 0.0;
355  tw.linear.y = -0.4;
356  tw.linear.z = 0.0;
357  tw.angular.z = 0.0;
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 ...");
363  StopBebop();
364 
365  double alt_start, yaw_start, alt_start_odom, yaw_start_odom;
366  // Make sure altitude is fresh
367  ASSERT_LT(alt_state->GetFreshness().toSec(), 0.5);
368  ASSERT_LT(odom->GetFreshness().toSec(), 0.5);
369 
370  alt_start = alt_state->GetMsgCopy().altitude;
371  alt_start_odom = odom->GetMsgCopy().pose.pose.position.z;
372  tw.linear.x = 0.0;
373  tw.linear.y = 0.0;
374  tw.linear.z = 0.2;
375  tw.angular.z = 0.0;
376  ROS_WARN("Ascending for 0.5m ...");
377  cmdvel_pub_.publish(tw);
378  TIMED_ASSERT(10.0,
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 ...");
384 
385  StopBebop();
386 
387  // Make sure altitude is fresh
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;
392  tw.linear.x = 0.0;
393  tw.linear.y = 0.0;
394  tw.linear.z = -0.2;
395  tw.angular.z = 0.0;
396  ROS_WARN("Descending for 0.5m ...");
397  cmdvel_pub_.publish(tw);
398  TIMED_ASSERT(10.0,
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 ...");
404 
405  StopBebop();
406 
407  // Make sure the attitude is fresh
408  ASSERT_LT(att_state->GetFreshness().toSec(), 0.5);
409  ASSERT_LT(odom->GetFreshness().toSec(), 0.5);
410  yaw_start = att_state->GetMsgCopy().yaw;
411  tw.linear.x = 0.0;
412  tw.linear.y = 0.0;
413  tw.linear.z = 0.0;
414  tw.angular.z = -0.5;
415  ROS_WARN("Rotating CW for 90 degrees ...");
416  cmdvel_pub_.publish(tw);
417 
418  // TODO(mani-monaj): Add yaw
419  TIMED_ASSERT(10.0,
420  angles::normalize_angle(att_state->GetMsgCopy().yaw - yaw_start) >= 0.5 * 3.141596,
421  "Measuring Yaw");
422 
423  StopBebop();
424 
425  // Make sure the attitude is fresh
426  ASSERT_LT(att_state->GetFreshness().toSec(), 0.5);
427  yaw_start = att_state->GetMsgCopy().yaw;
428  tw.linear.x = 0.0;
429  tw.linear.y = 0.0;
430  tw.linear.z = 0.0;
431  tw.angular.z = 0.5;
432  ROS_WARN("Rotating CCW for 90 degrees ...");
433  cmdvel_pub_.publish(tw);
434  TIMED_ASSERT(10.0,
435  angles::normalize_angle(att_state->GetMsgCopy().yaw - yaw_start) <= -0.5 * 3.141596,
436  "Measuring Yaw");
437 
438  StopBebop();
439 
440  /* By this time, battery state must have been changed (even on Bebop 2) */
441  TIMED_ASSERT(20.0, bat_state->IsActive(), "Measuring battery ...");
442  const uint8_t bat_percent = bat_state->GetMsgCopy().percent;
443 
444  tw.linear.x = 0.0;
445  tw.linear.y = 0.0;
446  tw.linear.z = 0.0;
447  tw.angular.z = 0.0;
448  ROS_WARN("Stop ...");
449  cmdvel_pub_.publish(tw);
450 
451  ROS_WARN("Landing ...");
452  land_pub_.publish(em);
453 
454  TIMED_ASSERT(10.0,
455  flying_state->IsActive() && flying_state->GetMsgCopy().state ==
456  bebop_msgs::Ardrone3PilotingStateFlyingStateChanged::state_landed,
457  "Waiting for land to finish..."
458  );
459 
460  // emergency state is transient (unlike ardrone), we may miss the signal
461 // ROS_WARN("Emergency ...");
462 // reset_pub.publish(em);
463 
464 // TIMED_ASSERT(5.0,
465 // flying_state->IsActive() && flying_state->GetMsgCopy().state ==
466 // bebop_msgs::Ardrone3PilotingStateFlyingStateChanged::state_emergency,
467 // "Waiting for reset to happen..."
468 // );
469 
470  ASSERT_GE(bat_percent - bat_state->GetMsgCopy().percent, 0);
471 }
472 
473 
474 // TODO(mani-monaj): Add value tests
476 {
478  tf2_ros::TransformListener tf_listener(tf_buffer, nh_);
479 
480  // We manually set the odom_frame_id to odom_custom in the launch file, so the following should throw
481  ASSERT_THROW(tf_buffer.lookupTransform("odom", "base_link", ros::Time(0), ros::Duration(2.0)), tf2::TransformException);
482  try
483  {
484  geometry_msgs::TransformStamped odom_to_base = tf_buffer.lookupTransform("odom_custom", "base_link", ros::Time(0), ros::Duration(5.0));
485 
486 // ASSERT_TRUE((fabs(odom_to_base.transform.translation.x) > 0.0) &&
487 // (fabs(odom_to_base.transform.translation.y) > 0.0) &&
488 // (fabs(odom_to_base.transform.translation.z) > 0.0));
489 
490  geometry_msgs::TransformStamped base_to_optical = tf_buffer.lookupTransform(
491  "base_link", "camera_optical", ros::Time(0), ros::Duration(5.0));
492 
493 // geometry_msgs::TransformStamped camera_to_optical = tf_buffer.lookupTransform(
494 // "camera_base_link", "camera_optical", ros::Time(0), ros::Duration(5.0));
495 
496 // tf2::Transform camera_to_optical_tf;
497 // double r, p, y;
498 // tf2::convert(camera_to_optical.transform, camera_to_optical_tf);
499 
500 // tf2::Matrix3x3(camera_to_optical_tf.getRotation()).getRPY(r, p, y);
501 // ASSERT_DOUBLE_EQ(r, 0.0);
502 // ASSERT_DOUBLE_EQ(p, 0.0);
503 // ASSERT_DOUBLE_EQ(y, 0.0);
504 // ASSERT_DOUBLE_EQ(camera_to_optical_tf.getOrigin().length(), 0.0);
505  }
506  catch (const tf2::TransformException& ex)
507  {
508  ASSERT_TRUE(false) << ex.what();
509  }
510 }
511 
513 {
515  new util::ASyncSub<sensor_msgs::NavSatFix>(nh_, "fix", 10));
516 
517  TIMED_ASSERT(2.0, fix_sub->IsActive() , "Waiting for the GPS topic ...");
518 
519  sensor_msgs::NavSatFix gps = fix_sub->GetMsgCopy();
520 
521  ASSERT_GT(gps.header.frame_id.length(), 0);
522  ASSERT_NE(gps.status.service, 0);
523 
524  const bool is_valid = gps.status.status >= sensor_msgs::NavSatStatus::STATUS_FIX;
525 
526  if (!is_valid)
527  {
528  ASSERT_DOUBLE_EQ(gps.latitude, 500.0);
529  ASSERT_DOUBLE_EQ(gps.longitude, 500.0);
530  ASSERT_DOUBLE_EQ(gps.altitude, 500.0);
531  }
532  else
533  {
534  ASSERT_NE(gps.latitude, 500.0);
535  ASSERT_NE(gps.longitude, 500.0);
536  ASSERT_NE(gps.altitude, 500.0);
537  }
538 }
539 
541 {
543  new util::ASyncSub<sensor_msgs::CameraInfo>(nh_, "camera_info", 10));
544 
545  TIMED_ASSERT(2.0, image_->IsActive() && camera_->IsActive() , "Waiting for front video stream ...");
546 
547  sensor_msgs::Image img = image_->GetMsgCopy();
548 
549  const std::size_t sz = img.step * img.height;
550 
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);
555  ASSERT_GT(sz, 0);
556 
557  ASSERT_GE(std::accumulate(img.data.begin(), img.data.end(), 0.0) , 0.0);
558 
559  sensor_msgs::CameraInfo cam_msg = camera_->GetMsgCopy();
560 
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());
566 
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());
571 
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);
576 }
577 
578 TEST_F(BebopInTheLoopTest, CameraMoveTest)
579 {
582  nh_, "states/ardrone3/CameraState/Orientation", 10));
583 
584  ros::Publisher twist_pub = nh_.advertise<geometry_msgs::Twist>("camera_control", 1);
585  TIMED_ASSERT(5.0, twist_pub.getNumSubscribers() > 0, "Waiting for camera control subscription ...");
586 
587  // tilt
588  tw.angular.y = 13;
589  // pan
590  tw.angular.z = -16;
591 
592  ROS_WARN("Moving the virtual camera");
593  twist_pub.publish(tw);
595 
596  TIMED_ASSERT(5.0, camera_state->IsActive(), "Waiting for camera state ...");
597 
598  ASSERT_EQ(camera_state->GetMsgCopy().tilt, 13);
599  ASSERT_EQ(camera_state->GetMsgCopy().pan, -16);
600 
601  // TODO(mani-monaj): Add TF tests
602 }
603 
604 TEST_F(BebopInTheLoopTest, DISABLED_FlatTrimTest)
605 {
608  nh_, "states/ardrone3/PilotingState/FlyingStateChanged", 10));
609  ros::Publisher flattrim_pub = nh_.advertise<std_msgs::Empty>("flattrim", 1);
610 
611  // Wait 5s time for connection to establish
612  TIMED_ASSERT(5.0, flattrim_pub.getNumSubscribers() > 0, "Waiting for flattrim subscription ...");
613 
614  ROS_WARN("Flat trim ...");
615  flattrim_pub.publish(em);
616 
617  TIMED_ASSERT(10.0,
618  flattrim_state->IsActive(),
619  "Waiting for flattrim ack ..."
620  );
621 }
622 } // namespace test
623 } // namespace bebop_driver
624 
625 
626 
627 int main(int argc, char* argv[])
628 {
629  ros::init(argc, argv, "bebop_itl_test");
630  ros::NodeHandle keep_me_awake;
631  testing::InitGoogleTest(&argc, argv);
632  const int res = RUN_ALL_TESTS();
633  ros::shutdown();
634  return res;
635 }
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())
bool sleep() const
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)
void dummy_cb(const bebop_msgs::Ardrone3PilotingStateAttitudeChanged::ConstPtr &msg_ptr)
#define ROS_WARN(...)
boost::shared_ptr< util::ASyncSub< sensor_msgs::Image > > image_
const ros::Time GetLastUpdated() const
#define TIMED_ASSERT(TIMEOUT, WAIT_UNTIL_TRUE, WAITING_TEXT)
#define ROS_INFO(...)
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)
bool sleep()
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)
static Time now()
ROSCPP_DECL void shutdown()
TEST_F(BebopInTheLoopTest, DISABLED_FlatTrimTest)
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[])


bebop_driver
Author(s): Mani Monajjemi
autogenerated on Mon Jun 10 2019 12:58:56