Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <ros/ros.h>
00031 #include <tf/transform_broadcaster.h>
00032 #include "math.h"
00033 #include "corobot_msgs/PosMsg.h"
00034 #include "nav_msgs/Odometry.h"
00035 #include <dynamic_reconfigure/server.h>
00036 #include <corobot_state_tf/corobot_state_tfConfig.h>
00037 #include "utility.h"
00038
00039
00040 Utility u;
00041
00042
00043 double DistancePerCount;
00044
00045
00046 double lengthBetweenTwoWheels;
00047
00048
00049 double x, y, th;
00050
00051
00052 bool firstTime = true;
00053
00054
00055 bool is4WheelDrive;
00056
00057
00058 bool publish_odom_tf;
00059
00060
00061 bool odometry_activated = true;
00062
00063
00064
00065
00066
00067 double previous_x = 0;
00068 double previous_y = 0;
00069 double previous_th = 0;
00070
00071 double previous_vx = 0;
00072 double previous_vy = 0;
00073 double previous_vth = 0;
00074
00075
00076
00077 corobot_msgs::PosMsg previous;
00078 corobot_msgs::PosMsg current;
00079
00080 std::vector<float> dists;
00081
00082
00083 bool x_startError = false;
00084 bool y_startError = false;
00085 bool th_startError = false;
00086
00087
00088
00089 void errorAdjustment(const double dx, const double dth) {
00090
00091
00092
00093 float th_error = -0.042555431f*dth;
00094 th = u.displaceAngle(th, th_error);
00095
00096 float tempx = dx*cos(th);
00097 float tempy = dx*sin(th);
00098
00099
00100 float x_error = -0.0181546483f*tempx;
00101
00102
00103 float y_error = -0.0181546483f*tempy;
00104
00105
00106
00107 x += (tempx + x_error);
00108 y += (tempy + y_error);
00109
00110
00111
00112 double v_x = (x - previous_x) / (current.header.stamp.toSec() - previous.header.stamp.toSec());
00113 double v_y = (y - previous_y) / (current.header.stamp.toSec() - previous.header.stamp.toSec());
00114 double v_th = (th - previous_th) / (current.header.stamp.toSec() - previous.header.stamp.toSec());
00115
00116 double a_x = (v_x - previous_vx) / (current.header.stamp.toSec() - previous.header.stamp.toSec());
00117 double a_y = (v_y - previous_vy) / (current.header.stamp.toSec() - previous.header.stamp.toSec());
00118 double a_th = (v_th - previous_vth) / (current.header.stamp.toSec() - previous.header.stamp.toSec());
00119
00120
00121 if( a_x > 0.6 && !x_startError && current.header.stamp != previous.header.stamp) {
00122 x += 0.009810897f/2.f;
00123 x_startError = true;
00124 }
00125
00126 if(a_y > 0.6 && !y_startError && current.header.stamp != previous.header.stamp) {
00127 y += 0.009810897f/2.f;
00128 y_startError = true;
00129 }
00130
00131 if( (a_th > 0.1 || a_th < -0.1) && !th_startError && current.header.stamp != previous.header.stamp) {
00132 th -= (0.005077337f / 2.f);
00133 th_startError = true;
00134 }
00135 else if(v_th > 0.001) {
00136 th_startError = false;
00137 }
00138 }
00139
00140
00142 void setValues() {
00143
00144
00145 ros::Time last_time_encoder = previous.header.stamp;
00146
00147
00148 ros::Time current_time_encoder = current.header.stamp;
00149
00150
00151 double delta_time = (current_time_encoder - last_time_encoder).toSec();
00152
00153
00154 if(firstTime == false) {
00155
00156
00157 double distance_left = ((double)(current.px - previous.px) * DistancePerCount);
00158 double distance_right = ((double)(current.py - previous.py) * DistancePerCount);
00159
00160
00161 double dx = (distance_left + distance_right)/2.0;
00162
00163
00164 double arc_length = (distance_right - distance_left);
00165
00166
00167
00168 double dth = (arc_length)/(lengthBetweenTwoWheels);
00169
00170
00171 th = u.displaceAngle(th, dth);
00172
00173
00174 errorAdjustment(dx, dth);
00175 }
00176
00177 else {
00178 firstTime = false;
00179 }
00180 }
00181
00182
00184 void WheelCallback(const corobot_msgs::PosMsg& pos) {
00185
00186 current = pos;
00187
00188 }
00189
00190
00191
00192 void dynamic_reconfigureCallback(corobot_state_tf::corobot_state_tfConfig &config, uint32_t level) {
00193 odometry_activated = config.camera_state_tf;
00194 }
00195
00196
00197
00199 void publish_odometry(ros::Publisher& odom_pub, tf::TransformBroadcaster& odom_broadcaster, tf::TransformBroadcaster& broadcaster) {
00200
00201
00202 setValues();
00203
00204
00205 broadcaster.sendTransform(tf::StampedTransform(tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.15, 0, 0)),ros::Time::now(),"base_link", "laser"));
00206
00207
00208 geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);
00209 geometry_msgs::Quaternion odom_quat2 = tf::createQuaternionMsgFromYaw(0);
00210
00211
00212 geometry_msgs::TransformStamped odom_trans;
00213 odom_trans.header.stamp = ros::Time::now();
00214 odom_trans.header.frame_id = "odom";
00215 odom_trans.child_frame_id = "base_footprint";
00216
00217 odom_trans.transform.translation.x = x;
00218 odom_trans.transform.translation.y = y;
00219 odom_trans.transform.translation.z = 0.0;
00220 odom_trans.transform.rotation = odom_quat;
00221
00222 geometry_msgs::TransformStamped odom_trans2;
00223 odom_trans2.header.stamp = current.header.stamp;
00224 odom_trans2.header.frame_id = "base_footprint";
00225 odom_trans2.child_frame_id = "base_link";
00226
00227 odom_trans2.transform.translation.x = 0;
00228 odom_trans2.transform.translation.y = 0;
00229 odom_trans2.transform.translation.z = 0.0;
00230 odom_trans2.transform.rotation = odom_quat2;
00231
00232
00233
00234 if(publish_odom_tf)
00235 odom_broadcaster.sendTransform(odom_trans);
00236 odom_broadcaster.sendTransform(odom_trans2);
00237
00238
00239 nav_msgs::Odometry odom;
00240 odom.header.stamp = current.header.stamp;
00241 odom.header.frame_id = "odom";
00242
00243
00244 odom.pose.pose.position.x = x;
00245 odom.pose.pose.position.y = y;
00246 odom.pose.pose.position.z = 0.0;
00247 odom.pose.pose.orientation = odom_quat;
00248
00249
00250 odom.pose.covariance[0] = 0.01;
00251 odom.pose.covariance[7] = 0.01;
00252 odom.pose.covariance[14] = 10000;
00253 odom.pose.covariance[21] = 10000;
00254 odom.pose.covariance[28] = 10000;
00255 odom.pose.covariance[35] = 0.1;
00256
00257
00260 odom.child_frame_id = "base_link";
00261
00262
00263 if (firstTime == false && current.header.stamp != previous.header.stamp) {
00264
00265
00266
00267
00268 odom.twist.twist.linear.x = (x - previous_x)/((current.header.stamp - previous.header.stamp).toSec());
00269
00270
00271 odom.twist.twist.linear.y = (y - previous_y)/((current.header.stamp - previous.header.stamp).toSec());
00272
00273
00274 odom.twist.twist.angular.z = (u.findDistanceBetweenAngles(th, previous_th)) / ((current.header.stamp - previous.header.stamp).toSec());
00275
00276
00277 previous_x = x;
00278 previous_y = y;
00279 previous_th = th;
00280 previous.header.stamp = current.header.stamp;
00281
00282 previous_vx = odom.twist.twist.linear.x;
00283 previous_vy = odom.twist.twist.linear.y;
00284 previous_vth = odom.twist.twist.angular.z;
00285 }
00286
00287
00288 else {
00289 odom.twist.twist.linear.x = 0;
00290 odom.twist.twist.linear.y = 0;
00291 odom.twist.twist.angular.z = 0;
00292 previous.header.stamp = ros::Time::now();
00293
00294 previous_vx = 0;
00295 previous_vy = 0;
00296 previous_vth = 0;
00297 x_startError = false;
00298 y_startError = false;
00299 th_startError = false;
00300 }
00301
00302
00303 odom.twist.covariance[0] = 0.01;
00304 odom.twist.covariance[7] = 0.01;
00305 odom.twist.covariance[14] = 10000;
00306 odom.twist.covariance[21] = 10000;
00307 odom.twist.covariance[28] = 10000;
00308 odom.twist.covariance[35] = 0.1;
00309
00310
00311 odom_pub.publish(odom);
00312
00313
00314 previous = current;
00315 }
00316
00317
00318 int main(int argc, char** argv) {
00319 int ticks_meter;
00320
00321 ros::init(argc, argv, "corobot_state_tf");
00322 ros::NodeHandle n;
00323 ros::NodeHandle nh("~");
00324
00325
00326
00327 nh.param("FourWheelDrive", is4WheelDrive, false);
00328
00329
00330 nh.param("base_width", lengthBetweenTwoWheels, 0.254);
00331
00332
00333 nh.param("ticks_meter", ticks_meter, 9400);
00334
00335
00336 nh.param("publish_odom_tf", publish_odom_tf, true);
00337
00338 dynamic_reconfigure::Server<corobot_state_tf::corobot_state_tfConfig> server;
00339 dynamic_reconfigure::Server<corobot_state_tf::corobot_state_tfConfig>::CallbackType f;
00340
00341 f = boost::bind(&dynamic_reconfigureCallback, _1, _2);
00342 server.setCallback(f);
00343
00344
00345 DistancePerCount = 1.0/(float)ticks_meter;
00346
00347
00348
00349 if(is4WheelDrive) {
00350 lengthBetweenTwoWheels *= 1.5;
00351 }
00352
00353
00354 ros::Subscriber sub = n.subscribe("position_data", 1000, WheelCallback);
00355 ros::Publisher odom_pub = n.advertise<nav_msgs::Odometry>("odometry", 50);
00356 tf::TransformBroadcaster odom_broadcaster;
00357
00358
00359 ros::Rate r(10);
00360
00361
00362 ros::Rate r_deactivated(2);
00363
00364 tf::TransformBroadcaster broadcaster;
00365
00366
00367 for(unsigned int i=0;i<3;i++) {
00368 dists.push_back(0);
00369 }
00370
00371 while(n.ok()) {
00372 ros::spinOnce();
00373 if (odometry_activated) {
00374 publish_odometry(odom_pub, odom_broadcaster, broadcaster);
00375 r.sleep();
00376 }
00377 else
00378 r_deactivated.sleep();
00379 }
00380
00381 return 0;
00382 }