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
00031 #include "std_msgs/String.h"
00032 #include "odometry_serialcom/odometry_serialcom.h"
00033
00034
00035 #define DEFAULT_PORT 1
00036 #define DEFAULT_BAUDRATE 9600
00037 #define MAX_BUF 1024
00038 typedef unsigned char BYTE;
00039 typedef unsigned short int WORD;
00040
00041 #define CRC16_GEN_POL 0xa001
00042 #define MKSHORT(a,b) ((unsigned short) (a) | ((unsigned short)(b) << 8))
00043 #include <tf/transform_broadcaster.h>
00044
00045 #include <iostream>
00046 #include <fstream>
00047 unsigned char _read0[10],_read1[10];
00048 bool b_is_received_params = false;
00049 bool b_reset_odom = false;
00050 double d_frequency;
00051 double d_wheel_separation;
00052 double d_height;
00053 int i_gear_ratio;
00054 int i_cpr;
00055 double d_wheel_diameter;
00056 int fd_;
00057 using namespace std;
00058 class SerialCom
00059 {
00060 public:
00061 SerialCom();
00062 ~SerialCom();
00063 int openPort(int fd, int comport);
00064 int setOpt(int fd,int nspeed,int nbits,char nevent,int nstop);
00065 int packSend(int fd,char ptr,char buff[]);
00066 int comInit();
00067 void SetBuf(char* buf,bool change,bool addCRC);
00068 void sendcommand();
00069 ros::NodeHandle serial_node_handle_;
00070
00071 private:
00072
00073 char _buf[MAX_BUF+3];
00074
00075 char _crc[10];
00076 unsigned char CRC_H,CRC_L;
00077 int _len;
00078 int port_,baudrate_;
00079 char command_buff_[30];
00080 ros::Time current_time_,last_time_;
00081 int nwrite;
00082 int nread;
00083 char hex[16];
00084 public:
00085 void SetBuf(char* buf,int len,bool change,bool addCRC);
00086 void Clear();
00087 char* GetBuf();
00088 int getLen();
00089 WORD CRC16(unsigned char *p,WORD len);
00090 void delay(unsigned int z);
00091
00092
00093 bool operator==(SerialCom& in);
00094 };
00095
00096
00097
00098 SerialCom::SerialCom()
00099 {
00100 char hex_[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
00101 memcpy(hex, hex_, sizeof(hex));
00102 serial_node_handle_.param("Port",port_,DEFAULT_PORT);
00103 serial_node_handle_.param("BaudRate",baudrate_,DEFAULT_BAUDRATE);
00104 comInit();
00105
00106
00107
00108
00109
00110
00111 }
00112
00113 SerialCom::~SerialCom()
00114 {
00115 close(fd_);
00116 }
00117
00118
00119 int SerialCom::openPort(int fd, int comport)
00120 {
00121 if(comport == 1)
00122 {
00123 fd = open("/dev/ttyMXUSB0",O_RDWR|O_NOCTTY|O_NDELAY);
00124
00125 if(-1 == fd)
00126 {
00127 ROS_INFO("failed to open /dev/ttyUSB0!");
00128 return(-1);
00129 }
00130 }
00131 else if(comport == 2)
00132 {
00133 fd = open("/dev/ttyMXUSB1",O_RDWR|O_NOCTTY|O_NDELAY);
00134 if(-1 == fd)
00135 {
00136 ROS_INFO("failed to open /dev/ttyUSB1!");
00137 return(-1);
00138 }
00139 }
00140
00141 if(fcntl(fd,F_SETFL,0)<0)
00142 ROS_INFO("fcntl failed!");
00143 else
00144 ROS_INFO("fcntl=%d.",fcntl(fd,F_SETFL,0));
00145
00146 if(isatty(STDIN_FILENO) == 0)
00147 ROS_INFO("standsrd input is not a terminal device.");
00148 else
00149 ROS_INFO("is a tty sucess.");
00150
00151 ROS_INFO("the return value of the serial open function=%d,!=-1,indicates succeed to open the serial.",fd);
00152
00153 return fd;
00154 }
00155
00156
00157 int SerialCom::setOpt(int fd,int nspeed,int nbits,char nevent,int nstop)
00158 {
00159 struct termios newtio,oldtio;
00160
00161
00162 if(tcgetattr(fd,&oldtio) != 0)
00163 {
00164 ROS_INFO("failed to setup the serial,failed to save the serial value!");
00165 return -1;
00166 }
00167
00168 bzero(&newtio,sizeof(newtio));
00169
00170 newtio.c_cflag |= CLOCAL | CREAD;
00171 newtio.c_cflag &= ~CSIZE;
00172
00173 switch(nbits)
00174 {
00175 case 7:
00176 newtio.c_cflag |= CS7;
00177 break;
00178 case 8:
00179 newtio.c_cflag |= CS8;
00180 break;
00181 }
00182
00183 switch(nevent)
00184 {
00185 case 'O':
00186 newtio.c_cflag |= PARENB;
00187 newtio.c_cflag |= PARODD;
00188 newtio.c_iflag |= (INPCK | ISTRIP);
00189 break;
00190 case 'E':
00191 newtio.c_iflag |= (INPCK | ISTRIP);
00192 newtio.c_cflag |= PARENB ;
00193 newtio.c_cflag &= ~ PARODD;
00194 break;
00195 case 'N':
00196 newtio.c_cflag &= ~ PARENB;
00197 break;
00198 }
00199
00200
00201 switch(nspeed)
00202 {
00203 case 2400:
00204 cfsetispeed(&newtio,B2400);
00205 cfsetospeed(&newtio,B2400);
00206 break;
00207 case 4800:
00208 cfsetispeed(&newtio,B4800);
00209 cfsetospeed(&newtio,B4800);
00210 break;
00211 case 9600:
00212 cfsetispeed(&newtio,B9600);
00213 cfsetospeed(&newtio,B9600);
00214 break;
00215 case 19200:
00216 cfsetispeed(&newtio,B19200);
00217 cfsetospeed(&newtio,B19200);
00218 break;
00219 case 38400:
00220 cfsetispeed(&newtio,B38400);
00221 cfsetospeed(&newtio,B38400);
00222 break;
00223 case 57600:
00224 cfsetispeed(&newtio,B57600);
00225 cfsetospeed(&newtio,B57600);
00226 break;
00227 case 115200:
00228 cfsetispeed(&newtio,B115200);
00229 cfsetospeed(&newtio,B115200);
00230 break;
00231 case 460800:
00232 cfsetispeed(&newtio,B460800);
00233 cfsetospeed(&newtio,B460800);
00234 break;
00235 default:
00236 cfsetispeed(&newtio,B9600);
00237 cfsetospeed(&newtio,B9600);
00238 break;
00239 }
00240
00241
00242 if(nstop == 1)
00243 newtio.c_cflag &= ~ CSTOPB;
00244 else if(nstop == 2)
00245 newtio.c_cflag |= CSTOPB;
00246
00247
00248 newtio.c_cc[VTIME] = 0;
00249 newtio.c_cc[VMIN] = 0;
00250
00251
00252 tcflush(fd,TCIFLUSH);
00253
00254
00255 if((tcsetattr(fd,TCSANOW,&newtio))!=0)
00256 {
00257 ROS_INFO("failed to activate the new serial setup!");
00258 return -1;
00259 }
00260
00261 ROS_INFO("serial setup success!\n");
00262
00263 return 0;
00264 }
00265
00266
00267
00268
00269
00270 int SerialCom::comInit()
00271 {
00272 int i;
00273
00274 if((fd_ = openPort(fd_,port_)) < 0)
00275 {
00276 ROS_INFO("failed to setup the serial!");
00277 return 0;
00278 }
00279
00280 if((i = setOpt(fd_,baudrate_,8,'N',1)) < 0)
00281 {
00282 ROS_INFO("failed to setup the serial!");
00283 return 0;
00284 }
00285
00286 ROS_INFO("the serial openned,setup the serial successed。the file operator=%d",fd_);
00287
00288 return 0;
00289 }
00290
00291
00293 void SerialCom::SetBuf(char* buf,bool change,bool addCRC)
00294 {
00295 _buf[0]='\0';
00296 if ( !change )
00297 {
00298 strcpy(_buf,buf);
00299 _len=(int)strlen(buf);
00300 }
00301 else
00302 {
00303 char c;
00304 _len=0;
00305 for(int i=0; *(buf+i)!='\0'&&i<MAX_BUF*2; i++)
00306 {
00307 c=*(buf+i);
00308 if ( c>='0' && c<='9' )
00309 c=(char)(c-'0');
00310 else if( c>='a' && c<='f' )
00311 c=(char)(c-'a'+10);
00312 else if( c>='A' && c<='F')
00313 c=(char)(c-'A'+10);
00314 else
00315 continue;
00316 if ( _len%2==0 )
00317 _buf[(int)(_len/2)]=c<<4;
00318 else
00319 _buf[(int)(_len/2)]=( _buf[(int)(_len/2)] | c );
00320 _len++;
00321 }
00322
00323 _len=(_len+1)/2;
00324
00325 }
00326 if( addCRC )
00327 {
00328
00329 WORD crc=CRC16((BYTE*)GetBuf(),getLen());;
00330 int high,low;
00331
00332 high=crc/256;
00333 low=crc%256;
00334 _buf[_len]=char(high);
00335 _buf[_len+1]=char(low);
00336 _len+=2;
00337 int temp;
00338 temp=(crc/256)/16;
00339 _crc[0]=hex[temp];
00340 temp=(crc/256)%16;
00341 _crc[1]=hex[temp];
00342 temp=(crc%256)/16;
00343 _crc[2]=hex[temp];
00344 temp=(crc%256)%16;
00345 _crc[3]=hex[temp];
00346 _crc[4]='\0';
00347
00348
00349
00350
00351
00352 }
00353 _buf[_len]='\0';
00354
00355 }
00356
00357
00358 void SerialCom::Clear()
00359 {
00360 _len=0;
00361 _buf[_len]='\0';
00362 }
00363
00364
00365 char* SerialCom::GetBuf()
00366 {
00367 return _buf;
00368 }
00369
00370
00371 int SerialCom::getLen()
00372 {
00373 return _len;
00374 }
00375
00376
00377
00378 bool SerialCom::operator==(SerialCom& in)
00379 {
00380 if ( _len==in.getLen() )
00381 {
00382 for(int i=0;i<_len;i++ )
00383 {
00384 if( _buf[i]!=*(in.GetBuf()+i) )
00385 return false;
00386 }
00387 return true;
00388 }
00389 return false;
00390 }
00391
00392 WORD SerialCom::CRC16(unsigned char *p,WORD len)
00393 {
00394 unsigned char i;
00395 WORD j;
00396 WORD uiCRC=0xffff;
00397 for(j=0;j<len;j++)
00398 {
00399 uiCRC^=(*p);
00400 p++;
00401 for(i=8;i!=0;i--)
00402 {
00403 if(uiCRC&1){uiCRC>>=1;uiCRC^=0xa001;}
00404 else
00405 uiCRC>>=1;
00406 }
00407 }
00408 return(uiCRC);
00409 }
00410 void SerialCom::sendcommand()
00411 {
00412 command_buff_[0]='\0';
00413 strcpy(command_buff_,"01 04 00 40 00 06 71 DC");
00414 SetBuf(command_buff_,true,false);
00415 nwrite=write(fd_,_buf,8);
00416 delay(10);
00417 nread=read(fd_,_read0,17);
00418 ROS_INFO("_read0[3]=%d",_read0[3]);
00419 ROS_INFO("_read0[4]=%d",_read0[4]);
00420 ROS_INFO("_read0[5]=%d",_read0[5]);
00421 ROS_INFO("_read0[6]=%d",_read0[6]);
00422 ROS_INFO("_read0[11]=%d",_read0[11]);
00423 ROS_INFO("_read0[12]=%d",_read0[12]);
00424 ROS_INFO("_read0[13]=%d",_read0[13]);
00425 ROS_INFO("_read0[14]=%d",_read0[14]);
00426 delay(900);
00427 }
00428 void SerialCom::delay(unsigned int z)
00429 {
00430 unsigned int i,j;
00431 for(i=z;i>0;i--)
00432 for(j=110;j>0;j--);
00433 }
00434 int main(int argc, char **argv)
00435 {
00436 ros::init(argc, argv, "odometry_serialcom");
00437 stringstream ss;
00438 SerialCom serial;
00439 ros::NodeHandle nh_private_;
00440 ros::NodeHandle n;
00441 if (!nh_private_.getParam ("d_wheel_separation", d_wheel_separation))
00442 d_wheel_separation = 0.39;
00443 if (!nh_private_.getParam ("d_height", d_height))
00444 d_height = 0;
00445 if (!nh_private_.getParam ("i_gear_ratio", i_gear_ratio))
00446 i_gear_ratio = 30;
00447 if (!nh_private_.getParam ("i_cpr", i_cpr))
00448 i_cpr = 500;
00449 if (!nh_private_.getParam ("d_frequency", d_frequency))
00450 d_frequency = 10;
00451 if (!nh_private_.getParam ("d_wheel_diameter", d_wheel_diameter))
00452 d_wheel_diameter = 0.138;
00453 realtime_tools::RealtimePublisher<nav_msgs::Odometry> * pose_pub = new realtime_tools::RealtimePublisher<nav_msgs::Odometry>(n, "odom", 10);
00454 ros::Rate loop_rate(d_frequency);
00455 ros::Time read_time = ros::Time::now();
00456 ros::Duration dur_time;
00457 geometry_msgs::Pose2D odom_pose;
00458 geometry_msgs::Pose2D delta_odom_pose;
00459 static tf::TransformBroadcaster br;
00460 tf::Transform transform;
00461 tf::Quaternion q;
00462 unsigned int f_left_read = 0, f_right_read = 0;
00463 unsigned int f_left_read_last = 0, f_right_read_last = 0;
00464 float covariance[36] = {0.01, 0, 0, 0, 0, 0,
00465 0, 0.01, 0, 0, 0, 0,
00466 0, 0, 99999, 0, 0, 0,
00467 0, 0, 0, 99999, 0, 0,
00468 0, 0, 0, 0, 99999, 0,
00469 0, 0, 0, 0, 0, 0.01};
00470 for(int i = 0; i < 36; i++)
00471 {
00472 pose_pub->msg_.pose.covariance[i] = covariance[i];
00473 }
00474
00475
00476
00477 write(fd_, "clean", 5);
00478
00479
00480 double roll = 0.0;
00481 double pitch = 0.0;
00482 double yaw = 0.0;
00483 int num=0;
00484 unsigned int test_num_l=0,test_num_r=0;
00485 while (ros::ok())
00486 {
00487 if(b_is_received_params)
00488 {
00489 ROS_DEBUG("EvarobotOdometry: Updating Odometry Params...");
00490 b_is_received_params = false;
00491 }
00492
00493 if(b_reset_odom)
00494 {
00495 ROS_DEBUG("EvarobotOdometry: Resetting Odometry");
00496
00497 write(fd_, "clean", 5);
00498
00499 f_left_read = 0.0;
00500 f_right_read = 0.0;
00501 f_left_read_last = 0.0;
00502 f_right_read_last = 0.0;
00503
00504 odom_pose.x = 0.0;
00505 odom_pose.y = 0.0;
00506 odom_pose.theta = 0.0;
00507
00508 delta_odom_pose.x = 0.0;
00509 delta_odom_pose.y = 0.0;
00510 delta_odom_pose.theta = 0.0;
00511
00512 b_reset_odom = false;
00513 }
00514
00515
00516 serial.sendcommand();
00517 f_left_read = ((_read0[3]*256+_read0[4])*256+_read0[5])*256+_read0[6];
00518 f_right_read =((_read0[11]*256+_read0[12])*256+_read0[13])*256+_read0[14];
00519
00520 dur_time = ros::Time::now() - read_time;
00521 read_time = ros::Time::now();
00522
00523 if(num<4)
00524 {
00525 f_left_read_last = f_left_read;
00526 f_right_read_last = f_right_read;
00527 num++;
00528 }
00529
00530
00531 float f_delta_sr = 0.0, f_delta_sl = 0.0, f_delta_s = 0.0;
00532 float f_rotvel_left = 0.0, f_rotvel_right = 0.0;
00533 float f_right_delta=0.0,f_left_delta=0.0;
00534 long long left_read,right_read,left_read_last,right_read_last;
00535 left_read=f_left_read;
00536 right_read=f_right_read;
00537 left_read_last=f_left_read_last;
00538 right_read_last=f_right_read_last;
00539 if(f_right_read_last > 4000000000.0 && f_right_read <= 10000)
00540 {
00541 f_right_delta = float(- 4294967296.0 + right_read_last - right_read);
00542 }
00543 else if(f_right_read > 4000000000.0 && f_right_read_last <= 10000)
00544 {
00545 f_right_delta = float(right_read_last + 4294967296.0 - right_read);
00546 }
00547 else if(f_right_read > 4000000000.0 && f_right_read_last == 0)
00548 {
00549 f_right_delta = float(4294967296.0 - right_read);
00550 }
00551 else
00552 {
00553 f_right_delta = float(right_read_last - right_read);
00554 }
00555
00556 if(f_left_read_last > 4000000000.0 && f_left_read <= 10000)
00557 {
00558 f_left_delta = float(4294967296.0 - left_read_last + left_read);
00559 }
00560 else if(f_left_read > 4000000000.0 && f_left_read_last <= 10000)
00561 {
00562 f_left_delta = float(- left_read_last - 4294967296.0 + left_read);
00563 }
00564 else if(f_left_read > 4000000000.0 && f_left_read_last == 0)
00565 {
00566 f_left_delta = float(- 4294967296.0 + left_read);
00567 }
00568 else
00569 {
00570 f_left_delta = float(left_read - left_read_last);
00571 }
00572 if(f_left_delta==4294967296.000000 || f_right_delta==4294967296.000000)
00573 {
00574 f_left_delta = 0.0;
00575 f_right_delta = 0.0;
00576 }
00577
00578
00579 test_num_l += f_left_delta;
00580 test_num_r +=f_right_delta;
00581 ROS_INFO("test_num_l = %u and test_num_r = %u ",test_num_l,test_num_r);
00582 ROS_INFO("f_right_delta = %f f_left_delta = %f",f_right_delta,f_left_delta);
00583 ROS_INFO("f_left_read = %u f_left_read_last = %u",f_left_read,f_left_read_last);
00584 ROS_INFO("f_right_read = %u f_right_read_last = %u",f_right_read,f_right_read_last);
00585
00586 f_delta_sr = PI * d_wheel_diameter * f_right_delta / (4.11*i_gear_ratio * i_cpr);
00587 f_delta_sl = PI * d_wheel_diameter * f_left_delta / (4.11*i_gear_ratio * i_cpr);
00588
00589 f_rotvel_left = 2*PI * f_left_delta / (4.11*i_gear_ratio * i_cpr);
00590 f_rotvel_right = 2*PI * f_right_delta / (4.11*i_gear_ratio * i_cpr);
00591
00592
00593 delta_odom_pose.theta = (f_delta_sr - f_delta_sl) / d_wheel_separation;
00594 f_delta_s = (f_delta_sr + f_delta_sl) / 2;
00595
00596
00597 delta_odom_pose.x = f_delta_s * cos(odom_pose.theta + delta_odom_pose.theta * 0.5);
00598 delta_odom_pose.y = f_delta_s * sin(odom_pose.theta + delta_odom_pose.theta * 0.5);
00599
00600
00601 odom_pose.x += delta_odom_pose.x;
00602 odom_pose.y += delta_odom_pose.y;
00603 odom_pose.theta += delta_odom_pose.theta;
00604
00605
00606 f_right_read_last = f_right_read;
00607 f_left_read_last = f_left_read;
00608
00609
00610
00611 pose_pub->msg_.pose.pose.position.x = odom_pose.x;
00612 pose_pub->msg_.pose.pose.position.y = odom_pose.y;
00613 pose_pub->msg_.pose.pose.position.z = (float)d_height;
00614
00615
00616 roll = 0.0;
00617 pitch = 0.0;
00618 yaw = odom_pose.theta;
00619
00620
00621 pose_pub->msg_.pose.pose.orientation.x = sin(roll*0.5) * cos(pitch*0.5) * cos(yaw*0.5) - cos(roll*0.5) * sin(pitch*0.5) * sin(yaw*0.5);
00622 pose_pub->msg_.pose.pose.orientation.y = cos(roll*0.5) * sin(pitch*0.5) * cos(yaw*0.5) + sin(roll*0.5) * cos(pitch*0.5) * sin(yaw*0.5);
00623 pose_pub->msg_.pose.pose.orientation.z = cos(roll*0.5) * cos(pitch*0.5) * sin(yaw*0.5) - sin(roll*0.5) * sin(pitch*0.5) * cos(yaw*0.5);
00624 pose_pub->msg_.pose.pose.orientation.w = cos(roll*0.5) * cos(pitch*0.5) * cos(yaw*0.5) + sin(roll*0.5) * sin(pitch*0.5) * sin(yaw*0.5);
00625
00626 transform.setOrigin( tf::Vector3(odom_pose.x, odom_pose.y, (float)d_height) );
00627 q.setRPY(0, 0, odom_pose.theta);
00628 transform.setRotation(q);
00629 br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "odom", "base_link"));
00630
00632 float f_lin_vel = 0, f_ang_vel = 0;
00633 float f_lin_vel_right = 0, f_lin_vel_left = 0;
00634
00635 ROS_DEBUG_STREAM("EvarobotOdometry: dur_time: " << dur_time.toSec());
00636
00637 if(dur_time.toSec() > 0)
00638 {
00639 f_lin_vel_right = f_delta_sr / dur_time.toSec();
00640 f_lin_vel_left = f_delta_sl / dur_time.toSec();
00641
00642 ROS_DEBUG_STREAM("EvarobotOdometry: VEl_LEFT: " << f_lin_vel_left << " Vel_right: " << f_lin_vel_right << " dur: " << dur_time.toSec());
00643
00644 f_rotvel_left /= dur_time.toSec();
00645 f_rotvel_right /= dur_time.toSec();
00646
00647 f_lin_vel = (f_lin_vel_right + f_lin_vel_left) / 2.0;
00648 f_ang_vel = (f_lin_vel_right - f_lin_vel_left) / d_wheel_separation;
00649 }
00650 else
00651 {
00652 ROS_INFO("dur_time.tosec() failed");
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 pose_pub->msg_.twist.twist.linear.x = f_lin_vel;
00680 pose_pub->msg_.twist.twist.linear.y = 0.0;
00681 pose_pub->msg_.twist.twist.linear.z = 0.0;
00682
00683 pose_pub->msg_.twist.twist.angular.x = 0.0;
00684 pose_pub->msg_.twist.twist.angular.y = 0.0;
00685 pose_pub->msg_.twist.twist.angular.z = f_ang_vel;
00686
00687
00688
00689
00690 pose_pub->msg_.header.stamp = ros::Time::now();
00691
00692
00693 ss.str("");
00694 ss << n.resolveName(n.getNamespace(), true) << "/odom";
00695 pose_pub->msg_.header.frame_id = ss.str();
00696
00697 ss.str("");
00698 ss << n.resolveName(n.getNamespace(), true) << "/base_link";
00699 pose_pub->msg_.child_frame_id = ss.str();
00700
00701
00702 if (pose_pub->trylock())
00703 {
00704 pose_pub->unlockAndPublish();
00705 }
00706
00707
00708 ros::spinOnce();
00709
00710
00711 loop_rate.sleep();
00712 }
00713
00714
00715
00716 return 0;
00717 }
00718