00001 #include "segway_rmp400_odom_fused_alg_node.h"
00002 #include <algorithm>
00003
00004 using namespace Eigen;
00005
00006 SegwayRmp400OdomAlgNode::SegwayRmp400OdomAlgNode(void) :
00007 algorithm_base::IriBaseAlgorithm<SegwayRmp400OdomAlgorithm>(),
00008 r_(0),
00009 p_(0),
00010 th_(0),
00011 dth_(0),
00012 sigma2_dth_(0),
00013 first_segway_status_(true),
00014 first_imu_(true)
00015 {
00016
00017 loop_rate_ = 10;
00018
00019 public_node_handle_.param<std::string>("tf_prefix", tf_prefix_, "");
00020 public_node_handle_.param<std::string>("odom_id", odom_id_, "odom" );
00021 public_node_handle_.param<std::string>("base_link_id", base_link_id_, "base_footprint" );
00022 public_node_handle_.param<bool> ("six_d", six_d_, true );
00023 public_node_handle_.param<bool> ("publish_tf", publish_tf_, true );
00024 public_node_handle_.param<bool> ("publish_odom_rel", publish_odom_rel_, true );
00025 public_node_handle_.param<double> ("sigma_dx_fwd", sigma_dx_fwd_, 0.00425 );
00026 public_node_handle_.param<double> ("sigma_dx_turn", sigma_dx_turn_, 0.00425 );
00027 public_node_handle_.param<double> ("sigma_thimu", sigma_thimu_, 0.00453 );
00028 public_node_handle_.param<double> ("offset_fwd", offset_fwd_, 0.06758 );
00029 public_node_handle_.param<double> ("offset_turn", offset_turn_, 0.06758 );
00030
00031 cov_ = MatrixXf::Zero(3,3);
00032 Q_ = MatrixXf::Zero(3,3);
00033 Jp_ = MatrixXf::Identity(3,3);
00034 Jd_ = MatrixXf::Identity(3,3);
00035
00036
00037 if( tf_prefix_.size()!=0 )
00038 {
00039 odom_id_ = tf_prefix_ + "/" + odom_id_;
00040 base_link_id_ = tf_prefix_ + "/" + base_link_id_;
00041 }
00042
00043
00044 odom_publisher_ = public_node_handle_.advertise<nav_msgs::Odometry>("odom", 100);
00045 odom_rel_publisher_ = public_node_handle_.advertise<nav_msgs::Odometry>("odom_rel", 100);
00046
00047
00048 segway_status_subscriber_ = public_node_handle_.subscribe("segway_status", 100, &SegwayRmp400OdomAlgNode::segway_status_callback, this);
00049 imu_subscriber_ = public_node_handle_.subscribe("imu", 100, &SegwayRmp400OdomAlgNode::imu_callback, this);
00050
00051 }
00052
00053 SegwayRmp400OdomAlgNode::~SegwayRmp400OdomAlgNode(void)
00054 {
00055
00056 }
00057
00058 void SegwayRmp400OdomAlgNode::mainNodeThread(void)
00059 {
00060
00061 if(first_segway_status_)
00062 {
00063 last_time_ = ros::Time::now();
00064 first_segway_status_=false;
00065 }
00066 ros::Time current_time = ros::Time::now();
00067
00068
00069 double dt = (current_time - last_time_).toSec();
00070 last_time_ = current_time;
00071
00072
00073 segway_status_mutex_.enter();
00074 double vT = vT_;
00075 segway_status_mutex_.exit();
00076
00077 imu_mutex_.enter();
00078 double sigma2_dth = sigma2_dth_;
00079 sigma2_dth_ = 0;
00080 double dth = dth_;
00081 dth_ = 0;
00082 double r = r_;
00083 double p = p_;
00084 double vrimu = vrimu_;
00085 double vpimu = vpimu_;
00086 double vthimu = vthimu_;
00087 imu_mutex_.exit();
00088
00089
00090
00091 double dx_local,sigma_dx;
00092 if (fabs(vthimu)>0.05)
00093 {
00094 dx_local = vT*dt*(1+ offset_turn_);
00095 sigma_dx = sigma_dx_turn_;
00096 }else{
00097 dx_local = vT*dt*(1+offset_fwd_);
00098 sigma_dx = sigma_dx_fwd_;
00099 }
00100 double dy_local = 0;
00101
00102 Jp_(0,2) =-sin(th_)*dx_local - cos(th_)*dy_local;
00103 Jp_(1,2) = cos(th_)*dx_local - sin(th_)*dy_local;
00104
00105 Jd_(0,0) = cos(th_);
00106 Jd_(0,1) =-sin(th_);
00107 Jd_(1,0) = sin(th_);
00108 Jd_(1,1) = cos(th_);
00109
00110 Q_(0,0) = sigma_dx*sigma_dx;
00111 Q_(1,1) = 1e-10;
00112 Q_(2,2) = sigma2_dth;
00113
00114 cov_ = Jp_ * cov_ * Jp_.transpose() + Jd_ * Q_ * Jd_.transpose();
00115
00116 Eigen::Matrix3f cov_rel = Q_;
00117
00118
00119
00120
00121 double dx = six_d_ ? dx_local*cos(th_)*cos(p) : dx_local*cos(th_)-dy_local*sin(th_);
00122 double dy = six_d_ ? dx_local*sin(th_)*cos(r) : dx_local*sin(th_)+dy_local*cos(th_);
00123 double dz = six_d_ ? dx_local*cos(r)*sin(p) : 0.0;
00124
00125 th_ += dth;
00126
00127
00128 geometry_msgs::TransformStamped odom_trans_msg;
00129 Odometry_msg_.header.stamp = odom_trans_msg.header.stamp = current_time;
00130 Odometry_msg_.header.frame_id = odom_trans_msg.header.frame_id = odom_id_;
00131 Odometry_msg_.child_frame_id = odom_trans_msg.child_frame_id = base_link_id_;
00132
00133 odom_trans_msg.transform.translation.x = Odometry_msg_.pose.pose.position.x += dx;
00134 odom_trans_msg.transform.translation.y = Odometry_msg_.pose.pose.position.y += dy;
00135 odom_trans_msg.transform.translation.z = Odometry_msg_.pose.pose.position.z += dz;
00136
00137 geometry_msgs::Quaternion rot,rot_rel;
00138 if(six_d_) rot = tf::createQuaternionMsgFromRollPitchYaw(r,-p,th_);
00139 else rot = tf::createQuaternionMsgFromYaw (th_);
00140 odom_trans_msg.transform.rotation = Odometry_msg_.pose.pose.orientation = rot;
00141
00142 Odometry_msg_.pose.covariance[0] = cov_(0,0);
00143 Odometry_msg_.pose.covariance[1] = cov_(0,1);
00144 Odometry_msg_.pose.covariance[5] = cov_(0,2);
00145 Odometry_msg_.pose.covariance[6] = cov_(1,0);
00146 Odometry_msg_.pose.covariance[7] = cov_(1,1);
00147 Odometry_msg_.pose.covariance[11] = cov_(1,2);
00148 Odometry_msg_.pose.covariance[30] = cov_(2,0);
00149 Odometry_msg_.pose.covariance[31] = cov_(2,1);
00150 Odometry_msg_.pose.covariance[35] = cov_(2,2);
00151
00152 Odometry_msg_.twist.twist.linear.x = vT;
00153 Odometry_msg_.twist.twist.linear.y = 0.0;
00154 Odometry_msg_.twist.twist.linear.z = 0.0;
00155 Odometry_msg_.twist.twist.angular.x = vrimu;
00156 Odometry_msg_.twist.twist.angular.y = vpimu;
00157 Odometry_msg_.twist.twist.angular.z = vthimu;
00158
00159 Odometry_msg_.twist.covariance[0] = sigma_dx*sigma_dx;
00160 Odometry_msg_.twist.covariance[35] = sigma2_dth_/(dt*dt);
00161
00162
00163 Odometry_rel_msg_ = Odometry_msg_;
00164 Odometry_rel_msg_.pose.pose.position.x = dx_local;
00165 Odometry_rel_msg_.pose.pose.position.y = dy_local;
00166
00167
00168
00169 rot_rel = tf::createQuaternionMsgFromYaw (dth);
00170 Odometry_rel_msg_.pose.pose.orientation = rot_rel;
00171 Odometry_rel_msg_.pose.covariance[0] = cov_rel(0,0);
00172 Odometry_rel_msg_.pose.covariance[1] = cov_rel(0,1);
00173 Odometry_rel_msg_.pose.covariance[5] = cov_rel(0,2);
00174 Odometry_rel_msg_.pose.covariance[6] = cov_rel(1,0);
00175 Odometry_rel_msg_.pose.covariance[7] = cov_rel(1,1);
00176 Odometry_rel_msg_.pose.covariance[11] = cov_rel(1,2);
00177 Odometry_rel_msg_.pose.covariance[30] = cov_rel(2,0);
00178 Odometry_rel_msg_.pose.covariance[31] = cov_rel(2,1);
00179 Odometry_rel_msg_.pose.covariance[35] = cov_rel(2,2);
00180
00181
00182 odom_publisher_.publish(Odometry_msg_);
00183 if(publish_odom_rel_)
00184 odom_rel_publisher_.publish(Odometry_rel_msg_);
00185 if(publish_tf_)
00186 odom_broadcaster_.sendTransform(odom_trans_msg);
00187 }
00188
00189 void SegwayRmp400OdomAlgNode::segway_status_callback(const iri_segway_rmp_msgs::SegwayRMP400Status::ConstPtr& msg)
00190 {
00191
00192 segway_status_mutex_.enter();
00193 vT_ = (msg->rmp200[0].left_wheel_velocity + msg->rmp200[0].right_wheel_velocity +
00194 msg->rmp200[1].left_wheel_velocity + msg->rmp200[1].right_wheel_velocity)/4;
00195 segway_status_mutex_.exit();
00196 }
00197
00198 void SegwayRmp400OdomAlgNode::imu_callback(const sensor_msgs::Imu::ConstPtr& msg)
00199 {
00200
00201
00202 imu_mutex_.enter();
00203
00204 if(first_imu_)
00205 {
00206 last_time_imu_ = msg->header.stamp;
00207 first_imu_ = false;
00208 }
00209
00210
00211 ros::Time current_time_imu = msg->header.stamp;
00212
00213 vrimu_ = msg->angular_velocity.x;
00214 vpimu_ = msg->angular_velocity.y;
00215 vthimu_ = -msg->angular_velocity.z;
00216
00217
00218 tf::Quaternion q;
00219 tf::quaternionMsgToTF(msg->orientation,q);
00220 tf::Matrix3x3(q).getRPY(rimu_, pimu_, thimu_);
00221
00222
00223 rimu_ = rimu_<0 ? rimu_+M_PI : rimu_-M_PI;
00224
00225 r_ = rimu_;
00226 p_ = -pimu_;
00227
00228 double dt_imu = (current_time_imu - last_time_imu_).toSec();
00229 last_time_imu_ = current_time_imu;
00230
00231
00232 dth_ += vthimu_ * dt_imu;
00233
00234 sigma2_dth_ += sigma_thimu_ * sigma_thimu_;
00235
00236
00237
00238
00239 imu_mutex_.exit();
00240 }
00241
00242
00243
00244
00245
00246
00247
00248 void SegwayRmp400OdomAlgNode::node_config_update(Config &config, uint32_t level)
00249 {
00250 alg_.lock();
00251
00252 alg_.unlock();
00253 }
00254
00255 void SegwayRmp400OdomAlgNode::addNodeDiagnostics(void)
00256 {
00257 }
00258
00259
00260 int main(int argc,char *argv[])
00261 {
00262 return algorithm_base::main<SegwayRmp400OdomAlgNode>(argc, argv, "segway_rmp400_odom_alg_node");
00263 }