00001
00002
00171
00172 #include <pthread.h>
00173
00174 #include <fcntl.h>
00175 #include <stdio.h>
00176 #include <unistd.h>
00177 #include <math.h>
00178 #include <termios.h>
00179 #include <stdlib.h>
00180
00181 #include "erratic.h"
00182
00183 #ifdef HAVE_CONFIG_H
00184 #include "config.h"
00185 #endif
00186
00187 bool debug_mode = FALSE;
00188
00189
00190
00193
00194 Driver* Erratic_Init(ConfigFile* cf, int section)
00195 {
00196 return (Driver*)(new Erratic(cf,section));
00197 }
00198
00199 void Erratic_Register(DriverTable* table)
00200 {
00201 table->AddDriver("erratic", Erratic_Init);
00202 }
00203
00204 #if 0
00205 extern "C" {
00206 int player_driver_init(DriverTable* table)
00207 {
00208 Erratic_Register(table);
00209 #define QUOTEME(x) #x
00210
00211 printf(" Erratic robot driver %s, build date %s\n", ERRATIC_VERSION, ERRATIC_DATE);
00212 return 0;
00213 }
00214 }
00215 #endif
00216
00217
00218 Erratic::Erratic(ConfigFile* cf, int section)
00219 : Driver(cf,section,true,PLAYER_MSGQUEUE_DEFAULT_MAXLEN)
00220 {
00221
00222 memset(&this->position_id, 0, sizeof(player_devaddr_t));
00223 memset(&this->power_id, 0, sizeof(player_devaddr_t));
00224 memset(&this->aio_id, 0, sizeof(player_devaddr_t));
00225 memset(&this->sonar_id, 0, sizeof(player_devaddr_t));
00226 memset(&this->ptz_id, 0, sizeof(player_devaddr_t));
00227 memset(&this->ptz2_id, 0, sizeof(player_devaddr_t));
00228
00229 memset(&this->last_position_cmd, 0, sizeof(player_position2d_cmd_vel_t));
00230 memset(&this->last_car_cmd, 0, sizeof(player_position2d_cmd_car_t));
00231
00232 this->position_subscriptions = 0;
00233 this->aio_ir_subscriptions = 0;
00234 this->sonar_subscriptions = 0;
00235 this->ptz_subscriptions = 0;
00236 this->ptz2_subscriptions = 0;
00237
00238
00239 motor_packet = NULL;
00240 mcount = 0;
00241 memset(&this->erratic_data,0,sizeof(this->erratic_data));
00242
00243
00244 if(cf->ReadDeviceAddr(&(this->position_id), section, "provides", PLAYER_POSITION2D_CODE, -1, NULL) == 0) {
00245 if(this->AddInterface(this->position_id) != 0) {
00246 this->SetError(-1);
00247 return;
00248 }
00249 }
00250
00251
00252 if(cf->ReadDeviceAddr(&(this->power_id), section, "provides", PLAYER_POWER_CODE, -1, NULL) == 0) {
00253 if(this->AddInterface(this->power_id) != 0) {
00254 this->SetError(-1);
00255 return;
00256 }
00257 }
00258
00259
00260 if(cf->ReadDeviceAddr(&(this->aio_id), section, "provides", PLAYER_AIO_CODE, -1, NULL) == 0) {
00261 if(this->AddInterface(this->aio_id) != 0) {
00262 this->SetError(-1);
00263 return;
00264 }
00265 }
00266
00267
00268 if(cf->ReadDeviceAddr(&(this->ir_id), section, "provides", PLAYER_IR_CODE, -1, NULL) == 0) {
00269 if(this->AddInterface(this->ir_id) != 0) {
00270 this->SetError(-1);
00271 return;
00272 }
00273 }
00274
00275
00276 if(cf->ReadDeviceAddr(&(this->sonar_id), section, "provides", PLAYER_SONAR_CODE, -1, NULL) == 0) {
00277 if(this->AddInterface(this->sonar_id) != 0) {
00278 this->SetError(-1);
00279 return;
00280 }
00281 }
00282
00283
00284
00285
00286 if(cf->ReadDeviceAddr(&(this->ptz2_id), section, "provides", PLAYER_PTZ_CODE, -1, "tilt") == 0) {
00287 if(this->AddInterface(this->ptz2_id) != 0) {
00288 this->SetError(-1);
00289 return;
00290 }
00291 }
00292
00293
00294
00295
00296 if(cf->ReadDeviceAddr(&(this->ptz_id), section, "provides", PLAYER_PTZ_CODE, -1, NULL) == 0) {
00297 if(this->AddInterface(this->ptz_id) != 0) {
00298 this->SetError(-1);
00299 return;
00300 }
00301 }
00302
00303
00304 initialize_robot_params();
00305
00306
00307 this->psos_serial_port = cf->ReadString(section,"port",DEFAULT_VIDERE_PORT);
00308 this->direct_wheel_vel_control = cf->ReadInt(section, "direct_wheel_vel_control", 0);
00309 this->motor_max_speed = (int)rint(1e3 * cf->ReadLength(section, "max_trans_vel", MOTOR_DEF_MAX_SPEED));
00310 this->motor_max_turnspeed = (int)rint(RTOD(cf->ReadAngle(section, "max_rot_vel", MOTOR_DEF_MAX_TURNSPEED)));
00311 this->motor_max_trans_accel = (short)rint(1.0e3 * cf->ReadLength(section, "trans_acc", 0));
00312 this->motor_max_trans_decel = (short)rint(1.0e3 * cf->ReadLength(section, "trans_decel", 0));
00313 this->motor_max_rot_accel = (short)rint(RTOD(cf->ReadAngle(section, "rot_acc", 0)));
00314 this->motor_max_rot_decel = (short)rint(RTOD(cf->ReadAngle(section, "rot_decel", 0)));
00315
00316 this->pid_trans_p = cf->ReadInt(section, "pid_trans_p", -1);
00317 this->pid_trans_v = cf->ReadInt(section, "pid_trans_v", -1);
00318 this->pid_trans_i = cf->ReadInt(section, "pid_trans_i", -1);
00319 this->pid_rot_p = cf->ReadInt(section, "pid_rot_p", -1);
00320 this->pid_rot_v = cf->ReadInt(section, "pid_rot_v", -1);
00321 this->pid_rot_i = cf->ReadInt(section, "pid_rot_i", -1);
00322
00323 this->motor_pwm_frequency = cf->ReadInt(section, "motor_pwm_frequency", -1);
00324 this->motor_pwm_max_on = (uint16_t)(cf->ReadFloat(section, "motor_pwm_max_on", -1) * 1000.0);
00325
00326 this->use_vel_band = 0;
00327
00328 this->print_all_packets = 0;
00329 this->print_status_summary = 1;
00330
00331 debug_mode = cf->ReadInt(section, "debug", 0);
00332 save_settings_in_robot = cf->ReadInt(section, "save_settings_in_robot", 0);
00333
00334 this->read_fd = -1;
00335 this->write_fd = -1;
00336
00337
00338 pthread_mutex_init(&send_queue_mutex, 0);
00339 pthread_cond_init(&send_queue_cond, 0);
00340 pthread_mutex_init(&motor_packet_mutex, 0);
00341
00342 if (Connect())
00343 {
00344 printf("Error connecting to Erratic robot\n");
00345 exit(1);
00346 }
00347 }
00348
00349
00350 int Erratic::Setup() {
00351
00352 return 0;
00353 }
00354
00355
00356 int Erratic::Connect()
00357 {
00358 printf(" Erratic connection initializing (%s)...",this->psos_serial_port); fflush(stdout);
00359
00360
00361 if ((this->read_fd = open(this->psos_serial_port, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) {
00362 perror("Erratic::Setup():open():");
00363 return(1);
00364 };
00365 if ((this->write_fd = open(this->psos_serial_port, O_WRONLY, S_IRUSR | S_IWUSR)) < 0) {
00366 perror("Erratic::Setup():open():");
00367 close(this->read_fd); this->read_fd = -1;
00368 return(1);
00369 }
00370
00371
00372 int bauds[] = {B38400, B115200};
00373 int numbauds = sizeof(bauds), currbaud = 0;
00374 struct termios read_term, write_term;
00375 {
00376 if(tcgetattr( this->read_fd, &read_term ) < 0 ) {
00377 perror("Erratic::Setup():tcgetattr():");
00378 close(this->read_fd); close(this->write_fd);
00379 this->read_fd = -1; this->write_fd = -1;
00380 return(1);
00381 }
00382
00383 cfmakeraw(&read_term);
00384
00385 cfsetispeed(&read_term, bauds[currbaud]);
00386 cfsetospeed(&read_term, bauds[currbaud]);
00387
00388 if(tcsetattr(this->read_fd, TCSAFLUSH, &read_term ) < 0) {
00389 perror("Erratic::Setup():tcsetattr(read channel):");
00390 close(this->read_fd); close(this->write_fd);
00391 this->read_fd = -1; this->write_fd = -1;
00392 return(1);
00393 }
00394 }
00395
00396
00397
00398 if (tcflush(this->read_fd, TCIOFLUSH ) < 0) {
00399 perror("Erratic::Setup():tcflush():");
00400 close(this->read_fd); close(this->write_fd);
00401 this->read_fd = -1; this->write_fd = -1;
00402 return(1);
00403 }
00404 if (tcflush(this->write_fd, TCIOFLUSH ) < 0) {
00405 perror("Erratic::Setup():tcflush():");
00406 close(this->read_fd); close(this->write_fd);
00407 this->read_fd = -1; this->write_fd = -1;
00408 return(1);
00409 }
00410
00411
00412 int num_sync_attempts = 10;
00413 int num_patience = 200;
00414 int failed = 0;
00415 enum { NO_SYNC, AFTER_FIRST_SYNC, AFTER_SECOND_SYNC, READY } communication_state = NO_SYNC;
00416 ErraticPacket received_packet;
00417 while(communication_state != READY && num_patience-- > 0) {
00418
00419 if (num_patience % 5 == 0) {
00420 ErraticPacket packet;
00421 unsigned char command = (command_e)configuration;
00422 packet.Build(&command, 1);
00423 packet.Send(this->write_fd);
00424 }
00425
00426
00427 uint8_t receive_error;
00428 if((receive_error = received_packet.Receive(this->read_fd))) {
00429 if (receive_error == (receive_result_e)failure)
00430 printf("Error receiving\n");
00431
00432 if((communication_state == NO_SYNC) && (num_sync_attempts >= 0)) {
00433 num_sync_attempts--;
00434 usleep(ROBOT_CYCLETIME);
00435 continue;
00436 }
00437
00438 else {
00439
00440 if(++currbaud < numbauds) {
00441
00442 cfsetispeed(&read_term, bauds[currbaud]);
00443 cfsetospeed(&write_term, bauds[currbaud]);
00444 if( tcsetattr(this->read_fd, TCSAFLUSH, &read_term ) < 0 ) {
00445 perror("Erratic::Setup():tcsetattr():");
00446 close(this->read_fd); close(this->write_fd);
00447 this->read_fd = -1; this->write_fd = -1;
00448 return(1);
00449 }
00450 if( tcsetattr(this->write_fd, TCSAFLUSH, &write_term ) < 0 ) {
00451 perror("Erratic::Setup():tcsetattr():");
00452 close(this->read_fd); close(this->write_fd);
00453 this->read_fd = -1; this->write_fd = -1;
00454 return(1);
00455 }
00456
00457
00458 if(tcflush(this->read_fd, TCIOFLUSH ) < 0 ) {
00459 perror("Erratic::Setup():tcflush():");
00460 close(this->read_fd); close(this->write_fd);
00461 this->read_fd = -1; this->write_fd = -1;
00462 return(1);
00463 }
00464 if(tcflush(this->write_fd, TCIOFLUSH ) < 0 ) {
00465 perror("Erratic::Setup():tcflush():");
00466 close(this->read_fd); close(this->write_fd);
00467 this->read_fd = -1; this->write_fd = -1;
00468 return(1);
00469 }
00470
00471
00472 num_sync_attempts = 10;
00473 continue;
00474 }
00475
00476 else failed = 1;
00477 }
00478 }
00479
00480
00481 if (failed) break;
00482
00483
00484 if (received_packet.packet[3] == 0x20) communication_state = READY;
00485
00486 usleep(ROBOT_CYCLETIME);
00487 }
00488
00489 if(failed) {
00490 printf(" Couldn't synchronize with Erratic robot.\n");
00491 printf(" Most likely because the robot is not connected to %s\n", this->psos_serial_port);
00492 close(this->read_fd); close(this->write_fd);
00493 this->read_fd = -1; this->write_fd = -1;
00494 return(1);
00495 }
00496 else if (communication_state != READY) {
00497 printf(" Couldn't synchronize with Erratic robot.\n");
00498 printf(" We heard something though. Is the sending part of the cable dead?\n");
00499 close(this->read_fd); close(this->write_fd);
00500 this->read_fd = -1; this->write_fd = -1;
00501 return(1);
00502 }
00503
00504 char name[20], type[20], subtype[20];
00505 sprintf(name, "%s", &received_packet.packet[5]);
00506 sprintf(type, "%s", &received_packet.packet[25]);
00507 sprintf(subtype, "%s", &received_packet.packet[45]);
00508
00509
00510 {
00511 ErraticPacket packet;
00512
00513 unsigned char command = (command_e)open_controller;
00514 packet.Build(&command, 1);
00515 packet.Send(this->write_fd);
00516 usleep(ROBOT_CYCLETIME);
00517
00518 command = (command_e)pulse;
00519 packet.Build(&command, 1);
00520 packet.Send(this->write_fd);
00521 usleep(ROBOT_CYCLETIME);
00522 }
00523
00524 printf(" done.\n Connected to <%s>, an %s %s\n", name, type, subtype);
00525
00526
00527 if (strcmp(subtype,"Rev H")==0)
00528 param_idx = 2;
00529 else if (strcmp(subtype,"Rev G")==0)
00530 param_idx = 1;
00531 else if (strcmp(subtype,"Rev E")==0)
00532 param_idx = 0;
00533 else
00534 param_idx = 0;
00535
00536
00537 this->motor_packet = new ErraticMotorPacket(param_idx);
00538 this->motor_packet->x_offset = 0;
00539 this->motor_packet->y_offset = 0;
00540 this->motor_packet->angle_offset = 0;
00541
00542
00543 {
00544 ErraticPacket *accel_packet;
00545 unsigned char accel_command[4];
00546 if(this->motor_max_trans_accel != 0) {
00547 accel_packet = new ErraticPacket();
00548 accel_command[0] = (command_e)set_max_trans_acc;
00549 accel_command[1] = (argtype_e)argint;
00550 accel_command[2] = this->motor_max_trans_accel & 0x00FF;
00551 accel_command[3] = (this->motor_max_trans_accel & 0xFF00) >> 8;
00552 accel_packet->Build(accel_command, 4);
00553 this->Send(accel_packet);
00554 }
00555 if(this->motor_max_trans_decel != 0) {
00556 accel_packet = new ErraticPacket();
00557 accel_command[0] = (command_e)set_max_trans_acc;
00558 accel_command[1] = (argtype_e)argnint;
00559 accel_command[2] = abs(this->motor_max_trans_decel) & 0x00FF;
00560 accel_command[3] = (abs(this->motor_max_trans_decel) & 0xFF00) >> 8;
00561 accel_packet->Build(accel_command, 4);
00562 this->Send(accel_packet);
00563 } else if(this->motor_max_trans_accel != 0) {
00564 accel_packet = new ErraticPacket();
00565 accel_command[0] = (command_e)set_max_trans_acc;
00566 accel_command[1] = (argtype_e)argnint;
00567 accel_command[2] = this->motor_max_trans_accel & 0x00FF;
00568 accel_command[3] = (this->motor_max_trans_accel & 0xFF00) >> 8;
00569 accel_packet->Build(accel_command, 4);
00570 this->Send(accel_packet);
00571 }
00572
00573 if(this->motor_max_rot_accel != 0) {
00574 accel_packet = new ErraticPacket();
00575 accel_command[0] = (command_e)set_max_rot_acc;
00576 accel_command[1] = (argtype_e)argint;
00577 accel_command[2] = this->motor_max_rot_accel & 0x00FF;
00578 accel_command[3] = (this->motor_max_rot_accel & 0xFF00) >> 8;
00579 accel_packet->Build(accel_command, 4);
00580 this->Send(accel_packet);
00581 }
00582 if(this->motor_max_rot_decel != 0) {
00583 accel_packet = new ErraticPacket();
00584 accel_command[0] = (command_e)set_max_rot_acc;
00585 accel_command[1] = (argtype_e)argnint;
00586 accel_command[2] = abs(this->motor_max_rot_decel) & 0x00FF;
00587 accel_command[3] = (abs(this->motor_max_rot_decel) & 0xFF00) >> 8;
00588 accel_packet->Build(accel_command, 4);
00589 this->Send(accel_packet);
00590 } else if(this->motor_max_rot_accel != 0) {
00591 accel_packet = new ErraticPacket();
00592 accel_command[0] = (command_e)set_max_rot_acc;
00593 accel_command[1] = (argtype_e)argnint;
00594 accel_command[2] = this->motor_max_rot_accel & 0x00FF;
00595 accel_command[3] = (this->motor_max_rot_accel & 0xFF00) >> 8;
00596 accel_packet->Build(accel_command, 4);
00597 this->Send(accel_packet);
00598 }
00599 }
00600
00601 {
00602 ErraticPacket *packet;
00603 unsigned char payload[4];
00604
00605
00606 if(this->pid_trans_p >= 0) {
00607 packet = new ErraticPacket();
00608 payload[0] = (command_e)set_pid_trans_p;
00609 payload[1] = (argtype_e)argint;
00610 payload[2] = this->pid_trans_p & 0x00FF;
00611 payload[3] = (this->pid_trans_p & 0xFF00) >> 8;
00612 packet->Build(payload, 4);
00613 this->Send(packet);
00614 }
00615 if(this->pid_trans_v >= 0) {
00616 packet = new ErraticPacket();
00617 payload[0] = (command_e)set_pid_trans_v;
00618 payload[1] = (argtype_e)argint;
00619 payload[2] = this->pid_trans_v & 0x00FF;
00620 payload[3] = (this->pid_trans_v & 0xFF00) >> 8;
00621 packet->Build(payload, 4);
00622 this->Send(packet);
00623 }
00624 if(this->pid_trans_i >= 0) {
00625 packet = new ErraticPacket();
00626 payload[0] = (command_e)set_pid_trans_i;
00627 payload[1] = (argtype_e)argint;
00628 payload[2] = this->pid_trans_i & 0x00FF;
00629 payload[3] = (this->pid_trans_i & 0xFF00) >> 8;
00630 packet->Build(payload, 4);
00631 this->Send(packet);
00632 }
00633 if(this->pid_rot_p >= 0) {
00634 packet = new ErraticPacket();
00635 payload[0] = (command_e)set_pid_rot_p;
00636 payload[1] = (argtype_e)argint;
00637 payload[2] = this->pid_rot_p & 0x00FF;
00638 payload[3] = (this->pid_rot_p & 0xFF00) >> 8;
00639 packet->Build(payload, 4);
00640 this->Send(packet);
00641 }
00642 if(this->pid_rot_v >= 0) {
00643 packet = new ErraticPacket();
00644 payload[0] = (command_e)set_pid_rot_v;
00645 payload[1] = (argtype_e)argint;
00646 payload[2] = this->pid_rot_v & 0x00FF;
00647 payload[3] = (this->pid_rot_v & 0xFF00) >> 8;
00648 packet->Build(payload, 4);
00649 this->Send(packet);
00650 }
00651 if(this->pid_rot_i >= 0) {
00652 packet = new ErraticPacket();
00653 payload[0] = (command_e)set_pid_rot_i;
00654 payload[1] = (argtype_e)argint;
00655 payload[2] = this->pid_rot_i & 0x00FF;
00656 payload[3] = (this->pid_rot_i & 0xFF00) >> 8;
00657 packet->Build(payload, 4);
00658 this->Send(packet);
00659 }
00660
00661
00662 if (this->motor_pwm_frequency > 0) {
00663 packet = new ErraticPacket();
00664 payload[0] = (command_e)set_pwm_freq;
00665 payload[1] = (argtype_e)argint;
00666 payload[2] = this->motor_pwm_frequency & 0x00FF;
00667 payload[3] = (this->motor_pwm_frequency & 0xFF00) >> 8;
00668 packet->Build(payload, 4);
00669 this->Send(packet);
00670 }
00671 if (this->motor_pwm_max_on > 0) {
00672 packet = new ErraticPacket();
00673 payload[0] = (command_e)set_pwm_max_on;
00674 payload[1] = (argtype_e)argint;
00675 payload[2] = this->motor_pwm_max_on & 0x00FF;
00676 payload[3] = (this->motor_pwm_max_on & 0xFF00) >> 8;
00677 packet->Build(payload, 4);
00678 this->Send(packet);
00679 }
00680
00681
00682 if (save_settings_in_robot) {
00683 packet = new ErraticPacket();
00684 payload[0] = (command_e)save_config;
00685 payload[1] = 0;
00686 payload[2] = 0;
00687 payload[3] = 0;
00688 packet->Build(payload, 4);
00689 this->Send(packet);
00690 }
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 ((Erratic*)this)->StartThreads();
00704 return(0);
00705 }
00706
00707
00708 int Erratic::Shutdown() {
00709
00710
00711 this->Disconnect();
00712 return 0;
00713 }
00714
00715
00716 int Erratic::Disconnect() {
00717 printf("Shutting Erratic driver down\n");
00718
00719 this->StopThreads();
00720
00721
00722 if (this->write_fd > -1) {
00723 unsigned char command[20],buffer[20];
00724 ErraticPacket packet;
00725
00726 memset(buffer,0,20);
00727
00728 command[0] = (command_e)stop;
00729 packet.Build(command, 1);
00730 packet.Send(this->write_fd);
00731 usleep(ROBOT_CYCLETIME);
00732
00733 command[0] = (command_e)close_controller;
00734 packet.Build(command, 1);
00735 packet.Send(this->write_fd);
00736 usleep(ROBOT_CYCLETIME);
00737
00738 close(this->write_fd);
00739 this->write_fd = -1;
00740 }
00741 if (this->read_fd > -1) {
00742 close(this->read_fd);
00743 this->read_fd = -1;
00744 }
00745
00746 if (this->motor_packet) {
00747 delete this->motor_packet;
00748 this->motor_packet = NULL;
00749 }
00750
00751 printf("Erratic has been shut down");
00752
00753 return(0);
00754 }
00755
00756
00757 void Erratic::StartThreads() {
00758 StartThread();
00759 pthread_create(&send_thread, 0, &SendThreadDummy, this);
00760 pthread_create(&receive_thread, 0, &ReceiveThreadDummy, this);
00761 }
00762 void Erratic::StopThreads() {
00763 pthread_cancel(send_thread);
00764 pthread_cancel(receive_thread);
00765
00766
00767 StopThread();
00768
00769
00770 pthread_mutex_trylock(&send_queue_mutex);
00771 pthread_mutex_unlock(&send_queue_mutex);
00772
00773 pthread_mutex_trylock(&motor_packet_mutex);
00774 pthread_mutex_unlock(&motor_packet_mutex);
00775 }
00776
00777
00778 int Erratic::Subscribe(player_devaddr_t id) {
00779 int setupResult;
00780
00781
00782 if((setupResult = Driver::Subscribe(id)) == 0)
00783 {
00784
00785
00786 if(Device::MatchDeviceAddress(id, this->position_id))
00787 this->position_subscriptions++;
00788
00789 if(Device::MatchDeviceAddress(id, this->aio_id))
00790 this->aio_ir_subscriptions++;
00791
00792 if(Device::MatchDeviceAddress(id, this->ir_id))
00793 this->aio_ir_subscriptions++;
00794
00795 if(Device::MatchDeviceAddress(id, this->sonar_id))
00796 this->sonar_subscriptions++;
00797
00798 if(Device::MatchDeviceAddress(id, this->ptz_id))
00799 this->ptz_subscriptions++;
00800
00801 if(Device::MatchDeviceAddress(id, this->ptz2_id))
00802 this->ptz2_subscriptions++;
00803 }
00804
00805 return(setupResult);
00806 }
00807 int Erratic::Unsubscribe(player_devaddr_t id) {
00808 int shutdownResult;
00809
00810
00811 if((shutdownResult = Driver::Unsubscribe(id)) == 0)
00812 {
00813
00814 if(Device::MatchDeviceAddress(id, this->position_id))
00815 {
00816 this->position_subscriptions--;
00817 assert(this->position_subscriptions >= 0);
00818 }
00819
00820 if(Device::MatchDeviceAddress(id, this->aio_id))
00821 this->aio_ir_subscriptions--;
00822
00823 if(Device::MatchDeviceAddress(id, this->ir_id))
00824 this->aio_ir_subscriptions--;
00825
00826 if(Device::MatchDeviceAddress(id, this->sonar_id))
00827 this->sonar_subscriptions--;
00828
00829 if(Device::MatchDeviceAddress(id, this->ptz_id))
00830 this->ptz_subscriptions--;
00831
00832 if(Device::MatchDeviceAddress(id, this->ptz2_id))
00833 this->ptz2_subscriptions--;
00834
00835 }
00836
00837 return(shutdownResult);
00838 }
00839
00840
00841
00842
00845
00846 void Erratic::ReceiveThread()
00847 {
00848 for (;;) {
00849 pthread_testcancel();
00850
00851
00852
00853 ErraticPacket packet;
00854 uint32_t waited = 0;
00855 uint8_t error_code;
00856 while ((error_code = packet.Receive(this->read_fd, 5000))) {
00857 waited += 5;
00858 printf("Lost serial communication with Erratic (%d) - no data received for %i seconds\n", error_code, waited);
00859 }
00860
00861 if (waited)
00862 printf("Connection re-established\n");
00863
00864
00865 if (print_all_packets) {
00866 printf("Got: ");
00867 packet.PrintHex();
00868 }
00869
00870
00871
00872
00873 int count, maxcount;
00874 switch(packet.packet[3])
00875 {
00876 case (reply_e)motor:
00877 case (reply_e)motor+2:
00878 case (reply_e)motor+3:
00879 if (motor_packet->Parse(&packet.packet[3], packet.size-3)) {
00880 motor_packet->Fill(&erratic_data);
00881 PublishPosition2D();
00882 PublishPower();
00883 }
00884 break;
00885
00886 case (reply_e)config:
00887 break;
00888
00889 case (reply_e)ain:
00890
00891 if(erratic_data.aio.voltages_count != (unsigned int)(packet.packet[4]+4))
00892 {
00893 erratic_data.aio.voltages_count = packet.packet[4]+4;
00894 if(erratic_data.aio.voltages)
00895 delete[] erratic_data.aio.voltages;
00896 erratic_data.aio.voltages = new float[erratic_data.aio.voltages_count];
00897 }
00898 if(erratic_data.ir.voltages_count !=
00899 (unsigned int)RobotParams[this->param_idx]->NumIR)
00900 {
00901 erratic_data.ir.voltages_count = RobotParams[this->param_idx]->NumIR;
00902 if(erratic_data.ir.voltages)
00903 delete[] erratic_data.ir.voltages;
00904 erratic_data.ir.voltages = new float[erratic_data.ir.voltages_count];
00905 }
00906 if(erratic_data.ir.ranges_count !=
00907 (unsigned int)RobotParams[this->param_idx]->NumIR)
00908 {
00909 erratic_data.ir.ranges_count = RobotParams[this->param_idx]->NumIR;
00910 if(erratic_data.ir.ranges)
00911 delete[] erratic_data.ir.ranges;
00912 erratic_data.ir.ranges = new float[erratic_data.ir.ranges_count];
00913 }
00914 unsigned int i_voltage;
00915 for (i_voltage = 0; i_voltage < erratic_data.aio.voltages_count ;i_voltage++)
00916 {
00917 erratic_data.aio.voltages[i_voltage] = (packet.packet[5+i_voltage*2]
00918 + 256*packet.packet[6+i_voltage*2]) * (1.0 / 1024.0) * CPU_VOLTAGE;
00919 erratic_data.ir.voltages[i_voltage] = (packet.packet[5+i_voltage*2]
00920 + 256*packet.packet[6+i_voltage*2]) * (1.0 / 1024.0) * CPU_VOLTAGE;
00921
00922 }
00923
00924
00925 for (int i=0; i < 4; i++)
00926 {
00927 erratic_data.aio.voltages[i_voltage+i] =
00928 (packet.packet[5+i_voltage*2] & (0x1 << i+4)) ? 1.0 : 0.0;
00929 erratic_data.ir.voltages[i] =
00930 (packet.packet[5+i_voltage*2] & (0x1 << i+4)) ? 1.0 : 0.0;
00931 erratic_data.ir.ranges[i] =
00932 IRFloorRange(erratic_data.ir.voltages[i]);
00933 }
00934
00935
00936
00937 PublishAIn();
00938 PublishIR();
00939 break;
00940
00941 case (reply_e)sonar:
00942
00943 maxcount = RobotParams[this->param_idx]->NumSonars;
00944 count = packet.packet[4];
00945 if(erratic_data.sonar.ranges_count != (unsigned int)maxcount)
00946 {
00947 erratic_data.sonar.ranges_count = maxcount;
00948 if(erratic_data.sonar.ranges)
00949 delete[] erratic_data.sonar.ranges;
00950 erratic_data.sonar.ranges = new float[erratic_data.sonar.ranges_count];
00951 }
00952 for (int i = 0; i < count; i++)
00953 {
00954 int ch = packet.packet[5+i*3];
00955 if (ch >= maxcount)
00956 continue;
00957 erratic_data.sonar.ranges[ch] = .001 * (double)(packet.packet[6+i*3]
00958 + 256*packet.packet[7+i*3]);
00959
00960 }
00961
00962 PublishSonar();
00963 break;
00964
00965 case (reply_e)debug:
00966 if (debug_mode) {
00967 printf("Debug message: ");
00968 for (uint8_t i = 3; i < packet.size-2 ;i++)
00969 printf("%c", packet.packet[i]);
00970 printf("\n");
00971 }
00972 break;
00973
00974 default:
00975 if (debug_mode) {
00976 printf("Unrecognized packet: ");
00977 packet.Print();
00978 }
00979 }
00980
00981
00982 }
00983 }
00984
00985 void* Erratic::ReceiveThreadDummy(void *driver) {
00986 ((Erratic*)driver)->ReceiveThread();
00987 return 0;
00988 }
00989
00990
00991 void Erratic::SendThread() {
00992 for (;;) {
00993 pthread_testcancel();
00994
00995
00996 pthread_mutex_lock(&send_queue_mutex);
00997
00998
00999 if (!send_queue.size())
01000 pthread_cond_wait(&send_queue_cond, &send_queue_mutex);
01001
01002
01003 ErraticPacket *packet = 0;
01004 if (send_queue.size()) {
01005 packet = send_queue.front();
01006 send_queue.pop();
01007 }
01008 pthread_mutex_unlock(&send_queue_mutex);
01009
01010
01011 if (packet) {
01012 if (print_all_packets) {
01013 printf("Just about to send: ");
01014 packet->Print();
01015 }
01016 packet->Send(this->write_fd);
01017
01018
01019
01020
01021 usleep(15000);
01022 }
01023 delete(packet);
01024 }
01025 }
01026 void* Erratic::SendThreadDummy(void *driver) {
01027 ((Erratic*)driver)->SendThread();
01028 return 0;
01029 }
01030
01031
01032 void Erratic::Send(ErraticPacket *packet) {
01033 pthread_mutex_lock(&send_queue_mutex); {
01034 send_queue.push(packet);
01035 pthread_cond_signal(&send_queue_cond);
01036 } pthread_mutex_unlock(&send_queue_mutex);
01037 }
01038
01039
01040
01041 void Erratic::ResetRawPositions() {
01042 ErraticPacket *pkt;
01043 unsigned char erraticcommand[4];
01044
01045
01046
01047
01048 if(this->motor_packet) {
01049 pkt = new ErraticPacket();
01050
01051
01052
01053 this->motor_packet->xpos = 0;
01054 this->motor_packet->ypos = 0;
01055 this->motor_packet->x_offset = 0;
01056 this->motor_packet->y_offset = 0;
01057 this->motor_packet->angle_offset = 0;
01058 erraticcommand[0] = (command_e)reset_origo;
01059 erraticcommand[1] = (argtype_e)argint;
01060
01061
01062
01063
01064 }
01065 }
01066
01067
01068 void Erratic::ToggleMotorPower(unsigned char val) {
01069 unsigned char command[4];
01070 ErraticPacket *packet = new ErraticPacket();
01071
01072 command[0] = (command_e)enable_motors;
01073 command[1] = (argtype_e)argint;
01074 command[2] = val;
01075 command[3] = 0;
01076 packet->Build(command, 4);
01077
01078 Send(packet);
01079 }
01080
01081
01082 void Erratic::ToggleAIn(unsigned char val)
01083 {
01084 unsigned char command[4];
01085 ErraticPacket *packet = new ErraticPacket();
01086
01087 command[0] = (command_e)set_analog;
01088 command[1] = (argtype_e)argint;
01089 command[2] = val ? 1 : 0;
01090 command[3] = 0;
01091 packet->Build(command, 4);
01092
01093 Send(packet);
01094 }
01095
01096
01097 void Erratic::ToggleSonar(unsigned char val)
01098 {
01099 unsigned char command[4];
01100 ErraticPacket *packet = new ErraticPacket();
01101
01102 command[0] = (command_e)set_sonar;
01103 command[1] = (argtype_e)argint;
01104 command[2] = val ? 1 : 0;
01105 command[3] = 0;
01106 packet->Build(command, 4);
01107
01108 Send(packet);
01109 }
01110
01111
01112 float Erratic::IRRangeFromVoltage(float voltage)
01113 {
01114
01115 return -.2475 + .1756 * voltage + .7455 / voltage - .0446 * voltage * voltage;
01116 }
01117
01118 float Erratic::IRFloorRange(float value)
01119 {
01120
01121 if (value >= 0.9)
01122 return 0.10;
01123 else
01124 return 1.0;
01125 }
01126
01127
01130
01131 void Erratic::Main() {
01132 int last_position_subscrcount=0;
01133 int last_aio_ir_subscriptions=0;
01134 int last_sonar_subscriptions=0;
01135
01136 for(;;)
01137 {
01138 pthread_testcancel();
01139
01140
01141
01142 usleep(10000);
01143
01144 this->Lock();
01145
01146
01147
01148
01149 if(!last_position_subscrcount && this->position_subscriptions)
01150 {
01151 this->ToggleMotorPower(0);
01152 this->ResetRawPositions();
01153 }
01154 else if(last_position_subscrcount && !(this->position_subscriptions))
01155 {
01156
01157 this->ToggleMotorPower(1);
01158 }
01159 last_position_subscrcount = this->position_subscriptions;
01160
01161
01162
01163
01164 if(!last_aio_ir_subscriptions && this->aio_ir_subscriptions)
01165 this->ToggleAIn(1);
01166 else if(last_aio_ir_subscriptions && !(this->aio_ir_subscriptions))
01167 this->ToggleAIn(0);
01168 last_aio_ir_subscriptions = this->aio_ir_subscriptions;
01169
01170
01171
01172
01173 if(!last_sonar_subscriptions && this->sonar_subscriptions)
01174 this->ToggleSonar(1);
01175 else if(last_sonar_subscriptions && !(this->sonar_subscriptions))
01176 this->ToggleSonar(0);
01177 last_sonar_subscriptions = this->sonar_subscriptions;
01178
01179 this->Unlock();
01180
01181
01182
01183 if(!this->InQueue->Empty())
01184 {
01185 ProcessMessages();
01186 }
01187 else
01188 {
01189
01190
01191
01192 }
01193
01194
01195 if (print_status_summary) {
01196
01197 }
01198 }
01199 }
01200
01201
01202 void Erratic::PublishPosition2D() {
01203 this->Publish(this->position_id,
01204 PLAYER_MSGTYPE_DATA,
01205 PLAYER_POSITION2D_DATA_STATE,
01206 (void*)&(this->erratic_data.position),
01207 sizeof(player_position2d_data_t),
01208 NULL);
01209 }
01210 void Erratic::PublishPower() {
01211 this->Publish(this->power_id,
01212 PLAYER_MSGTYPE_DATA,
01213 PLAYER_POWER_DATA_STATE,
01214 (void*)&(this->erratic_data.power),
01215 sizeof(player_power_data_t),
01216 NULL);
01217 }
01218 void Erratic::PublishAIn() {
01219 this->Publish(this->aio_id,
01220 PLAYER_MSGTYPE_DATA,
01221 PLAYER_AIO_DATA_STATE,
01222 (void*)&(this->erratic_data.aio),
01223 sizeof(player_aio_data_t),
01224 NULL);
01225 }
01226 void Erratic::PublishIR() {
01227 this->Publish(this->ir_id,
01228 PLAYER_MSGTYPE_DATA,
01229 PLAYER_IR_DATA_RANGES,
01230 (void*)&(this->erratic_data.ir),
01231 sizeof(player_ir_data_t),
01232 NULL);
01233 }
01234 void Erratic::PublishSonar() {
01235 this->Publish(this->sonar_id,
01236 PLAYER_MSGTYPE_DATA,
01237 PLAYER_SONAR_DATA_RANGES,
01238 (void*)&(this->erratic_data.sonar),
01239 sizeof(player_sonar_data_t),
01240 NULL);
01241 }
01242 void Erratic::PublishAllData() {
01243 this->PublishPosition2D();
01244 this->PublishPower();
01245 this->PublishAIn();
01246 this->PublishIR();
01247 this->PublishSonar();
01248 }
01249
01250
01251 int Erratic::ProcessMessage(QueuePointer &resp_queue, player_msghdr * hdr, void * data) {
01252
01253 if(hdr->type == PLAYER_MSGTYPE_REQ)
01254 return(this->HandleConfig(resp_queue,hdr,data));
01255 else if(hdr->type == PLAYER_MSGTYPE_CMD)
01256 return(this->HandleCommand(hdr,data));
01257 else
01258 return(-1);
01259 }
01260
01261
01262 int Erratic::HandleConfig(QueuePointer &resp_queue, player_msghdr * hdr, void * data) {
01263
01264
01265 if(Message::MatchMessage(hdr,PLAYER_MSGTYPE_REQ,
01266 PLAYER_POSITION2D_REQ_SET_ODOM,
01267 this->position_id))
01268 {
01269 if(hdr->size != sizeof(player_position2d_set_odom_req_t))
01270 {
01271 PLAYER_WARN("Arg to odometry set requests wrong size; ignoring");
01272 return(-1);
01273 }
01274 player_position2d_set_odom_req_t* set_odom_req =
01275 (player_position2d_set_odom_req_t*)data;
01276
01277 this->motor_packet->x_offset = ((int )rint(set_odom_req->pose.px*1e3))
01278 + this->motor_packet->xpos;
01279 this->motor_packet->y_offset = ((int)rint(set_odom_req->pose.py*1e3))
01280 + this->motor_packet->ypos;
01281 this->motor_packet->angle_offset = ((int)rint(RTOA(set_odom_req->pose.pa)))
01282 + this->motor_packet->angle;
01283
01284
01285
01286
01287
01288
01289 this->Publish(this->position_id, resp_queue,
01290 PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION2D_REQ_SET_ODOM);
01291 return(0);
01292 }
01293 else if(Message::MatchMessage(hdr,PLAYER_MSGTYPE_REQ,
01294 PLAYER_POSITION2D_REQ_MOTOR_POWER,
01295 this->position_id)) {
01296 if(hdr->size != sizeof(player_position2d_power_config_t)) {
01297 PLAYER_WARN("Arg to motor state change request wrong size; ignoring");
01298 return(-1);
01299 }
01300 player_position2d_power_config_t* power_config =
01301 (player_position2d_power_config_t*)data;
01302 this->ToggleMotorPower(power_config->state);
01303
01304 this->Publish(this->position_id, resp_queue,
01305 PLAYER_MSGTYPE_RESP_ACK,
01306 PLAYER_POSITION2D_REQ_MOTOR_POWER);
01307 return(0);
01308 } else if(Message::MatchMessage(hdr,PLAYER_MSGTYPE_REQ,
01309 PLAYER_POSITION2D_REQ_RESET_ODOM,
01310 this->position_id)) {
01311 if(hdr->size != 0) {
01312 PLAYER_WARN("Arg to reset position request is wrong size; ignoring");
01313 return(-1);
01314 }
01315
01316 this->motor_packet->x_offset = this->motor_packet->xpos;
01317 this->motor_packet->y_offset = this->motor_packet->ypos;;
01318 this->motor_packet->angle_offset = this->motor_packet->angle;;
01319 printf("Resetting odometry offsets: %d %d %d\n", motor_packet->xpos,
01320 motor_packet->ypos, motor_packet->angle);
01321
01322 this->Publish(this->position_id, resp_queue,
01323 PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION2D_REQ_RESET_ODOM);
01324 return(0);
01325 }
01326 else if(Message::MatchMessage(hdr,PLAYER_MSGTYPE_REQ,
01327 PLAYER_POSITION2D_REQ_GET_GEOM,
01328 this->position_id)) {
01329
01330 if(hdr->size != 0) {
01331 PLAYER_WARN("Arg get robot geom is wrong size; ignoring");
01332 return(-1);
01333 }
01334 player_position2d_geom_t geom;
01335
01336 geom.pose.px = -RobotParams[param_idx]->RobotAxleOffset / 1e3;
01337 geom.pose.py = 0.0;
01338 geom.pose.pyaw = 0.0;
01339
01340 geom.size.sl = RobotParams[param_idx]->RobotLength / 1e3;
01341 geom.size.sw = RobotParams[param_idx]->RobotWidth / 1e3;
01342
01343 this->Publish(this->position_id, resp_queue,
01344 PLAYER_MSGTYPE_RESP_ACK,
01345 PLAYER_POSITION2D_REQ_GET_GEOM,
01346 (void*)&geom, sizeof(geom), NULL);
01347 return(0);
01348 }
01349 else if(Message::MatchMessage(hdr,PLAYER_MSGTYPE_REQ,
01350 PLAYER_POSITION2D_REQ_VELOCITY_MODE,
01351 this->position_id)) {
01352
01353
01354
01355
01356 if(hdr->size != sizeof(player_position2d_velocity_mode_config_t))
01357 {
01358 PLAYER_WARN("Arg to velocity control mode change request is wrong "
01359 "size; ignoring");
01360 return(-1);
01361 }
01362 player_position2d_velocity_mode_config_t* velmode_config =
01363 (player_position2d_velocity_mode_config_t*)data;
01364
01365 if(velmode_config->value)
01366 direct_wheel_vel_control = false;
01367 else
01368 direct_wheel_vel_control = true;
01369
01370 this->Publish(this->position_id, resp_queue,
01371 PLAYER_MSGTYPE_RESP_ACK,
01372 PLAYER_POSITION2D_REQ_VELOCITY_MODE);
01373 return(0);
01374 }
01375
01376
01377 else if(Message::MatchMessage(hdr,PLAYER_MSGTYPE_REQ,
01378 PLAYER_IR_REQ_POSE,
01379 this->ir_id)) {
01380 player_ir_pose_t pose;
01381 pose.poses_count = RobotParams[param_idx]->NumIR;
01382 for (uint16_t i = 0; i < pose.poses_count ;i++)
01383 pose.poses[i] = RobotParams[param_idx]->IRPose[i];
01384
01385 this->Publish(this->ir_id, resp_queue,
01386 PLAYER_MSGTYPE_RESP_ACK,
01387 PLAYER_IR_REQ_POSE,
01388 (void*)&pose, sizeof(pose), NULL);
01389 return(0);
01390 }
01391
01392
01393 else if (Message::MatchMessage(hdr,PLAYER_MSGTYPE_REQ,
01394 PLAYER_SONAR_DATA_GEOM,
01395 this->sonar_id))
01396 {
01397 player_sonar_geom_t pose;
01398 pose.poses_count = RobotParams[param_idx]->NumSonars;
01399 for (uint16_t i = 0; i < pose.poses_count ;i++)
01400 pose.poses[i] = RobotParams[param_idx]->sonar_pose[i];
01401
01402 this->Publish(this->sonar_id, resp_queue,
01403 PLAYER_MSGTYPE_RESP_ACK,
01404 PLAYER_SONAR_DATA_GEOM,
01405 (void*)&pose, sizeof(pose), NULL);
01406 return(0);
01407 }
01408
01409
01410
01411 else if (Message::MatchMessage(hdr,PLAYER_MSGTYPE_REQ,
01412 PLAYER_SONAR_REQ_GET_GEOM,
01413 this->sonar_id))
01414 {
01415 player_sonar_geom_t pose;
01416 pose.poses_count = RobotParams[param_idx]->NumSonars;
01417 for (uint16_t i = 0; i < pose.poses_count ;i++)
01418 pose.poses[i] = RobotParams[param_idx]->sonar_pose[i];
01419
01420 this->Publish(this->sonar_id, resp_queue,
01421 PLAYER_MSGTYPE_RESP_ACK,
01422 PLAYER_SONAR_REQ_GET_GEOM,
01423 (void*)&pose, sizeof(pose), NULL);
01424 return(0);
01425 }
01426
01427 else
01428 {
01429 PLAYER_WARN("unknown config request to erratic driver");
01430 return(-1);
01431 }
01432 }
01433
01434
01435
01436
01437
01438 void
01439 Erratic::HandleCarCommand(player_position2d_cmd_car_t cmd)
01440 {
01441 int speedDemand, angleDemand;
01442 unsigned short absspeedDemand, absangleDemand;
01443 unsigned char motorcommand[4];
01444 ErraticPacket *motorpacket;
01445
01446 speedDemand = (int)rint(cmd.velocity * 1e3);
01447 angleDemand = (int)rint(RTOD(cmd.angle));
01448 angleDemand += (int)rint(ATOD(this->motor_packet->angle_offset));
01449 while (angleDemand > 360)
01450 angleDemand -= 360;
01451 while (angleDemand < 0)
01452 angleDemand += 360;
01453
01454
01455 motorcommand[0] = (command_e)trans_vel;
01456 if(speedDemand >= 0)
01457 motorcommand[1] = (argtype_e)argint;
01458 else
01459 motorcommand[1] = (argtype_e)argnint;
01460
01461 absspeedDemand = (unsigned short)abs(speedDemand);
01462 if(absspeedDemand < this->motor_max_speed)
01463 {
01464 motorcommand[2] = absspeedDemand & 0x00FF;
01465 motorcommand[3] = (absspeedDemand & 0xFF00) >> 8;
01466 }
01467 else
01468 {
01469 motorcommand[2] = this->motor_max_speed & 0x00FF;
01470 motorcommand[3] = (this->motor_max_speed & 0xFF00) >> 8;
01471 }
01472
01473 motorpacket = new ErraticPacket();
01474 motorpacket->Build(motorcommand, 4);
01475 Send(motorpacket);
01476
01477
01478
01479 motorcommand[0] = (command_e)rot_pos;
01480 if(angleDemand >= 0)
01481 motorcommand[1] = (argtype_e)argint;
01482 else
01483 motorcommand[1] = (argtype_e)argnint;
01484
01485 absangleDemand = (unsigned short)abs(angleDemand);
01486 motorcommand[2] = absangleDemand & 0x00FF;
01487 motorcommand[3] = (absangleDemand & 0xFF00) >> 8;
01488
01489 motorpacket = new ErraticPacket();
01490 motorpacket->Build(motorcommand, 4);
01491 Send(motorpacket);
01492 }
01493
01494
01495
01496 int getms()
01497 {
01498 struct timeval tv;
01499 gettimeofday(&tv,NULL);
01500 return tv.tv_sec*1000 + tv.tv_usec/1000;
01501 }
01502
01503
01504
01505 void Erratic::HandlePositionCommand(player_position2d_cmd_vel_t position_cmd)
01506 {
01507 int speedDemand, turnRateDemand;
01508 double leftvel, rightvel;
01509 double rotational_term;
01510 unsigned short absspeedDemand, absturnRateDemand;
01511 unsigned char motorcommand[4];
01512 ErraticPacket *motorpacket;
01513
01514 speedDemand = (int)rint(position_cmd.vel.px * 1e3);
01515 turnRateDemand = (int)rint(RTOD(position_cmd.vel.pa));
01516
01517
01518
01519
01520
01521 int ms = getms();
01522 if (mcount == 0) mcount = ms-200;
01523 if (ms < mcount + 50)
01524 return;
01525 mcount = ms;
01526
01527
01528
01529
01530
01531 if(this->direct_wheel_vel_control)
01532 {
01533
01534 rotational_term = (M_PI/180.0) * turnRateDemand /
01535 RobotParams[param_idx]->DiffConvFactor;
01536
01537
01538
01539 leftvel = (speedDemand - rotational_term);
01540 rightvel = (speedDemand + rotational_term);
01541
01542
01543
01544
01545 if(fabs(leftvel) > this->motor_max_speed)
01546 {
01547 if(leftvel > 0)
01548 {
01549 leftvel = this->motor_max_speed;
01550 rightvel *= this->motor_max_speed/leftvel;
01551 }
01552 else
01553 {
01554 leftvel = -this->motor_max_speed;
01555 rightvel *= -this->motor_max_speed/leftvel;
01556 }
01557 }
01558 if(fabs(rightvel) > this->motor_max_speed)
01559 {
01560 if(rightvel > 0)
01561 {
01562 rightvel = this->motor_max_speed;
01563 leftvel *= this->motor_max_speed/rightvel;
01564 }
01565 else
01566 {
01567 rightvel = -this->motor_max_speed;
01568 leftvel *= -this->motor_max_speed/rightvel;
01569 }
01570 }
01571
01572
01573 if(this->use_vel_band)
01574 {
01575
01576
01577
01578
01579 if (leftvel * rightvel < 0)
01580 {
01581 if (leftvel + rightvel >= 0)
01582 {
01583 if (leftvel < 0)
01584 leftvel = 0;
01585 if (rightvel < 0)
01586 rightvel = 0;
01587 }
01588 else
01589 {
01590 if (leftvel > 0)
01591 leftvel = 0;
01592 if (rightvel > 0)
01593 rightvel = 0;
01594 }
01595 }
01596 }
01597
01598
01599 if (leftvel / RobotParams[param_idx]->Vel2Divisor > 126)
01600 leftvel = 126 * RobotParams[param_idx]->Vel2Divisor;
01601 if (leftvel / RobotParams[param_idx]->Vel2Divisor < -126)
01602 leftvel = -126 * RobotParams[param_idx]->Vel2Divisor;
01603 if (rightvel / RobotParams[param_idx]->Vel2Divisor > 126)
01604 rightvel = 126 * RobotParams[param_idx]->Vel2Divisor;
01605 if (rightvel / RobotParams[param_idx]->Vel2Divisor < -126)
01606 rightvel = -126 * RobotParams[param_idx]->Vel2Divisor;
01607
01608
01609 motorcommand[0] = (command_e)wheel_vel;
01610 motorcommand[1] = (argtype_e)argint;
01611 motorcommand[2] = (char)(rightvel /
01612 RobotParams[param_idx]->Vel2Divisor);
01613 motorcommand[3] = (char)(leftvel /
01614 RobotParams[param_idx]->Vel2Divisor);
01615
01616 motorpacket = new ErraticPacket();
01617 motorpacket->Build(motorcommand, 4);
01618 Send(motorpacket);
01619 }
01620 else
01621 {
01622
01623 motorcommand[0] = (command_e)trans_vel;
01624 if(speedDemand >= 0)
01625 motorcommand[1] = (argtype_e)argint;
01626 else
01627 motorcommand[1] = (argtype_e)argnint;
01628
01629 absspeedDemand = (unsigned short)abs(speedDemand);
01630 if(absspeedDemand < this->motor_max_speed)
01631 {
01632 motorcommand[2] = absspeedDemand & 0x00FF;
01633 motorcommand[3] = (absspeedDemand & 0xFF00) >> 8;
01634 }
01635 else
01636 {
01637 motorcommand[2] = this->motor_max_speed & 0x00FF;
01638 motorcommand[3] = (this->motor_max_speed & 0xFF00) >> 8;
01639 }
01640
01641 motorpacket = new ErraticPacket();
01642 motorpacket->Build(motorcommand, 4);
01643 Send(motorpacket);
01644
01645 motorcommand[0] = (command_e)rot_vel;
01646 if(turnRateDemand >= 0)
01647 motorcommand[1] = (argtype_e)argint;
01648 else
01649 motorcommand[1] = (argtype_e)argnint;
01650
01651 absturnRateDemand = (unsigned short)abs(turnRateDemand);
01652 if(absturnRateDemand < this->motor_max_turnspeed)
01653 {
01654 motorcommand[2] = absturnRateDemand & 0x00FF;
01655 motorcommand[3] = (absturnRateDemand & 0xFF00) >> 8;
01656 }
01657 else
01658 {
01659 motorcommand[2] = this->motor_max_turnspeed & 0x00FF;
01660 motorcommand[3] = (this->motor_max_turnspeed & 0xFF00) >> 8;
01661 }
01662
01663 motorpacket = new ErraticPacket();
01664 motorpacket->Build(motorcommand, 4);
01665 Send(motorpacket);
01666
01667 }
01668 }
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685 #define SERVO_NEUTRAL 1650 // in servo counts
01686 #define SERVO_COUNTS_PER_DEGREE 6.5
01687 #define SERVO_MAX_COUNT 2300
01688 #define SERVO_MIN_COUNT 1100
01689
01690
01691 void
01692 Erratic::HandlePtzCommand(player_ptz_cmd_t cmd, player_devaddr_t id)
01693 {
01694 int pan, tilt, servo=0;
01695 unsigned char payload[6];
01696 ErraticPacket *packet;
01697
01698
01699 pan = (int)(RTOD(cmd.pan));
01700 pan = (int)((double)pan*SERVO_COUNTS_PER_DEGREE + SERVO_NEUTRAL);
01701 if (pan > SERVO_MAX_COUNT)
01702 pan = SERVO_MAX_COUNT;
01703 if (pan < SERVO_MIN_COUNT)
01704 pan = SERVO_MIN_COUNT;
01705
01706
01707 if (Device::MatchDeviceAddress(id,this->ptz_id))
01708 {
01709 packet = new ErraticPacket();
01710 payload[0] = (command_e)servo_pos;
01711 payload[1] = (argtype_e)argstr;
01712 payload[2] = 3;
01713 payload[3] = 2;
01714 payload[4] = pan&0xff;
01715 payload[5] = (pan&0xff00)>>8;
01716 packet->Build(payload, 6);
01717 this->Send(packet);
01718 }
01719
01720
01721 tilt = (int)(RTOD(cmd.tilt));
01722 tilt = (int)((double)tilt*SERVO_COUNTS_PER_DEGREE + SERVO_NEUTRAL);
01723 if (tilt > SERVO_MAX_COUNT)
01724 tilt = SERVO_MAX_COUNT;
01725 if (tilt < SERVO_MIN_COUNT)
01726 tilt = SERVO_MIN_COUNT;
01727
01728
01729 if (Device::MatchDeviceAddress(id,this->ptz_id))
01730 servo = 1;
01731 else if (Device::MatchDeviceAddress(id,this->ptz2_id))
01732 servo = 0;
01733
01734 packet = new ErraticPacket();
01735 payload[0] = (command_e)servo_pos;
01736 payload[1] = (argtype_e)argstr;
01737 payload[2] = 3;
01738 payload[3] = servo;
01739 payload[4] = tilt&0xff;
01740 payload[5] = (tilt&0xff00)>>8;
01741 packet->Build(payload, 6);
01742 this->Send(packet);
01743 }
01744
01745
01746
01747
01748 int Erratic::HandleCommand(player_msghdr * hdr, void* data)
01749 {
01750 if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, PLAYER_POSITION2D_CMD_VEL, this->position_id))
01751 {
01752 player_position2d_cmd_vel_t position_cmd = *(player_position2d_cmd_vel_t*)data;
01753 this->HandlePositionCommand(position_cmd);
01754 }
01755 else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, PLAYER_POSITION2D_CMD_CAR, this->position_id))
01756 {
01757 player_position2d_cmd_car_t position_cmd = *(player_position2d_cmd_car_t*)data;
01758 this->HandleCarCommand(position_cmd);
01759 }
01760 else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, PLAYER_POSITION2D_CMD_VEL_HEAD, this->position_id))
01761 {
01762 player_position2d_cmd_car_t position_cmd = *(player_position2d_cmd_car_t*)data;
01763 this->HandleCarCommand(position_cmd);
01764 }
01765 else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, PLAYER_PTZ_CMD_STATE, this->ptz_id))
01766 {
01767 player_ptz_cmd_t ptz_cmd = *(player_ptz_cmd_t*)data;
01768 this->HandlePtzCommand(ptz_cmd, this->ptz_id);
01769 }
01770 else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, PLAYER_PTZ_CMD_STATE, this->ptz2_id))
01771 {
01772 player_ptz_cmd_t ptz_cmd = *(player_ptz_cmd_t*)data;
01773 this->HandlePtzCommand(ptz_cmd, this->ptz2_id);
01774 }
01775 else
01776 return(-1);
01777
01778 return(0);
01779 }