00001
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include "amigo_gazebo/pub_odometry.h"
00049 #include "pluginlib/class_list_macros.h"
00050
00052 PLUGINLIB_REGISTER_CLASS(BaseOdometryPlugin,
00053 controller::BaseOdometry,
00054 pr2_controller_interface::Controller)
00055
00056 #define WHEELRAD 0.06
00057 #define DIS2CENT 0.28991378
00058 #define HALFSQRT2 0.7071
00059
00060 using namespace controller;
00061
00062
00063
00064 bool BaseOdometry::init(pr2_mechanism_model::RobotState *robot, ros::NodeHandle &n) {
00065
00066
00067 std::string prefix_param;
00068 n.searchParam("tf_prefix", prefix_param);
00069 n.getParam(prefix_param, tf_prefix_);
00070
00071 n.param("odom/initial_x", odometry_.x, 0.0);
00072 n.param("odom/initial_y", odometry_.y, 0.0);
00073 n.param("odom/initial_yaw", odometry_.z, 0.0);
00074 n.param<std::string> ("odom_frame", odometry_frame_, "odom");
00075 n.param<std::string> ("base_link_frame", base_link_frame_, "base_link");
00076 n.param<std::string> ("base_footprint_frame", base_footprint_frame_, "base_link");
00077
00078 n.param("odom_publish_rate", odometry_publish_rate_, 200.0);
00079 n.param("publish_tf", publish_tf_, true);
00080
00081 n.param<double> ("x_stddev", sigma_x_, 0.002);
00082 n.param<double> ("y_stddev", sigma_y_, 0.002);
00083 n.param<double> ("rotation_stddev", sigma_theta_, 0.017);
00084 n.param<double> ("cov_xy", cov_x_y_, 0.0);
00085 n.param<double> ("cov_xrotation", cov_x_theta_, 0.0);
00086 n.param<double> ("cov_yrotation", cov_y_theta_, 0.0);
00087
00088 std::string wheel_inner_left_front, wheel_inner_right_front, wheel_inner_left_rear, wheel_inner_right_rear;
00089
00090
00091 if (!n.getParam("wheel_inner_left_front", wheel_inner_left_front)){
00092 ROS_ERROR("No joint given in namespace: '%s')",
00093 n.getNamespace().c_str());
00094 return false;
00095 }
00096
00097 wheel_inner_left_front_state = robot->getJointState(wheel_inner_left_front);
00098 if (!wheel_inner_left_front_state ){
00099 ROS_ERROR("BaseOdometry could not find joint named '%s'",
00100 wheel_inner_left_front.c_str());
00101 return false;
00102 }
00103
00104
00105 if (!n.getParam("wheel_inner_right_front", wheel_inner_right_front)){
00106 ROS_ERROR("No joint given in namespace: '%s')",
00107 n.getNamespace().c_str());
00108 return false;
00109 }
00110
00111 wheel_inner_right_front_state = robot->getJointState(wheel_inner_right_front);
00112 if (!wheel_inner_right_front_state ){
00113 ROS_ERROR("BaseOdometry could not find joint named '%s'",
00114 wheel_inner_right_front.c_str());
00115 return false;
00116 }
00117
00118
00119 if (!n.getParam("wheel_inner_left_rear", wheel_inner_left_rear)){
00120 ROS_ERROR("No joint given in namespace: '%s')",
00121 n.getNamespace().c_str());
00122 return false;
00123 }
00124
00125 wheel_inner_left_rear_state = robot->getJointState(wheel_inner_left_rear);
00126 if (!wheel_inner_left_rear_state ){
00127 ROS_ERROR("BaseOdometry could not find joint named '%s'",
00128 wheel_inner_left_rear.c_str());
00129 return false;
00130 }
00131
00132
00133 if (!n.getParam("wheel_inner_right_rear", wheel_inner_right_rear)){
00134 ROS_ERROR("No joint given in namespace: '%s')",
00135 n.getNamespace().c_str());
00136 return false;
00137 }
00138
00139 wheel_inner_right_rear_state = robot->getJointState(wheel_inner_right_rear);
00140 if (!wheel_inner_right_rear_state ){
00141 ROS_ERROR("BaseOdometry could not find joint named '%s'",
00142 wheel_inner_right_rear.c_str());
00143 return false;
00144 }
00145
00146
00147
00148 robot_ = robot;
00149
00150 odometry_publisher_.reset(new realtime_tools::RealtimePublisher<nav_msgs::Odometry>(n,"/odom", 1));
00151 transform_publisher_.reset(new realtime_tools::RealtimePublisher<tf::tfMessage>(n,"/tf", 1));
00152 transform_publisher_->msg_.transforms.resize(1);
00153
00154 if(odometry_publish_rate_ <= 0.0){
00155 expected_publish_time_ = 0.0;
00156 publish_odometry_ = false;
00157 }else{
00158 expected_publish_time_ = 1.0/odometry_publish_rate_;
00159 publish_odometry_ = true;
00160 }
00161
00162 return true;
00163 }
00164
00165
00166 void BaseOdometry::starting() {
00167 current_time_ = robot_->getTime();
00168 last_time_ = robot_->getTime();
00169 last_odometry_publish_time_ = robot_->getTime();
00170 last_transform_publish_time_ = robot_->getTime();
00171 }
00172
00173
00174 void BaseOdometry::update() {
00175 current_time_ = robot_->getTime();
00176 ros::Time update_start = ros::Time::now();
00177 updateOdometry();
00178
00179 update_time = (ros::Time::now()-update_start).toSec();
00180 ros::Time publish_start = ros::Time::now();
00181
00182 if(publish_odometry_)
00183 publish();
00184 if(publish_tf_)
00185 publishTransform();
00186
00187 last_time_ = current_time_;
00188 }
00189
00190
00191 void BaseOdometry::stopping() {
00192 }
00193
00194
00195 void BaseOdometry::updateOdometry() {
00196 double dt = (current_time_ - last_time_).toSec();
00197
00198 computeBaseVelocity();
00199
00200 double odom_delta_x = odometry_vel_.linear.x * dt;
00201 double odom_delta_y = odometry_vel_.linear.y * dt;
00202 double odom_delta_th = odometry_vel_.angular.z * dt;
00203
00204 odometry_.x += odom_delta_x;
00205 odometry_.y += odom_delta_y;
00206 odometry_.z += odom_delta_th;
00207
00208 ROS_DEBUG("Odometry:: Position: %f, %f, %f",odometry_.x,odometry_.y,odometry_.z);
00209 }
00210
00211
00212 void BaseOdometry::computeBaseVelocity() {
00213 current_vel_wheel_inner_left_front = wheel_inner_left_front_state->velocity_;
00214 current_vel_wheel_inner_right_front = wheel_inner_right_front_state->velocity_;
00215 current_vel_wheel_inner_left_rear = wheel_inner_left_rear_state->velocity_;
00216 current_vel_wheel_inner_right_rear = wheel_inner_right_rear_state->velocity_;
00217
00218
00219
00221 current_vel_x = 0.25*WHEELRAD*(current_vel_wheel_inner_right_front + current_vel_wheel_inner_left_front - current_vel_wheel_inner_left_rear - current_vel_wheel_inner_right_rear);
00222 current_vel_y = 0.25*WHEELRAD*(-current_vel_wheel_inner_right_front + current_vel_wheel_inner_left_front + current_vel_wheel_inner_left_rear - current_vel_wheel_inner_right_rear);
00223
00224 current_vel_phi = -0.25*WHEELRAD/DIS2CENT*(current_vel_wheel_inner_right_front+current_vel_wheel_inner_left_front+current_vel_wheel_inner_left_rear+current_vel_wheel_inner_right_rear);
00225
00226 double theta = odometry_.z;
00227 double costh = cos(theta);
00228 double sinth = sin(theta);
00229
00230
00231 odometry_vel_.linear.x = (current_vel_x * costh - current_vel_y * sinth);
00232 odometry_vel_.linear.y = (current_vel_x * sinth + current_vel_y * costh);
00233 odometry_vel_.angular.z = current_vel_phi;
00234 }
00235
00236
00237 void BaseOdometry::publish() {
00238 if(fabs((last_odometry_publish_time_ - current_time_).toSec()) < expected_publish_time_){
00239 return;
00240 }
00241 if(odometry_publisher_->trylock()){
00242 getOdometryMessage(odometry_publisher_->msg_);
00243 odometry_publisher_->unlockAndPublish();
00244 last_odometry_publish_time_ = current_time_;
00245 }
00246 }
00247
00248
00249 void BaseOdometry::getOdometryMessage(nav_msgs::Odometry &msg) {
00250 msg.header.frame_id = odometry_frame_;
00251 msg.header.stamp = current_time_;
00252 msg.pose.pose.position.x = odometry_.x;
00253 msg.pose.pose.position.y = odometry_.y;
00254 msg.pose.pose.position.z = 0.0;
00255
00256 geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(odometry_.z);
00257 msg.pose.pose.orientation = odom_quat;
00258
00259 msg.twist.twist.linear.x = current_vel_x;
00260 msg.twist.twist.linear.y = current_vel_y;
00261 msg.twist.twist.angular.z = current_vel_phi;
00262
00263 populateCovariance(msg);
00264 }
00265
00266
00267 void BaseOdometry::populateCovariance(nav_msgs::Odometry &msg) {
00268
00269
00270
00271
00272 if(fabs(odometry_vel_.linear.x) <= 1e-8 && fabs(odometry_vel_.linear.y) <= 1e-8 && fabs(odometry_vel_.angular.z) <= 1e-8){
00273 msg.pose.covariance[0] = 1e-12;
00274 msg.pose.covariance[7] = 1e-12;
00275 msg.pose.covariance[35] = 1e-12;
00276
00277 msg.pose.covariance[1] = 1e-12;
00278 msg.pose.covariance[6] = 1e-12;
00279
00280 msg.pose.covariance[31] = 1e-12;
00281 msg.pose.covariance[11] = 1e-12;
00282
00283 msg.pose.covariance[30] = 1e-12;
00284 msg.pose.covariance[5] = 1e-12;
00285 }else{
00286 msg.pose.covariance[0] = pow(sigma_x_,2);
00287 msg.pose.covariance[7] = pow(sigma_y_,2);
00288 msg.pose.covariance[35] = pow(sigma_theta_,2);
00289
00290 msg.pose.covariance[1] = cov_x_y_;
00291 msg.pose.covariance[6] = cov_x_y_;
00292
00293 msg.pose.covariance[31] = cov_y_theta_;
00294 msg.pose.covariance[11] = cov_y_theta_;
00295
00296 msg.pose.covariance[30] = cov_x_theta_;
00297 msg.pose.covariance[5] = cov_x_theta_;
00298 }
00299
00300 msg.pose.covariance[14] = DBL_MAX;
00301 msg.pose.covariance[21] = DBL_MAX;
00302 msg.pose.covariance[28] = DBL_MAX;
00303
00304 msg.twist.covariance = msg.pose.covariance;
00305 }
00306
00307
00308 void BaseOdometry::publishTransform() {
00309 if(fabs((last_transform_publish_time_ - current_time_).toSec()) < expected_publish_time_){
00310 return;
00311 }
00312 if(transform_publisher_->trylock()){
00313
00314 geometry_msgs::TransformStamped &out = transform_publisher_->msg_.transforms[0];
00315 out.header.stamp = current_time_;
00316 out.header.frame_id = tf::resolve(tf_prefix_,odometry_frame_);
00317 out.child_frame_id = tf::resolve(tf_prefix_,base_footprint_frame_);
00318 out.transform.translation.x = odometry_.x;
00319 out.transform.translation.y = odometry_.y;
00320 out.transform.translation.z = 0;
00321 tf::Quaternion quat_trans;
00322 quat_trans.setRPY(0.0, 0.0, odometry_.z);
00323
00324 out.transform.rotation.x = quat_trans.x();
00325 out.transform.rotation.y = quat_trans.y();
00326 out.transform.rotation.z = quat_trans.z();
00327 out.transform.rotation.w = quat_trans.w();
00328
00329 transform_publisher_->unlockAndPublish();
00330 last_transform_publish_time_ = current_time_;
00331 }
00332 }
00333