Go to the documentation of this file.00001
00010 #include "ucl_drone/pose_estimation.h"
00011
00012 #include <math.h>
00013
00014
00015 PoseEstimator::PoseEstimator()
00016 {
00017
00018
00019 ros::param::get("~use_visual_pose",
00020 this->use_visual_pose);
00021
00022 std::string drone_prefix;
00023 ros::param::get("~drone_prefix", drone_prefix);
00024
00025
00026
00027 navdata_channel =
00028 nh.resolveName(drone_prefix + "ardrone/navdata");
00029 navdata_sub = nh.subscribe(navdata_channel, 10, &PoseEstimator::navdataCb, this);
00030
00031 odometry_channel =
00032 nh.resolveName(drone_prefix + "ardrone/odometry");
00033
00034
00035 odometry_sub = nh.subscribe(odometry_channel, 10, &PoseEstimator::odometryCb, this);
00036
00037 pose_visual_channel = nh.resolveName("pose_visual");
00038 pose_visual_sub = nh.subscribe(pose_visual_channel, 1, &PoseEstimator::poseVisualCb, this);
00039
00040 reset_channel = nh.resolveName("reset_pose");
00041 reset_sub = nh.subscribe(reset_channel, 10, &PoseEstimator::resetCb, this);
00042
00043
00044
00045 if (this->use_visual_pose)
00046 {
00047 pose_channel = nh.resolveName("pose_estimation");
00048 end_reset_pose_channel = nh.resolveName("end_reset_pose");
00049 }
00050 else
00051 {
00052 pose_channel = nh.resolveName("blind_pose_estimation");
00053 end_reset_pose_channel = nh.resolveName("blind_end_reset_pose");
00054 }
00055
00056 pose_pub = nh.advertise< ucl_drone::Pose3D >(pose_channel, 1);
00057
00058 end_reset_pose_pub = nh.advertise< std_msgs::Empty >(end_reset_pose_channel, 1);
00059
00060 odometry_publishing = false;
00061 visual_pose_available = false;
00062 pending_reset = false;
00063 }
00064
00065
00066 PoseEstimator::~PoseEstimator()
00067 {
00068 }
00069
00070 void PoseEstimator::resetCb(const std_msgs::Empty msg)
00071 {
00072 pending_reset = true;
00073 }
00074
00075
00076
00077 void PoseEstimator::doFlatTrim()
00078 {
00079 ros::ServiceClient client = nh.serviceClient< std_srvs::Empty >("motherboard1/ardrone/flattrim");
00080 std_srvs::Empty srv;
00081 client.call(srv);
00082 }
00083
00084
00085 void PoseEstimator::doReset()
00086 {
00087 odometry_x = 0;
00088 odometry_y = 0;
00089 odometry_rotX = 0;
00090 odometry_rotY = 0;
00091 odometry_rotZ = 0;
00092 odom_time = lastOdometryReceived.header.stamp;
00093
00094 lastposeVisualReceived = ucl_drone::Pose3D();
00095 visual_pose_available = false;
00096
00097 rot_Z_offset = lastNavdataReceived.rotZ / 180.0 * PI;
00098 }
00099
00100 void PoseEstimator::navdataCb(const ardrone_autonomy::Navdata::ConstPtr navdataPtr)
00101 {
00102 if (pending_reset)
00103 return;
00104 lastNavdataReceived = *navdataPtr;
00105 }
00106
00107 void PoseEstimator::poseVisualCb(const ucl_drone::Pose3D::ConstPtr poseVisualPtr)
00108 {
00109 if (pending_reset)
00110 return;
00111
00112
00113 if (poseVisualPtr->header.stamp < ros::Time::now() - ros::Duration(1.0 / 2.0))
00114 {
00115 ROS_DEBUG("VISUAL POSE disregarded in pose_estimation");
00116 return;
00117 }
00118
00119 lastposeVisualReceived = *poseVisualPtr;
00120 visual_pose_available = true;
00121 }
00122
00123 void PoseEstimator::odometryCb(const nav_msgs::Odometry::ConstPtr odometryPtr)
00124 {
00125
00126
00127
00128
00129 if (std::isfinite(odometryPtr->twist.twist.linear.x) &&
00130 std::isfinite(odometryPtr->twist.twist.linear.y))
00131 {
00132 odometry_publishing = true;
00133 lastOdometryReceived = *odometryPtr;
00134 previous_rotX = lastRotX;
00135 previous_rotY = lastRotY;
00136 previous_rotZ = lastRotZ;
00137 lastRotX = lastNavdataReceived.rotX / 180.0 * PI;
00138 lastRotY = lastNavdataReceived.rotY / 180.0 * PI;
00139 lastRotZ = lastNavdataReceived.rotZ / 180.0 * PI;
00140 }
00141 else
00142 {
00143 ROS_DEBUG("Is ardrone_autonomy odometry a stupid Nan ?");
00144 }
00145 }
00146
00147 void PoseEstimator::publish_end_reset_pose()
00148 {
00149 std_msgs::Empty msg;
00150 end_reset_pose_pub.publish(msg);
00151 pending_reset = false;
00152 }
00153
00154 void PoseEstimator::publish_pose()
00155 {
00156 ucl_drone::Pose3D pose_msg;
00157 bool fusion_is_ok = false;
00158 if (this->use_visual_pose)
00159 {
00160 fusion_is_ok = queuePoseFusion(pose_msg);
00161 }
00162 else
00163 {
00164 fusion_is_ok = poseFusion(pose_msg);
00165 }
00166
00167
00168 if (fusion_is_ok)
00169 {
00170 pose_pub.publish(pose_msg);
00171 }
00172 }
00173
00174 bool PoseEstimator::poseCopy(ucl_drone::Pose3D& pose_msg)
00175 {
00176
00177
00178
00179
00180
00181
00182 pose_msg.header.stamp = ros::Time().now();
00183 pose_msg.header.frame_id = lastOdometryReceived.header.frame_id;
00184 pose_msg.x = lastOdometryReceived.pose.pose.position.x;
00185 pose_msg.y = lastOdometryReceived.pose.pose.position.y;
00186 pose_msg.z = lastOdometryReceived.pose.pose.position.z;
00187
00188 pose_msg.rotX = lastNavdataReceived.rotX / 180.0 * PI;
00189 pose_msg.rotY = lastNavdataReceived.rotY / 180.0 * PI;
00190 pose_msg.rotZ = lastNavdataReceived.rotZ / 180.0 * PI;
00191 pose_msg.xvel = lastOdometryReceived.twist.twist.linear.x;
00192 pose_msg.yvel = lastOdometryReceived.twist.twist.linear.y;
00193 pose_msg.zvel = lastOdometryReceived.twist.twist.linear.z;
00194 pose_msg.rotXvel = lastOdometryReceived.twist.twist.angular.x;
00195 pose_msg.rotYvel = lastOdometryReceived.twist.twist.angular.y;
00196 pose_msg.rotZvel = lastOdometryReceived.twist.twist.angular.z;
00197 }
00198
00199 bool PoseEstimator::poseFusion(ucl_drone::Pose3D& pose_msg)
00200 {
00201
00202
00203
00204 ros::Time previous_odom_time = odom_time;
00205 odom_time = lastOdometryReceived.header.stamp;
00206 double delta_t = (odom_time - previous_odom_time).toSec();
00207
00208 if (delta_t == 0)
00209 {
00210 ROS_DEBUG("Is ardrone_autonomy always responding ?");
00211 return false;
00212 }
00213 if (!std::isfinite(delta_t))
00214 {
00215 ROS_DEBUG("Something strange hapenned! delta_t is not finite!");
00216 return false;
00217 }
00218
00219 pose_msg.rotX = lastRotX;
00220 pose_msg.rotY = lastRotY;
00221
00222 odometry_rotZ += lastRotZ - previous_rotZ;
00223
00224 if (odometry_rotZ > M_PI)
00225 odometry_rotZ -= 2 * M_PI;
00226 if (odometry_rotZ < -M_PI)
00227 odometry_rotZ += 2 * M_PI;
00228
00229 pose_msg.rotZ = odometry_rotZ;
00230
00231
00232
00233 double xvel =
00234 (float)((cos(pose_msg.rotZ) * (lastOdometryReceived.twist.twist.linear.x) -
00235 sin(pose_msg.rotZ) * (lastOdometryReceived.twist.twist.linear.y)) *
00236 delta_t);
00237 odometry_x += xvel;
00238
00239 double yvel =
00240 (float)((sin(pose_msg.rotZ) * (lastOdometryReceived.twist.twist.linear.x) +
00241 cos(pose_msg.rotZ) * (lastOdometryReceived.twist.twist.linear.y)) *
00242 delta_t);
00243 odometry_y += yvel;
00244
00245 pose_msg.x = odometry_x;
00246 pose_msg.y = odometry_y;
00247 pose_msg.z = lastOdometryReceived.pose.pose.position.z;
00248
00249 if (lastOdometryReceived.pose.pose.position.z == 0)
00250 pose_msg.z = lastposeVisualReceived.z;
00251
00252 pose_msg.header.stamp = odom_time;
00253
00254 pose_msg.xvel = lastOdometryReceived.twist.twist.linear.x;
00255 pose_msg.yvel = lastOdometryReceived.twist.twist.linear.y;
00256 pose_msg.zvel =
00257 lastOdometryReceived.twist.twist.linear.z;
00258 pose_msg.rotXvel =
00259 lastOdometryReceived.twist.twist.angular.x;
00260 pose_msg.rotYvel =
00261 lastOdometryReceived.twist.twist.angular.y;
00262 pose_msg.rotZvel =
00263 lastOdometryReceived.twist.twist.angular.z;
00264
00265 return true;
00266 }
00267
00268 bool PoseEstimator::queuePoseFusion(ucl_drone::Pose3D& pose_msg)
00269 {
00270
00271
00272 ros::Time previous_odom_time = odom_time;
00273 odom_time = lastOdometryReceived.header.stamp;
00274 double delta_t = (odom_time - previous_odom_time).toSec();
00275
00276 if (delta_t == 0)
00277 {
00278 ROS_DEBUG("Is ardrone_autonomy always responding ?");
00279 return false;
00280 }
00281 if (!std::isfinite(delta_t))
00282 {
00283 ROS_DEBUG("Something strange hapenned! delta_t is not finite!");
00284 return false;
00285 }
00286
00287 if (visual_pose_available)
00288 {
00289 ROS_DEBUG("VISUAL POSE received in pose_estimation");
00290 odometry_x = 0;
00291 odometry_y = 0;
00292 odometry_rotZ = lastposeVisualReceived.rotZ;
00293
00294 this->processQueue(this->queue_dx, this->odometry_x);
00295 this->processQueue(this->queue_dy, this->odometry_y);
00296 this->processQueue(this->queue_drotZ, this->odometry_rotZ);
00297
00298 visual_pose_available = false;
00299 }
00300
00301 pose_msg.rotX = lastRotX;
00302 pose_msg.rotY = lastRotY;
00303
00305 odometry_rotZ += lastRotZ - previous_rotZ;
00306
00308 this->pushQueue(this->queue_drotZ, lastRotZ - previous_rotZ);
00309 pose_msg.rotZ = odometry_rotZ;
00310
00311
00312
00313
00314
00315
00316
00317 if (pose_msg.rotZ > M_PI)
00318 pose_msg.rotZ -= 2 * M_PI;
00319 if (pose_msg.rotZ < -M_PI)
00320 pose_msg.rotZ += 2 * M_PI;
00321
00322
00323
00324 double dx =
00325 (float)((cos(pose_msg.rotZ) * (lastOdometryReceived.twist.twist.linear.x) -
00326 sin(pose_msg.rotZ) * (lastOdometryReceived.twist.twist.linear.y)) *
00327 delta_t);
00328 odometry_x += dx;
00329
00330 this->pushQueue(this->queue_dx, dx);
00331
00332 double dy =
00333 (float)((sin(pose_msg.rotZ) * (lastOdometryReceived.twist.twist.linear.x) +
00334 cos(pose_msg.rotZ) * (lastOdometryReceived.twist.twist.linear.y)) *
00335 delta_t);
00336 odometry_y += dy;
00337
00338 this->pushQueue(this->queue_dy, dy);
00339
00340 pose_msg.x = lastposeVisualReceived.x + odometry_x;
00341 pose_msg.y = lastposeVisualReceived.y + odometry_y;
00342 pose_msg.z = lastOdometryReceived.pose.pose.position.z;
00343
00344 if (lastOdometryReceived.pose.pose.position.z == 0)
00345 pose_msg.z = lastposeVisualReceived.z;
00346
00347 pose_msg.header.stamp = odom_time;
00348
00349 pose_msg.xvel = lastOdometryReceived.twist.twist.linear.x;
00350 pose_msg.yvel = lastOdometryReceived.twist.twist.linear.y;
00351 pose_msg.zvel =
00352 lastOdometryReceived.twist.twist.linear.z;
00353 pose_msg.rotXvel =
00354 lastOdometryReceived.twist.twist.angular.x;
00355 pose_msg.rotYvel =
00356 lastOdometryReceived.twist.twist.angular.y;
00357 pose_msg.rotZvel =
00358 lastOdometryReceived.twist.twist.angular.z;
00359
00360 return true;
00361 }
00362
00363 void PoseEstimator::pushQueue(std::queue< std::vector< double > >& myqueue, double item)
00364 {
00365 std::vector< double > v(2);
00366 v[0] = lastOdometryReceived.header.stamp.toSec();
00367 v[1] = item;
00368 myqueue.push(v);
00369 if (myqueue.size() > 200)
00370 {
00371 myqueue.pop();
00372 }
00373 }
00374
00375 void PoseEstimator::processQueue(std::queue< std::vector< double > >& myqueue, double& result)
00376 {
00377 bool test = true;
00378 while (test && !myqueue.empty())
00379 {
00380 std::vector< double > popped = myqueue.front();
00381 myqueue.pop();
00382 test = popped[0] < lastposeVisualReceived.header.stamp.toSec();
00383 }
00384
00385 while (!myqueue.empty())
00386 {
00387 std::vector< double > popped = myqueue.front();
00388 myqueue.pop();
00389 result += popped[1];
00390 }
00391 }
00392
00393 int main(int argc, char** argv)
00394 {
00395
00396
00397
00398
00399 ROS_INFO_STREAM("pose_estimation started!");
00400
00401 ros::init(argc, argv, "pose_estimation");
00402 PoseEstimator myPose;
00403 ros::Rate r(20);
00404
00405 ROS_DEBUG("pose estimation initialized");
00406 while (!myPose.odometry_publishing && ros::ok())
00407 {
00408 ros::spinOnce();
00409 r.sleep();
00410 }
00411
00412 ROS_DEBUG("ardrone_driver publishing: ending hibernate");
00413 myPose.doFlatTrim();
00414 myPose.doReset();
00415 ROS_DEBUG("reset done");
00416
00417 while (ros::ok())
00418 {
00419 TIC(pose);
00420 myPose.publish_pose();
00421 TOC(pose, "pose");
00422
00423 if (myPose.pending_reset)
00424 {
00425 ros::Time t = ros::Time::now() + ros::Duration(3);
00426 while (ros::Time::now() < t)
00427 {
00428 ros::spinOnce();
00429 myPose.doReset();
00430 }
00431 myPose.publish_end_reset_pose();
00432 }
00433
00434 ros::spinOnce();
00435 r.sleep();
00436 }
00437 return 0;
00438 }