jockey.cpp
Go to the documentation of this file.
00001 #include <lj_laser_heading/jockey.h>
00002 
00003 namespace lj_laser_heading
00004 {
00005 
00006 // Maximum time interval between reception of LaserScan and heading (either as
00007 // Pose or Odoometry), whichever comes first. The jockey will reject all data
00008 // until one LaserScan message and one Pose/Odometry message come shortly one
00009 // after another.
00010 // TODO: write as a parameter.
00011 const ros::Duration Jockey::max_data_time_delta_ = ros::Duration(0.050);
00012 
00013 Jockey::Jockey(std::string name, const double frontier_width, const double max_frontier_angle) :
00014   lj_laser::Jockey(name, frontier_width, max_frontier_angle),
00015   heading_reception_time_(ros::Time(0))
00016 {
00017 }
00018 
00019 /* Start the subscribers, wait for a LaserScan and a Pose, and exit upon reception.
00020  */
00021 void Jockey::getData()
00022 {
00023   data_received_ = false;
00024   laserHandler_ = nh_.subscribe<sensor_msgs::LaserScan>("base_scan", 1, &Jockey::handleLaser, this);
00025   poseHandler_ = nh_.subscribe<geometry_msgs::Pose>("pose", 1, &Jockey::handlePose, this);
00026   odomHandler_ = nh_.subscribe<nav_msgs::Odometry>("odom", 1, &Jockey::handleOdom, this);
00027 
00028   ros::Rate r(100);
00029   while (ros::ok())
00030   {
00031     if (data_received_)
00032     {
00033       // Stop the subscribers (may be superfluous).
00034       laserHandler_.shutdown();
00035       poseHandler_.shutdown();
00036       odomHandler_.shutdown();
00037       data_received_ = false;
00038       break;
00039     }
00040     ros::spinOnce();
00041     r.sleep();
00042   }
00043   rotateScan();
00044 }
00045 
00046 /* Change angle_min and angle_max of scan_, so that they represent absolute angles.
00047  *
00048  * This as for consequence that angle_min or angle_max can be outside of ]-pi,pi].
00049  */
00050 void Jockey::rotateScan()
00051 {
00052   scan_.angle_min -= heading_;
00053   scan_.angle_max -= heading_;
00054 }
00055 
00056 /* Receive a LaserScan message and store it.
00057  */
00058 void Jockey::handleLaser(const sensor_msgs::LaserScanConstPtr& msg)
00059 {
00060   ROS_DEBUG("%s: laser arrived with %zu beams", jockey_name_.c_str(), msg->ranges.size());
00061 
00062   scan_ = *msg;
00063   scan_reception_time_ = msg->header.stamp;
00064   data_received_ = (scan_reception_time_ - heading_reception_time_) < max_data_time_delta_;
00065 }
00066 
00067 /* Return the angle from a quaternion representing a rotation around the z-axis
00068  *
00069  * The quaternion in ROS is q = (w, x, y, z), so that
00070  * q = (cos(a/2), ux * sin(a/2), uy * sin(a/2), uz * sin(a/2)),
00071  *   where a is the rotation angle and (ux, uy, uz) is the unit vector of the
00072  *   rotation axis.
00073  * For a rotation around z, we have q = (cos(a/2), 0, 0, sin(a/2)). Thus
00074  * a = 2 * atan2(z, w).
00075  */
00076 double angleFromQuaternion(const geometry_msgs::Quaternion& q)
00077 {
00078   if (std::fabs(q.x) > 1e-5 || std::fabs(q.y) > 1e-5)
00079   {
00080     ROS_WARN("Laser frame rotation is not around the z-axis, just pretending it is");
00081   }
00082   return 2 * std::atan2(q.z, q.w);
00083 }
00084 
00085 /* Receive a Pose message and store the heading information.
00086  */
00087 void Jockey::handlePose(const geometry_msgs::PoseConstPtr& msg)
00088 {
00089   ROS_DEBUG("%s: pose arrived", jockey_name_.c_str());
00090 
00091   heading_ = angleFromQuaternion(msg->orientation);
00092   heading_reception_time_ = ros::Time::now();
00093   data_received_ = (heading_reception_time_ - scan_reception_time_) < max_data_time_delta_;
00094 }
00095 
00096 /* Receive a Odometry message and store the heading information.
00097  */
00098 void Jockey::handleOdom(const nav_msgs::OdometryConstPtr& msg)
00099 {
00100   ROS_DEBUG("%s: odom arrived", jockey_name_.c_str());
00101 
00102   // TODO: make writing heading_ and heading_reception_time_ thread safe.
00103   heading_ = angleFromQuaternion(msg->pose.pose.orientation);
00104   heading_reception_time_ = msg->header.stamp;
00105   data_received_ = (heading_reception_time_ - scan_reception_time_) < max_data_time_delta_;
00106 }
00107 
00108 } // namespace lj_laser_heading


lj_laser_heading
Author(s): Gaƫl Ecorchard
autogenerated on Thu Jun 6 2019 17:50:49