odometer_base.h
Go to the documentation of this file.
00001 
00002 #ifndef ODOMETER_BASE_H_
00003 #define ODOMETER_BASE_H_
00004 
00005 #include <ros/ros.h>
00006 #include <nav_msgs/Odometry.h>
00007 #include <std_srvs/Empty.h>
00008 
00009 #include <tf/transform_listener.h>
00010 #include <tf/transform_broadcaster.h>
00011 
00012 namespace viso2_ros
00013 {
00014 
00020     class OdometerBase
00021     {
00022         private:
00023             // publisher
00024             ros::Publisher odom_pub_;
00025             ros::Publisher pose_pub_;
00026 
00027             ros::ServiceServer reset_service_;
00028 
00029             // tf related
00030             std::string sensor_frame_id_;
00031             std::string odom_frame_id_;
00032             std::string base_link_frame_id_;
00033             tf::TransformListener tf_listener_;
00034             tf::TransformBroadcaster tf_broadcaster_;
00035             bool publish_tf_;
00036 
00037             // the current integrated camera pose
00038             tf::Transform integrated_pose_;
00039             // timestamp of the last update
00040             ros::Time last_update_time_;
00041 
00042             // covariances
00043             boost::array<double, 36> pose_covariance_;
00044             boost::array<double, 36> twist_covariance_;
00045 
00046         public:
00047             OdometerBase()
00048             {
00049                 // Read local parameters
00050                 ros::NodeHandle local_nh("~");
00051 
00052                 local_nh.param("odom_frame_id", odom_frame_id_, std::string("/odom"));
00053                 local_nh.param("base_link_frame_id", base_link_frame_id_, std::string("/multisense/head"));
00054                 local_nh.param("sensor_frame_id", sensor_frame_id_, std::string("/multisense/left_camera_optical_frame"));
00055                 local_nh.param("publish_tf", publish_tf_, true);
00056 
00057                 ROS_INFO_STREAM("Basic Odometer Settings:" << std::endl <<
00058                         "  odom_frame_id      = " << odom_frame_id_ << std::endl <<
00059                         "  base_link_frame_id = " << base_link_frame_id_ << std::endl <<
00060                         "  publish_tf         = " << (publish_tf_?"true":"false"));
00061 
00062                 // advertise
00063                 odom_pub_ = local_nh.advertise<nav_msgs::Odometry>("odometry", 1);
00064                 pose_pub_ = local_nh.advertise<geometry_msgs::PoseStamped>("pose", 1);
00065 
00066                 reset_service_ = local_nh.advertiseService("reset_pose", &OdometerBase::resetPose, this);
00067 
00068                 integrated_pose_.setIdentity();
00069 
00070                 pose_covariance_.assign(0.0);
00071                 twist_covariance_.assign(0.0);
00072             }
00073 
00074         protected:
00075 
00076             void setSensorFrameId(const std::string& frame_id)
00077             {
00078                 sensor_frame_id_ = frame_id;
00079             }
00080 
00081             std::string getSensorFrameId() const
00082             {
00083                 return sensor_frame_id_;
00084             }
00085 
00086             void setPoseCovariance(const boost::array<double, 36>& pose_covariance)
00087             {
00088                 pose_covariance_ = pose_covariance;
00089             }
00090 
00091             void setTwistCovariance(const boost::array<double, 36>& twist_covariance)
00092             {
00093                 twist_covariance_ = twist_covariance;
00094             }
00095 
00096             void integrateAndPublish(const tf::Transform& delta_transform, const ros::Time& timestamp)
00097             {
00098                 if (sensor_frame_id_.empty())
00099                 {
00100                     ROS_ERROR("[odometer] update called with unknown sensor frame id!");
00101                     return;
00102                 }
00103                 if (timestamp < last_update_time_)
00104                 {
00105                     ROS_WARN("[odometer] saw negative time change in incoming sensor data, resetting pose.");
00106                     integrated_pose_.setIdentity();
00107                     tf_listener_.clear();
00108                 }
00109                 integrated_pose_ *= delta_transform;
00110 
00111                 // transform integrated pose to base frame
00112                 tf::StampedTransform base_to_sensor;
00113                 std::string error_msg;
00114                 if (tf_listener_.canTransform(base_link_frame_id_, sensor_frame_id_, timestamp, &error_msg))
00115                 {
00116                     tf_listener_.lookupTransform(
00117                             base_link_frame_id_,
00118                             sensor_frame_id_,
00119                             timestamp, base_to_sensor);
00120                 }
00121                 else
00122                 {
00123                     ROS_WARN_THROTTLE(10.0, "The tf from '%s' to '%s' does not seem to be available, "
00124                             "will assume it as identity!",
00125                             base_link_frame_id_.c_str(),
00126                             sensor_frame_id_.c_str());
00127                     ROS_DEBUG("Transform error: %s", error_msg.c_str());
00128                     base_to_sensor.setIdentity();
00129                 }
00130 
00131                 tf::Transform base_transform = base_to_sensor * integrated_pose_ * base_to_sensor.inverse();
00132                 /*
00133                  *tf::Quaternion q;
00134                  *double rx,ry,rz;
00135                  *base_transform.getBasis().getEulerYPR(rz,ry,rx);
00136                  *std::cout<<rx<<" "<<ry<<" "<<rz<<std::endl;
00137                  *q.setEuler(rz,ry,rx);
00138                  *q.normalize();
00139                  *base_transform.setRotation(q);
00140                  */
00141 
00142                 nav_msgs::Odometry odometry_msg;
00143                 odometry_msg.header.stamp = timestamp;
00144                 odometry_msg.header.frame_id = odom_frame_id_;
00145                 odometry_msg.child_frame_id = base_link_frame_id_;
00146                 tf::poseTFToMsg(base_transform, odometry_msg.pose.pose);
00147 
00148                 // calculate twist (not possible for first run as no delta_t can be computed)
00149                 tf::Transform delta_base_transform = base_to_sensor * delta_transform * base_to_sensor.inverse();
00150                 if (!last_update_time_.isZero())
00151                 {
00152                     double delta_t = (timestamp - last_update_time_).toSec();
00153                     if (delta_t)
00154                     {
00155                         odometry_msg.twist.twist.linear.x = delta_base_transform.getOrigin().getX() / delta_t;
00156                         odometry_msg.twist.twist.linear.y = delta_base_transform.getOrigin().getY() / delta_t;
00157                         odometry_msg.twist.twist.linear.z = delta_base_transform.getOrigin().getZ() / delta_t;
00158                         tf::Quaternion delta_rot = delta_base_transform.getRotation();
00159                         tfScalar angle = delta_rot.getAngle();
00160                         tf::Vector3 axis = delta_rot.getAxis();
00161                         tf::Vector3 angular_twist = axis * angle / delta_t;
00162                         odometry_msg.twist.twist.angular.x = angular_twist.x();
00163                         odometry_msg.twist.twist.angular.y = angular_twist.y();
00164                         odometry_msg.twist.twist.angular.z = angular_twist.z();
00165                     }
00166                 }
00167                 //std::cout<<"odometry_msg.pose.pose="<<odometry_msg.pose.pose<<std::endl;
00168                 //std::cout<<"base_transform= "<<base_transform.getOrigin().getX()<<"\t"<<base_transform.getOrigin().getY()<<"\t"<<base_transform.getOrigin().getZ()<<std::endl;
00169                 odometry_msg.pose.covariance = pose_covariance_;
00170                 odometry_msg.twist.covariance = twist_covariance_;
00171                 odom_pub_.publish(odometry_msg);
00172 
00173                 geometry_msgs::PoseStamped pose_msg;
00174                 pose_msg.header.stamp = odometry_msg.header.stamp;
00175                 pose_msg.header.frame_id = odometry_msg.header.frame_id;
00176                 pose_msg.pose = odometry_msg.pose.pose;
00177 
00178                 pose_pub_.publish(pose_msg);
00179 
00180                 if (publish_tf_)
00181                 {
00182                     tf_broadcaster_.sendTransform(
00183                             tf::StampedTransform(base_transform, timestamp,
00184                                 odom_frame_id_, base_link_frame_id_));
00185                 }
00186 
00187                 last_update_time_ = timestamp;
00188             }
00189 
00190 
00191             bool resetPose(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
00192             {
00193                 integrated_pose_.setIdentity();
00194                 return true;
00195             }
00196 
00197     };
00198 
00199 } // end of namespace
00200 
00201 #endif
00202 


dlut_viso2_ros
Author(s): Zhuang Yan , Yan Fei, Wu Nai Liang
autogenerated on Thu Jun 6 2019 20:03:36