00001 #include "kinton_odom_alg_node.h"
00002
00003 KintonOdomAlgNode::KintonOdomAlgNode(void) :
00004 algorithm_base::IriBaseAlgorithm<KintonOdomAlgorithm>()
00005 {
00006
00007 this->loop_rate_ = 100;
00008
00009 this->public_node_handle_.param<std::string>("tf_prefix", this->tf_prefix_, "");
00010 this->public_node_handle_.param<std::string>("odom_id", this->odom_id_, "odom" );
00011 this->public_node_handle_.param<std::string>("base_link_id", this->base_link_id_, "base_link" );
00012 this->public_node_handle_.param<bool> ("publish_tf", this->publish_tf_, true );
00013
00014
00015 if( this->tf_prefix_.size()!=0 )
00016 {
00017 this->odom_id_ = this->tf_prefix_ + "/" + this->odom_id_;
00018 this->base_link_id_ = this->tf_prefix_ + "/" + this->base_link_id_;
00019 }
00020
00021 ini_zeros();
00022
00023
00024 sleep(1.0);
00025
00026
00027 tf::TransformListener listener1,listener2,listener3;
00028 tf::StampedTransform tf_accelerometers,tf_gyros,tf_compass;
00029
00030 try {
00031 listener1.waitForTransform("/base_link","/accelerometers", ros::Time::now(), ros::Duration(1.0));
00032 listener1.lookupTransform("/base_link","/accelerometers", ros::Time::now(), tf_accelerometers);
00033 }
00034 catch (tf::TransformException ex1) {
00035 ROS_ERROR("Accelerometers Transform error: %s",ex1.what());
00036 }
00037
00038 try {
00039 listener2.waitForTransform("/base_link","/gyros", ros::Time::now(), ros::Duration(1.0));
00040 listener2.lookupTransform("/base_link","/gyros", ros::Time::now(), tf_gyros);
00041 }
00042 catch (tf::TransformException ex2) {
00043 ROS_ERROR("Gyros Transform error: %s",ex2.what());
00044 }
00045
00046 try {
00047 listener3.waitForTransform("/base_link","/compass", ros::Time::now(), ros::Duration(1.0));
00048 listener3.lookupTransform("/base_link","/compass", ros::Time::now(), tf_compass);
00049 }
00050 catch (tf::TransformException ex3) {
00051 ROS_ERROR("Compass Transform error: %s",ex3.what());
00052 }
00053
00054
00055
00056 this->T_acc_ = getTransform(tf_accelerometers);
00057 this->T_gyr_ = getTransform(tf_gyros);
00058 this->T_comp_ = getTransform(tf_compass);
00059
00060
00061 this->odom_publisher_ = this->public_node_handle_.advertise<nav_msgs::Odometry>("odom", 100);
00062
00063
00064 this->imu_subscriber_ = this->public_node_handle_.subscribe("imu", 100, &KintonOdomAlgNode::imu_callback, this);
00065 this->height_point_subscriber_ = this->public_node_handle_.subscribe("height_point", 100, &KintonOdomAlgNode::height_point_callback, this);
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 }
00076
00077 KintonOdomAlgNode::~KintonOdomAlgNode(void)
00078 {
00079
00080 }
00081
00082 void KintonOdomAlgNode::mainNodeThread(void)
00083 {
00084 geometry_msgs::TransformStamped odom_trans_msg;
00085
00086
00087 double dt = (this->current_time_ - this->last_time_).toSec();
00088 if (dt > 10) dt = 0.01;
00089
00090
00091
00092 this->last_time_ = this->current_time_;
00093
00094
00095
00096 Eigen::MatrixXd pos_ang_imu(3,1), vel_ang_imu(3,1), acc_lin_imu(3,1);
00097 this->imu_mutex_.enter();
00098 pos_ang_imu = this->pos_ang_imu_;
00099 vel_ang_imu = this->vel_ang_imu_;
00100 acc_lin_imu = this->acc_lin_imu_;
00101 this->imu_mutex_.exit();
00102
00103 double height;
00104 this->height_point_mutex_.enter();
00105 height = this->height_;
00106 this->height_point_mutex_.exit();
00107
00108
00109 this->pos_ang_odom_ += vel_ang_imu * dt;
00110 geometry_msgs::Quaternion rot;
00111 rot = tf::createQuaternionMsgFromRollPitchYaw(this->pos_ang_odom_(0,0),this->pos_ang_odom_(1,0),this->pos_ang_odom_(2,0));
00112
00113 Eigen::Matrix3d R_mov;
00114 R_mov = Eigen::AngleAxisd(this->pos_ang_odom_(0,0), Eigen::Vector3d::UnitX()) \
00115 * Eigen::AngleAxisd(this->pos_ang_odom_(1,0), Eigen::Vector3d::UnitY()) \
00116 * Eigen::AngleAxisd(this->pos_ang_odom_(2,0), Eigen::Vector3d::UnitZ());
00117
00118
00119 Eigen::MatrixXd vel_lin_imu(3,1);
00120 vel_lin_imu = acc_lin_imu * dt;
00121
00122 this->vel_lin_odom_ += R_mov * vel_lin_imu;
00123
00124
00125 this->pos_lin_odom_ += this->vel_lin_odom_ * dt;
00126
00127
00128
00129
00130
00131 this->transform_.translation.x = this->pos_lin_odom_(0,0);
00132 this->transform_.translation.y = this->pos_lin_odom_(1,0);
00133
00134 this->transform_.translation.z = height;
00135 this->transform_.rotation = rot;
00136
00137
00138 this->pose_.pose.position.x = this->pos_lin_odom_(0,0);
00139 this->pose_.pose.position.y = this->pos_lin_odom_(1,0);
00140
00141 this->pose_.pose.position.z = height;
00142 this->pose_.pose.orientation = rot;
00143 this->pose_.covariance[0] =
00144 this->pose_.covariance[7] =
00145 this->pose_.covariance[14] =
00146 this->pose_.covariance[21] =
00147 this->pose_.covariance[28] =
00148 this->pose_.covariance[35] = 0.5;
00149
00150
00151 this->twist_.twist.linear.x = vel_lin_imu(0,0);
00152 this->twist_.twist.linear.y = vel_lin_imu(1,0);
00153 this->twist_.twist.linear.z = vel_lin_imu(2,0);
00154 this->twist_.twist.angular.x = vel_ang_imu(0,0);
00155 this->twist_.twist.angular.y = vel_ang_imu(1,0);
00156 this->twist_.twist.angular.z = vel_ang_imu(2,0);
00157
00158 this->twist_.covariance[0] =
00159 this->twist_.covariance[7] =
00160 this->twist_.covariance[14] =
00161 this->twist_.covariance[21] =
00162 this->twist_.covariance[28] =
00163 this->twist_.covariance[35] = 0.01;
00164
00165
00166 if(this->publish_tf_)
00167 {
00168
00169 odom_trans_msg.header.stamp = this->current_time_;
00170 odom_trans_msg.header.frame_id = this->odom_id_;
00171 odom_trans_msg.child_frame_id = this->base_link_id_;
00172 odom_trans_msg.transform = this->transform_;
00173
00174 this->odom_broadcaster_.sendTransform(odom_trans_msg);
00175 }
00176
00177
00178 this->Odometry_msg_.header.stamp = this->current_time_;
00179 this->Odometry_msg_.header.frame_id = this->odom_id_;
00180 this->Odometry_msg_.child_frame_id = this->base_link_id_;
00181 this->Odometry_msg_.pose = this->pose_;
00182 this->Odometry_msg_.twist = this->twist_;
00183
00184
00185
00186
00187
00188
00189
00190
00191 this->odom_publisher_.publish(this->Odometry_msg_);
00192 }
00193
00194
00195
00196 void KintonOdomAlgNode::imu_callback(const sensor_msgs::Imu::ConstPtr& msg)
00197 {
00198
00199
00200
00201
00202
00203
00204
00205
00206 this->imu_mutex_.enter();
00207
00208
00209 this->current_time_ = msg->header.stamp;
00210
00211 Eigen::MatrixXd pos_ang_imu(4,1), acc_lin_imu(4,1), vel_ang_imu(4,1);
00212
00213
00214
00215 acc_lin_imu(0,0) = msg->linear_acceleration.x;
00216 acc_lin_imu(1,0) = msg->linear_acceleration.y;
00217 acc_lin_imu(2,0) = msg->linear_acceleration.z;
00218 acc_lin_imu(3,0) = 1.0;
00219
00220
00221 vel_ang_imu(0,0) = msg->angular_velocity.x;
00222 vel_ang_imu(1,0) = msg->angular_velocity.y;
00223 vel_ang_imu(2,0) = msg->angular_velocity.z;
00224 vel_ang_imu(3,0) = 1.0;
00225
00226
00227 tf::Quaternion q;
00228 tf::quaternionMsgToTF(msg->orientation,q);
00229 tf::Matrix3x3(q).getRPY(pos_ang_imu(0,0), pos_ang_imu(1,0), pos_ang_imu(2,0));
00230 pos_ang_imu(3,0) = 1.0;
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 this->Rquad_ = Eigen::AngleAxisd(pos_ang_imu(0,0), Eigen::Vector3d::UnitX()) \
00242 * Eigen::AngleAxisd(pos_ang_imu(1,0), Eigen::Vector3d::UnitY()) \
00243 * Eigen::AngleAxisd(pos_ang_imu(2,0), Eigen::Vector3d::UnitZ());
00244
00245
00246 Eigen::MatrixXd g(3,1), new_g(3,1);
00247 g(0) = 0;
00248 g(1) = 0;
00249 g(2) = 9.8;
00250 new_g = this->Rquad_ * g;
00251
00252
00253 acc_lin_imu(0,0) = (acc_lin_imu(0,0) - new_g(0,0));
00254 acc_lin_imu(1,0) = (acc_lin_imu(1,0) - new_g(1,0));
00255 acc_lin_imu(2,0) = (acc_lin_imu(2,0) - new_g(2,0));
00256 acc_lin_imu(3,0) = 1.0;
00257
00259
00260 acc_lin_imu = Eigen::MatrixXd::Zero(3,1);
00261
00262 pos_ang_imu = Eigen::MatrixXd::Zero(3,1);
00264
00265 this->acc_lin_imu_ = acc_lin_imu.block(0,0,3,1);
00266 this->vel_ang_imu_ = vel_ang_imu.block(0,0,3,1);
00267 this->pos_ang_imu_ = pos_ang_imu.block(0,0,3,1);
00268
00269
00270
00271
00272
00273
00274
00275
00276 this->imu_mutex_.exit();
00277 }
00278
00279 void KintonOdomAlgNode::height_point_callback(const geometry_msgs::PointStamped::ConstPtr& msg)
00280 {
00281
00282
00283
00284
00285 this->height_point_mutex_.enter();
00286
00287 this->height_ = msg->point.z;
00288
00289 if (this->init_) {
00290 this->height_init_ = this->height_;
00291 this->init_ = false;
00292 }
00293 this->height_ = this->height_ - this->height_init_;
00294
00295
00296
00297
00298 this->height_point_mutex_.exit();
00299 }
00300
00301
00302
00303
00304
00305
00306 void KintonOdomAlgNode::ini_zeros()
00307 {
00308 ROS_DEBUG("Initialization to Zeros");
00309
00310 this->last_time_ = ros::Time::now();
00311 usleep(10);
00312 this->current_time_ = ros::Time::now();
00313
00314
00315 this->pos_ang_imu_ = Eigen::MatrixXd::Zero(3,1);
00316 this->vel_ang_imu_ = Eigen::MatrixXd::Zero(3,1);
00317 this->acc_lin_imu_ = Eigen::MatrixXd::Zero(3,1);
00318
00319
00320 this->vel_lin_odom_ = Eigen::MatrixXd::Zero(3,1);
00321
00322
00323 this->pos_ang_odom_ = Eigen::MatrixXd::Zero(3,1);
00324
00325
00326 this->pos_lin_odom_ = Eigen::MatrixXd::Zero(3,1);
00327
00328
00329 this->height_init_ = 0.0;
00330
00331
00332 this->init_ = true;
00333 }
00334
00335 Eigen::Matrix4d KintonOdomAlgNode::getTransform(const tf::StampedTransform& transform)
00336 {
00337
00338 double roll,pitch,yaw;
00339 tf::Quaternion q = transform.getRotation();
00340 tf::Matrix3x3(q).getRPY(roll,pitch,yaw);
00341
00342 Eigen::Matrix3d Rot;
00343 Rot = Eigen::AngleAxisd(yaw, Eigen::Vector3d::UnitZ()) \
00344 * Eigen::AngleAxisd(pitch, Eigen::Vector3d::UnitY()) \
00345 * Eigen::AngleAxisd(roll, Eigen::Vector3d::UnitX());
00346 Eigen::Matrix4d T = Eigen::Matrix4d::Zero();
00347
00348 T.block(0,0,3,3) = Rot;
00349 T(0,3) = transform.getOrigin().x();
00350 T(1,3) = transform.getOrigin().y();
00351 T(2,3) = transform.getOrigin().z();
00352 T(3,3) = 1.0;
00353
00354
00355
00356 return T;
00357 }
00358
00359 void KintonOdomAlgNode::node_config_update(Config &config, uint32_t level)
00360 {
00361 this->alg_.lock();
00362
00363 this->alg_.unlock();
00364 }
00365
00366 void KintonOdomAlgNode::addNodeDiagnostics(void)
00367 {
00368 }
00369
00370
00371 int main(int argc,char *argv[])
00372 {
00373 return algorithm_base::main<KintonOdomAlgNode>(argc, argv, "kinton_odom_alg_node");
00374 }