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
00100 #if HAVE_CONFIG_H
00101 #include <config.h>
00102 #endif
00103
00104 #include "er.h"
00105 #include <errno.h>
00106 #include <fcntl.h>
00107 #include <termios.h>
00108 #include <stdlib.h>
00109 #include <unistd.h>
00110 #include <netinet/in.h>
00111 #include <math.h>
00112 #include <string.h>
00113 #include <sys/ioctl.h>
00114 #include <sys/time.h>
00115
00116 #define DEG2RAD_CONV(x) ((x)*(M_PI/180))
00117 #include <libplayercore/playercore.h>
00118
00119 static float lastlvel, lastrvel;
00120
00121 static void StopRobot(void* erdev);
00122
00123
00124 Driver* ER_Init( ConfigFile* cf, int section)
00125 {
00126 return((Driver*)(new ER(cf, section)));
00127 }
00128
00129
00130
00131 void
00132 ER_Register(DriverTable* table)
00133 {
00134 table->AddDriver("er1", ER_Init);
00135 }
00136
00137 ER::ER(ConfigFile* cf, int section)
00138 : Driver(cf, section)
00139 {
00140
00141 memset(&this->position_id, 0, sizeof(position_id));
00142 this->position_subscriptions = 0;
00143
00144 printf( "discovering drivers\n" );
00145
00146
00147 if(cf->ReadDeviceAddr(&(this->position_id), section, "provides",
00148 PLAYER_POSITION2D_CODE, -1, NULL) == 0)
00149 {
00150 if(this->AddInterface(this->position_id) != 0)
00151 {
00152 this->SetError(-1);
00153 return;
00154 }
00155 }
00156
00157
00158
00159 _fd = -1;
00160 _tc_num = new int[3];
00161 _tc_num[0] = 2;
00162 _tc_num[1] = 0;
00163 _tc_num[2] = 185;
00164 this->_serial_port = cf->ReadString(section, "port", ER_DEFAULT_PORT);
00165
00166
00167 _axle_length = cf->ReadFloat( section, "axle", ER_DEFAULT_AXLE_LENGTH );
00168
00169
00170 int dir = cf->ReadInt(section,"motor_dir", 1);
00171 _motor_0_dir = dir * ER_DEFAULT_MOTOR_0_DIR;
00172 _motor_1_dir = dir * ER_DEFAULT_MOTOR_1_DIR;
00173
00174 _debug = (1 == cf->ReadInt( section, "debug", 0 ));
00175
00176 _powered = false;
00177 _resting = false;
00178 }
00179
00180
00182
00184 int
00185 ER::ReadBuf(unsigned char* s, size_t len)
00186 {
00187 int thisnumread;
00188 int errorprinted = 0;
00189 size_t numread = 0;
00190
00191 for (int i = 0; i < 50; i++) {
00192 usleep (100);
00193 thisnumread = read (this->_fd, s + numread, len - numread);
00194 if (thisnumread > 0) {
00195 numread += thisnumread;
00196 errorprinted = 0;
00197 } else if (thisnumread < 0 && !errorprinted) {
00198 perror ("read");
00199 errorprinted = 1;
00200 } else if (numread != 0) {
00201
00202 return numread;
00203 }
00204
00205 }
00206
00207 return 0;
00208 }
00209
00210 int
00211 ER::WriteBuf(unsigned char* s, size_t len)
00212 {
00213 size_t numwritten;
00214 int thisnumwritten;
00215 numwritten=0;
00216 while(numwritten < len)
00217 {
00218 if((thisnumwritten = write(this->_fd,s+numwritten,len-numwritten)) < 0)
00219 {
00220 if(!this->_fd_blocking && errno == EAGAIN)
00221 {
00222 usleep(ER_DELAY_US);
00223 continue;
00224 }
00225 printf("write() failed: %s\n", strerror(errno));
00226 return(-1);
00227 }
00228 numwritten += thisnumwritten;
00229 }
00230
00231 ioctl( this->_fd, TIOCMSET, _tc_num );
00232 if( _tc_num[0] == 2 ) { _tc_num[0] = 0; }
00233 else { _tc_num[0] = 2; }
00234
00235 return numwritten;
00236 }
00237
00238 int
00239 ER::checksum_ok (unsigned char *buf, int len)
00240 {
00241 unsigned char csum = 0;
00242 for (int i = 0; i < len; i++) {
00243 csum += buf[i];
00244 }
00245 return (csum == 0);
00246 }
00247
00248 int
00249 ER::send_command( unsigned char address, unsigned char c, int ret_num, unsigned char * ret )
00250 {
00251 unsigned char cmd[4];
00252
00253 cmd[0] = address;
00254 cmd[2] = 0x00;
00255 cmd[3] = c;
00256
00257
00258 int chk = 0x100;
00259 chk -= cmd[0];
00260 chk -= cmd[2];
00261 chk -= cmd[3];
00262
00263 cmd[1] = (unsigned char) chk;
00264
00265 if (WriteBuf (cmd, 4) != 4) return -1;
00266 if (ReadBuf (ret, ret_num) <= 0) return -1;
00267
00268
00269
00270 return 4;
00271 }
00272
00273
00274
00275 int
00276 ER::send_command_2_arg( unsigned char address, unsigned char c, int arg, int ret_num, unsigned char * ret )
00277 {
00278 unsigned char cmd[6];
00279
00280 cmd[0] = address;
00281 cmd[2] = 0x00;
00282 cmd[3] = c;
00283
00284 int a = htons( arg );
00285
00286 cmd[5] = (a >> 8) & 0xFF;
00287 cmd[4] = (a >> 0) & 0xFF;
00288
00289
00290 int chk = 0x100;
00291 chk -= cmd[0];
00292 chk -= cmd[2];
00293 chk -= cmd[3];
00294 chk -= cmd[4];
00295 chk -= cmd[5];
00296
00297 cmd[1] = (unsigned char) chk;
00298
00299 if (WriteBuf (cmd, 6) != 6) return -1;
00300 if (ReadBuf (ret, ret_num) <= 0) return -1;
00301
00302
00303
00304 return 6;
00305 }
00306
00307 int
00308 ER::send_command_4_arg( unsigned char address, unsigned char c, int arg, int ret_num, unsigned char * ret )
00309 {
00310 unsigned char cmd[8];
00311
00312 cmd[0] = address;
00313 cmd[2] = 0x00;
00314 cmd[3] = c;
00315
00316 int a = htonl( arg );
00317 cmd[7] = (a >> 24) & 0xFF;
00318 cmd[6] = (a >> 16) & 0xFF;
00319 cmd[5] = (a >> 8 ) & 0xFF;
00320 cmd[4] = (a >> 0 ) & 0xFF;
00321
00322
00323 int chk = 0x100;
00324 chk -= cmd[0];
00325 chk -= cmd[2];
00326 chk -= cmd[3];
00327 chk -= cmd[4];
00328 chk -= cmd[5];
00329 chk -= cmd[6];
00330 chk -= cmd[7];
00331
00332 cmd[1] = (unsigned char) chk;
00333
00334 if (WriteBuf (cmd, 8) != 8) return -1;
00335 if (ReadBuf (ret, ret_num) <= 0) return -1;
00336
00337
00338
00339
00340 return 8;
00341 }
00342
00344
00346
00347 int
00348 ER::InitRobot()
00349 {
00350
00351 unsigned char buf[6];
00352 usleep(ER_DELAY_US);
00353 if(send_command( MOTOR_0, GETVERSION, 6, buf ) < 0)
00354 {
00355 return -1;
00356 }
00357
00358 if (!checksum_ok (buf, 6)) {
00359 printf ("invalid checksum\n");
00360 errno = ENXIO;
00361 return -1;
00362 }
00363
00364 if(send_command( MOTOR_1, GETVERSION, 6, buf ) < 0)
00365 {
00366 return -1;
00367 }
00368
00369 _tc_num[2] = 25;
00370 _stopped = true;
00371 return(0);
00372 }
00373
00374 int
00375 ER::InitOdom()
00376 {
00377 unsigned char ret[8];
00378
00379
00380 send_command( MOTOR_0, RESET, 2, ret );
00381 send_command_2_arg( MOTOR_0, SETMOTORCMD, 0, 2, ret );
00382 send_command_2_arg( MOTOR_0, SETLIMITSWITCHMODE, 0, 2, ret );
00383 send_command_2_arg( MOTOR_0, SETPROFILEMODE, 0x0001, 2, ret );
00384 send_command_4_arg( MOTOR_0, SETVEL, 0, 2, ret );
00385 send_command_4_arg( MOTOR_0, SETACCEL, 0, 2, ret );
00386 send_command_4_arg( MOTOR_0, SETDECEL, 0, 2, ret );
00387
00388
00389 send_command( MOTOR_1, RESET, 2, ret );
00390 send_command_2_arg( MOTOR_1, SETMOTORCMD, 0, 2, ret );
00391 send_command_2_arg( MOTOR_1, SETLIMITSWITCHMODE, 0, 2, ret );
00392 send_command_2_arg( MOTOR_1, SETPROFILEMODE, 0x0001, 2, ret );
00393 send_command_4_arg( MOTOR_1, SETVEL, 0, 2, ret );
00394 send_command_4_arg( MOTOR_1, SETACCEL, 0, 2, ret );
00395 send_command_4_arg( MOTOR_1, SETDECEL, 0, 2, ret );
00396
00397
00398 send_command( MOTOR_0, UPDATE, 2, ret );
00399 send_command( MOTOR_1, UPDATE, 2, ret );
00400
00401 _last_ltics = 0;
00402 _last_rtics = 0;
00403
00404 return 0;
00405 }
00406
00407 int
00408 ER::Setup()
00409 {
00410 struct termios term;
00411 int flags;
00412
00413
00414 this->_px = this->_py = this->_pa = 0.0;
00415 this->_odom_initialized = false;
00416
00417 printf("Evolution Robotics evolution_rcm connection initializing (%s)...\n", _serial_port);
00418 fflush(stdout);
00419
00420
00421 if((this->_fd = open(_serial_port, O_RDWR | O_NONBLOCK, S_IRUSR | S_IWUSR )) < 0 )
00422 {
00423 printf("open() failed: %s\n", strerror(errno));
00424 return(-1);
00425 }
00426
00427 if(tcgetattr(this->_fd, &term) < 0 )
00428 {
00429 printf("tcgetattr() failed: %s\n", strerror(errno));
00430 close(this->_fd);
00431 this->_fd = -1;
00432 return(-1);
00433 }
00434
00435 cfmakeraw( &term );
00436 term.c_cc[VTIME] = 20;
00437 term.c_cc[VMIN] = 0;
00438 cfsetispeed(&term, B230400);
00439 cfsetospeed(&term, B230400);
00440 if(tcsetattr(this->_fd, TCSADRAIN, &term) < 0 )
00441 {
00442 printf("tcsetattr() failed: %s\n", strerror(errno));
00443 close(this->_fd);
00444 this->_fd = -1;
00445 return(-1);
00446 }
00447
00448 _fd_blocking = false;
00449 if(InitRobot() < 0)
00450 {
00451 printf("failed to initialize robot\n");
00452 close(this->_fd);
00453 this->_fd = -1;
00454 return(-1);
00455 }
00456
00457
00458 if((flags = fcntl(this->_fd, F_GETFL)) < 0)
00459 {
00460 printf("fcntl() failed: %s\n", strerror(errno));
00461 close(this->_fd);
00462 this->_fd = -1;
00463 return(-1);
00464 }
00465
00466 flags &= ~O_NONBLOCK;
00467 if(fcntl(this->_fd, F_SETFL, flags) < 0)
00468 {
00469 printf("fcntl() failed: %s\n", strerror(errno));
00470 close(this->_fd);
00471 this->_fd = -1;
00472 return(-1);
00473 }
00474 _fd_blocking = true;
00475
00476
00477 if( InitOdom() < 0 ) {
00478 printf("InitOdom failed\n" );
00479 close(this->_fd);
00480 this->_fd = -1;
00481 return -1;
00482 }
00483
00484
00485 this->StartThread();
00486
00487 return(0);
00488 }
00489
00490 void InvokeMain (void *arg)
00491 {
00492 ER *er = (ER *)arg;
00493 er->Main();
00494 }
00495
00496 int
00497 ER::Shutdown()
00498 {
00499 if(this->_fd == -1)
00500 return(0);
00501
00502 StopThread();
00503
00504
00505
00506
00507 if(SetVelocity(0,0) < 0)
00508 printf("failed to stop robot while shutting down\n");
00509
00510
00511 usleep(ER_DELAY_US);
00512
00513 if(close(this->_fd))
00514 printf("close() failed:%s\n",strerror(errno));
00515 this->_fd = -1;
00516 if( _debug )
00517 printf("ER has been shutdown\n\n");
00518
00519 return(0);
00520 }
00521
00522 void
00523 ER::Stop( int StopMode )
00524 {
00525 unsigned char ret[8];
00526
00527 printf( "Stop\n" );
00528
00529 _stopped = true;
00530 if( StopMode == FULL_STOP )
00531 {
00532
00533 send_command_2_arg( MOTOR_0, RESETEVENTSTATUS, 0x0000, 2, ret );
00534 send_command_2_arg( MOTOR_0, SETMOTORCMD, 0x0000, 2, ret );
00535 send_command_2_arg( MOTOR_0, SETPROFILEMODE, 0x0001, 2, ret );
00536 send_command_2_arg( MOTOR_0, SETSTOPMODE, 0x0001, 2, ret );
00537 send_command_4_arg( MOTOR_0, SETVEL, 0, 2, ret );
00538 send_command_4_arg( MOTOR_0, SETACCEL, 0, 2, ret );
00539 send_command_4_arg( MOTOR_0, SETDECEL, 0, 2, ret );
00540 send_command( MOTOR_0, UPDATE, 2, ret );
00541 send_command( MOTOR_0, RESET, 2, ret );
00542
00543
00544 send_command_2_arg( MOTOR_1, RESETEVENTSTATUS, 0x0000, 2, ret );
00545 send_command_2_arg( MOTOR_1, SETMOTORCMD, 0x0000, 2, ret );
00546 send_command_2_arg( MOTOR_1, SETPROFILEMODE, 0x0001, 2, ret );
00547 send_command_2_arg( MOTOR_1, SETSTOPMODE, 0x0001, 2, ret );
00548 send_command_4_arg( MOTOR_1, SETVEL, 0, 2, ret );
00549 send_command_4_arg( MOTOR_1, SETACCEL, 0, 2, ret );
00550 send_command_4_arg( MOTOR_1, SETDECEL, 0, 2, ret );
00551 send_command( MOTOR_1, UPDATE, 2, ret );
00552 send_command( MOTOR_1, RESET, 2, ret );
00553 } else {
00554
00555 send_command_2_arg( MOTOR_0, RESETEVENTSTATUS, 0x0700, 2, ret );
00556 send_command_4_arg( MOTOR_0, SETVEL, 0, 2, ret );
00557 send_command( MOTOR_0, UPDATE, 2, ret );
00558 send_command( MOTOR_0, RESET, 2, ret );
00559
00560
00561 send_command_2_arg( MOTOR_1, RESETEVENTSTATUS, 0x0700, 2, ret );
00562 send_command_4_arg( MOTOR_1, SETVEL, 0, 2, ret );
00563 send_command( MOTOR_1, UPDATE, 2, ret );
00564 send_command( MOTOR_1, RESET, 2, ret );
00565 }
00566 }
00567
00569
00571
00572
00573
00574
00575
00576 int ER::GetOdom(int *ltics, int *rtics)
00577 {
00578
00579 unsigned char ret[6];
00580
00581
00582 send_command( MOTOR_0, GETCMDPOS, 6, ret );
00583 *ltics = _motor_0_dir * BytesToInt32(&(ret[2]));
00584
00585
00586 send_command( MOTOR_1, GETCMDPOS, 6, ret );
00587 *rtics = _motor_1_dir * BytesToInt32(&(ret[2]));
00588
00589
00590 if (_debug)
00591 {
00592 printf("lticks: %d, %2x %2x %2x %2x %2x %2x\n",
00593 *ltics, ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
00594 printf("rticks: %d, %2x %2x %2x %2x %2x %2x\n",
00595 *rtics, ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
00596 }
00597
00598
00599
00600
00601
00602
00603
00604 send_command( MOTOR_0, GETCMDPOS, 6, ret );
00605 *ltics = _motor_0_dir * BytesToInt32(&(ret[2]));
00606
00607
00608 send_command( MOTOR_1, GETCMDPOS, 6, ret );
00609 *rtics = _motor_1_dir * BytesToInt32(&(ret[2]));
00610
00611
00612 if (_debug)
00613 {
00614 printf("lticks: %d, %2x %2x %2x %2x %2x %2x\n",
00615 *ltics, ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
00616 printf("rticks: %d, %2x %2x %2x %2x %2x %2x\n",
00617 *rtics, ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
00618 }
00619
00620
00621 if( _debug )
00622 {
00623 printf("ltics: %d rtics: %d\n", *ltics, *rtics);
00624 }
00625
00626 return(0);
00627 }
00628
00629 int
00630 ER::GetBatteryVoltage(int* voltage)
00631 {
00632 unsigned char ret[4];
00633
00634 send_command_2_arg( MOTOR_1, READANALOG, 0x0001, 6, ret );
00635
00636 if( _debug )
00637 printf( "voltage?: %f\n", (float) BytesToFloat(&(ret[2])) );
00638
00639
00640
00641 return(0);
00642 }
00643
00644 int
00645 ER::GetRangeSensor(int s, float * val )
00646 {
00647 unsigned char ret[6];
00648
00649 send_command_2_arg( s / 8, READANALOG, s % 8, 6, ret );
00650
00651
00652 float range = (float) BytesToFloat( &(ret[2]) );
00653
00654 if( _debug )
00655 printf( "sensor value?: %d\n", s );
00656
00657 val = ⦥
00658
00659 return 0;
00660 }
00661
00662
00663
00664
00665
00666 int
00667 ER::SetVelocity(double lvel, double rvel)
00668 {
00669 lastlvel = lvel;
00670 lastrvel = rvel;
00671
00672 if (_debug)
00673 printf("Setting velocity to %f %f\n",lvel,rvel);
00674
00675 if (lvel != 0 || rvel != 0) {
00676 this->_powered = true;
00677 }
00678 this->_resting = false;
00679
00680
00681 static bool stopped = false;
00682 if ( (lvel == 0) && (rvel == 0) )
00683 {
00684
00685 if (stopped)
00686 {
00687
00688 return 0;
00689 }
00690
00691 stopped = true;
00692 } else {
00693
00694 stopped = false;
00695 }
00696
00697
00698
00699
00700 unsigned char ret[8];
00701 if( _debug )
00702 printf( "lvel: %f rvel: %f\n", lvel, rvel );
00703
00704
00705
00706 send_command( MOTOR_0, GETEVENTSTATUS, 4, ret );
00707
00708 if( _stopped )
00709 {
00710 send_command_2_arg( MOTOR_0, RESETEVENTSTATUS, 0x0300, 2, ret );
00711 send_command_2_arg( MOTOR_0, SETMOTORCMD, 0x6590, 2, ret );
00712 send_command_2_arg( MOTOR_0, SETPROFILEMODE, 0x0001, 2, ret );
00713 } else {
00714 send_command_2_arg( MOTOR_0, RESETEVENTSTATUS, 0x0700, 2, ret );
00715 }
00716
00717 SpeedCommand( MOTOR_0, lvel, _motor_0_dir );
00718
00719 send_command_4_arg( MOTOR_0, SETACCEL, 0x0000007E, 2, ret );
00720
00721
00722
00723 send_command( MOTOR_1, GETEVENTSTATUS, 4, ret );
00724
00725 if( _stopped )
00726 {
00727 send_command_2_arg( MOTOR_1, RESETEVENTSTATUS, 0x0300, 2, ret );
00728 send_command_2_arg( MOTOR_1, SETMOTORCMD, 0x6590, 2, ret );
00729 send_command_2_arg( MOTOR_1, SETPROFILEMODE, 0x0001, 2, ret );
00730 } else {
00731 send_command_2_arg( MOTOR_1, RESETEVENTSTATUS, 0x0700, 2, ret );
00732 }
00733
00734 SpeedCommand( MOTOR_1, rvel, _motor_1_dir );
00735 send_command_4_arg( MOTOR_1, SETACCEL, 0x0000007E, 2, ret );
00736
00737
00738 send_command( MOTOR_0, UPDATE, 2, ret );
00739 send_command( MOTOR_1, UPDATE, 2, ret );
00740
00741 _stopped = false;
00742 return 0;
00743 }
00744
00745
00746 void
00747 ER::Main()
00748 {
00749 player_position2d_data_t data;
00750 int rtics, ltics;
00751 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
00752
00753
00754 pthread_cleanup_push(StopRobot,this);
00755
00756 for(;;)
00757 {
00758 pthread_testcancel();
00759 ProcessMessages();
00760
00761
00762 GetOdom (<ics, &rtics);
00763 UpdateOdom (ltics, rtics);
00764
00765
00766 data.pos.px = this->_px;
00767 data.pos.py = this->_py;
00768 data.pos.pa = this->_pa;
00769
00770
00771 data.vel.px = (lastlvel + lastrvel) / 2.0;
00772 data.vel.py = 0;
00773 data.vel.pa = (lastrvel - lastlvel) / _axle_length;
00774
00775 data.stall = _stopped;
00776
00777 if (this->_powered || !this->_resting) {
00778 Publish(position_id, PLAYER_MSGTYPE_DATA, PLAYER_POSITION2D_DATA_STATE, &data, sizeof(data), NULL);
00779 if (!this->_powered) this->_resting = true;
00780 }
00781
00782 usleep (50000);
00783
00784 }
00785 pthread_cleanup_pop(1);
00786 }
00787
00789
00790 int ER::ProcessMessage(QueuePointer & resp_queue,
00791 player_msghdr * hdr,
00792 void * data)
00793 {
00794 assert(hdr);
00795 assert(data);
00796
00797 if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_GET_GEOM, position_id))
00798 {
00799 player_position2d_geom_t geom;
00800
00801
00802 geom.pose.px = -0.1;
00803 geom.pose.py = 0;
00804 geom.pose.pyaw = 0;
00805 geom.size.sw = 0.25;
00806 geom.size.sl = 0.425;
00807 Publish(position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION2D_REQ_GET_GEOM, &geom, sizeof(geom),NULL);
00808
00809 return 0;
00810 }
00811
00812 if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_MOTOR_POWER, position_id))
00813 {
00814 player_position2d_power_config_t * powercfg = reinterpret_cast<player_position2d_power_config_t *> (data);
00815
00816 printf("got motor power req: %d\n", powercfg->state);
00817 if(ChangeMotorState(powercfg->state) < 0)
00818 Publish(position_id, resp_queue, PLAYER_MSGTYPE_RESP_NACK, PLAYER_POSITION2D_REQ_MOTOR_POWER);
00819 else
00820 Publish(position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION2D_REQ_MOTOR_POWER);
00821 return 0;
00822 }
00823
00824 if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_SET_ODOM, position_id))
00825 {
00826 player_position2d_set_odom_req_t * odom = (player_position2d_set_odom_req_t *)data;
00827 this->_px = odom->pose.px;
00828 this->_py = odom->pose.py;
00829 this->_pa = odom->pose.pa;
00830 while (this->_pa > M_PI) this->_pa -= M_PI;
00831 while (this->_pa < -M_PI) this->_pa += M_PI;
00832 this->_resting = false;
00833 Publish (position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION2D_REQ_SET_ODOM);
00834 return 0;
00835 }
00836
00837 if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_RESET_ODOM, position_id))
00838 {
00839 this->_px = 0.0;
00840 this->_py = 0.0;
00841 this->_pa = 0.0;
00842 this->_resting = false;
00843 Publish (position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION2D_REQ_RESET_ODOM);
00844 return 0;
00845 }
00846
00847 if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, PLAYER_POSITION2D_CMD_VEL, position_id) ||
00848 Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, PLAYER_POSITION2D_CMD_CAR, position_id))
00849 {
00850 double velocity, angle;
00851 if (hdr->subtype == PLAYER_POSITION2D_CMD_VEL) {
00852 player_position2d_cmd_vel_t *position_cmd = (player_position2d_cmd_vel_t *)data;
00853 velocity = position_cmd->vel.px;
00854 angle = position_cmd->vel.pa;
00855 } else {
00856 player_position2d_cmd_car_t *carlike_cmd = (player_position2d_cmd_car_t *)data;
00857 velocity = carlike_cmd->velocity;
00858 angle = carlike_cmd->angle;
00859 }
00860
00861 double rotational_term;
00862 double command_rvel, command_lvel;
00863 double final_lvel = 0, final_rvel = 0;
00864 double last_final_lvel = 0, last_final_rvel = 0;
00865
00866
00867 rotational_term = angle * _axle_length / 2.0;
00868 command_rvel = velocity + rotational_term;
00869 command_lvel = velocity - rotational_term;
00870
00871
00872 if (fabs (command_lvel) > ER_MAX_WHEELSPEED) {
00873 command_rvel = command_rvel * ER_MAX_WHEELSPEED / fabs (command_lvel);
00874 command_lvel = command_lvel * ER_MAX_WHEELSPEED / fabs (command_lvel);
00875 }
00876 if (fabs (command_rvel) > ER_MAX_WHEELSPEED) {
00877 command_lvel = command_lvel * ER_MAX_WHEELSPEED / fabs (command_rvel);
00878 command_rvel = command_rvel * ER_MAX_WHEELSPEED / fabs (command_rvel);
00879 }
00880
00881 final_lvel = command_lvel;
00882 final_rvel = command_rvel;
00883
00884 if( _debug )
00885 printf( "final_lvel: %f, final_rvel: %f\n", final_lvel, final_rvel );
00886
00887 if ((final_lvel != last_final_lvel) || (final_rvel != last_final_rvel)) {
00888 if (final_lvel * last_final_lvel < 0 || final_rvel * last_final_rvel < 0) {
00889
00890 SetVelocity(0,0);
00891 }
00892 if (SetVelocity (final_lvel, final_rvel) < 0) {
00893 printf ("failed to set velocity\n");
00894 pthread_exit (NULL);
00895 }
00896 if (velocity == 0 && angle == 0)
00897 {
00898 if (_debug) printf ("STOP\n");
00899 Stop (STOP);
00900 }
00901
00902 last_final_lvel = final_lvel;
00903 last_final_rvel = final_rvel;
00904 MotorSpeed();
00905 }
00906
00907
00908 if( (velocity == 0) && (angle == 0) )
00909 {
00910
00911 SetVelocity(0,0);
00912 }
00913
00914 return 0;
00915 }
00916
00917 return -1;
00918 }
00919
00920
00921
00923
00925
00926 void
00927 ER::MotorSpeed()
00928 {
00929 unsigned char ret[8];
00930
00931 send_command( MOTOR_0, GETEVENTSTATUS, 4, ret );
00932 send_command_2_arg( MOTOR_0, RESETEVENTSTATUS, 0x0700, 2, ret );
00933 send_command_4_arg( MOTOR_0, SETACCEL, 0x0000007A, 2, ret );
00934 send_command( MOTOR_1, GETEVENTSTATUS, 4, ret );
00935 send_command_2_arg( MOTOR_1, RESETEVENTSTATUS, 0x0700, 2, ret );
00936 send_command_4_arg( MOTOR_1, SETACCEL, 0x0000007A, 2, ret );
00937
00938 send_command( MOTOR_0, UPDATE, 2, ret );
00939 send_command( MOTOR_1, UPDATE, 2, ret );
00940 }
00941
00942 void
00943 ER::SpeedCommand( unsigned char address, double speed, int dir ) {
00944
00945 unsigned char ret[2];
00946
00947 int whole = dir * (int) (speed / ER_M_PER_TICK);
00948
00949 send_command_4_arg( address, SETVEL, whole, 2, ret );
00950
00951
00952 }
00953
00954 int
00955 ER::BytesToInt32(unsigned char *ptr)
00956 {
00957 unsigned char char0,char1,char2,char3;
00958 int data = 0;
00959
00960 char0 = ptr[3];
00961 char1 = ptr[2];
00962 char2 = ptr[1];
00963 char3 = ptr[0];
00964
00965 data |= ((int)char0) & 0x000000FF;
00966 data |= (((int)char1) << 8) & 0x0000FF00;
00967 data |= (((int)char2) << 16) & 0x00FF0000;
00968 data |= (((int)char3) << 24) & 0xFF000000;
00969
00970
00971
00972 return data;
00973 }
00974
00975 float
00976 ER::BytesToFloat(unsigned char *ptr)
00977 {
00978 float res;
00979 int intermediate = BytesToInt32 (ptr);
00980 memcpy(&res,&intermediate,sizeof(res));
00981 return res;
00982 }
00983
00984 int
00985 ER::ComputeTickDiff(int from, int to)
00986 {
00987 int diff1, diff2;
00988
00989
00990 if(to > from)
00991 {
00992 diff1 = to - from;
00993 diff2 = (-ER_MAX_TICKS - from) + (to - ER_MAX_TICKS);
00994 }
00995 else
00996 {
00997 diff1 = to - from;
00998 diff2 = (from - ER_MAX_TICKS) + (-ER_MAX_TICKS - to);
00999 }
01000
01001 if(abs(diff1) < abs(diff2))
01002 return(diff1);
01003 else
01004 return(diff2);
01005
01006 return 0;
01007 }
01008
01009 void
01010 ER::UpdateOdom(int ltics, int rtics)
01011 {
01012 int ltics_delta, rtics_delta;
01013 double l_delta, r_delta, a_delta, d_delta;
01014 int max_tics;
01015 static struct timeval lasttime;
01016 struct timeval currtime;
01017 double timediff;
01018
01019 if(!this->_odom_initialized)
01020 {
01021 this->_last_ltics = ltics;
01022 this->_last_rtics = rtics;
01023 gettimeofday(&lasttime,NULL);
01024 this->_odom_initialized = true;
01025 return;
01026 }
01027
01028
01029
01030 ltics_delta = ltics - this->_last_ltics;
01031 rtics_delta = rtics - this->_last_rtics;
01032
01033 gettimeofday(&currtime,NULL);
01034 timediff = (currtime.tv_sec + currtime.tv_usec/1e6) - (lasttime.tv_sec + lasttime.tv_usec/1e6);
01035 max_tics = (int)rint(ER_MAX_WHEELSPEED / ER_M_PER_TICK / timediff);
01036 lasttime = currtime;
01037
01038 if( _debug ) {
01039 printf("ltics: %d\trtics: %d\n", ltics,rtics);
01040 printf("ldelt: %d\trdelt: %d\n", ltics_delta, rtics_delta);
01041 }
01042
01043 l_delta = ltics_delta * ER_M_PER_TICK;
01044 r_delta = rtics_delta * ER_M_PER_TICK;
01045
01046 a_delta = (r_delta - l_delta) / _axle_length;
01047 d_delta = (l_delta + r_delta) / 2.0;
01048
01049 this->_px += d_delta * cos(this->_pa + (a_delta / 2));
01050 this->_py += d_delta * sin(this->_pa + (a_delta / 2));
01051 this->_pa += a_delta;
01052 while (this->_pa > M_PI) this->_pa -= 2*M_PI;
01053 while (this->_pa < -M_PI) this->_pa += 2*M_PI;
01054
01055 if( _debug ) {
01056 printf("er: pose: %f,%f,%f\n", this->_px,this->_py,this->_pa);
01057 }
01058 this->_last_ltics = ltics;
01059 this->_last_rtics = rtics;
01060 }
01061
01062
01063 int
01064 ER::ChangeMotorState(int state)
01065 {
01066 if (!state) {
01067 SetVelocity (0, 0);
01068 this->_powered = false;
01069 } else {
01070 this->_powered = true;
01071 }
01072 return 0;
01073 }
01074
01075 static void
01076 StopRobot(void* erdev)
01077 {
01078 ER* er = (ER*)erdev;
01079
01080 er->Stop (FULL_STOP);
01081 }
01082