00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <termios.h>
00024 #include <fcntl.h>
00025 #include <string.h>
00026
00027 #include <ros/ros.h>
00028 #include <p2os_driver/p2os.h>
00029
00030 P2OSNode::P2OSNode(ros::NodeHandle nh) :
00031 n(nh), gripper_dirty_(false),
00032 batt_pub_(n.advertise<p2os_msgs::BatteryState>("battery_state",1000),
00033 diagnostic_,
00034 diagnostic_updater::FrequencyStatusParam(&desired_freq, &desired_freq, 0.1),
00035 diagnostic_updater::TimeStampStatusParam()),
00036 ptz_(this)
00037 {
00043
00044 ros::NodeHandle n_private("~");
00045 n_private.param(std::string("odom_frame_id"), odom_frame_id,std::string("odom"));
00046 n_private.param(std::string("base_link_frame_id"), base_link_frame_id,std::string("base_link"));
00047 n_private.param("use_sonar", use_sonar_, false);
00048
00049
00050
00051 n_private.param("bumpstall", bumpstall, -1);
00052
00053 n_private.param("pulse", pulse, -1.0);
00054
00055 n_private.param("rot_kp", rot_kp, -1);
00056
00057 n_private.param("rot_kv", rot_kv, -1);
00058
00059 n_private.param("rot_ki", rot_ki, -1);
00060
00061 n_private.param("trans_kp", trans_kp, -1);
00062
00063 n_private.param("trans_kv", trans_kv, -1);
00064
00065 n_private.param("trans_ki", trans_ki, -1);
00066
00067 std::string def = DEFAULT_P2OS_PORT;
00068 n_private.param("port", psos_serial_port, def);
00069 ROS_INFO("using serial port: [%s]", psos_serial_port.c_str());
00070 n_private.param("use_tcp", psos_use_tcp, false);
00071 std::string host = DEFAULT_P2OS_TCP_REMOTE_HOST;
00072 n_private.param("tcp_remote_host", psos_tcp_host, host);
00073 n_private.param("tcp_remote_port", psos_tcp_port, DEFAULT_P2OS_TCP_REMOTE_PORT);
00074
00075 n_private.param("radio", radio_modemp, 0);
00076
00077 n_private.param("joystick", joystick, 0);
00078
00079 n_private.param("direct_wheel_vel_control", direct_wheel_vel_control, 0);
00080
00081 double spd;
00082 n_private.param("max_xspeed", spd, MOTOR_DEF_MAX_SPEED);
00083 motor_max_speed = (int)rint(1e3*spd);
00084
00085 n_private.param("max_yawspeed", spd, MOTOR_DEF_MAX_TURNSPEED);
00086 motor_max_turnspeed = (short)rint(RTOD(spd));
00087
00088 n_private.param("max_xaccel", spd, 0.0);
00089 motor_max_trans_accel = (short)rint(1e3*spd);
00090
00091 n_private.param("max_xdecel", spd, 0.0);
00092 motor_max_trans_decel = (short)rint(1e3*spd);
00093
00094 n_private.param("max_yawaccel", spd, 0.0);
00095 motor_max_rot_accel = (short)rint(RTOD(spd));
00096
00097 n_private.param("max_yawdecel", spd, 0.0);
00098 motor_max_rot_decel = (short)rint(RTOD(spd));
00099
00100 desired_freq = 10;
00101
00102
00103 pose_pub_ = n.advertise<nav_msgs::Odometry>("pose", 1000);
00104
00105 mstate_pub_ = n.advertise<p2os_msgs::MotorState>("motor_state",1000);
00106 grip_state_pub_ = n.advertise<p2os_msgs::GripperState>("gripper_state",1000);
00107 ptz_state_pub_ = n.advertise<p2os_msgs::PTZState>("ptz_state",1000);
00108 sonar_pub_ = n.advertise<p2os_msgs::SonarArray>("sonar", 1000);
00109 aio_pub_ = n.advertise<p2os_msgs::AIO>("aio", 1000);
00110 dio_pub_ = n.advertise<p2os_msgs::DIO>("dio", 1000);
00111
00112
00113 cmdvel_sub_ = n.subscribe("cmd_vel", 1, &P2OSNode::cmdvel_cb, this);
00114 cmdmstate_sub_ = n.subscribe("cmd_motor_state", 1, &P2OSNode::cmdmotor_state,
00115 this);
00116 gripper_sub_ = n.subscribe("gripper_control", 1, &P2OSNode::gripperCallback,
00117 this);
00118 ptz_cmd_sub_ = n.subscribe("ptz_control", 1, &P2OSPtz::callback, &ptz_);
00119
00120 veltime = ros::Time::now();
00121
00122
00123 diagnostic_.add("Motor Stall", this, &P2OSNode::check_stall);
00124 diagnostic_.add("Battery Voltage", this, &P2OSNode::check_voltage);
00125
00126
00127 initialize_robot_params();
00128 }
00129
00130 P2OSNode::~P2OSNode() {}
00131
00132 void P2OSNode::cmdmotor_state(const p2os_msgs::MotorStateConstPtr & msg)
00133 {
00134 motor_dirty = true;
00135 cmdmotor_state_ = *msg;
00136 }
00137
00138 void P2OSNode::check_and_set_motor_state()
00139 {
00140 if(!motor_dirty) return;
00141 motor_dirty = false;
00142
00143 unsigned char val = (unsigned char) cmdmotor_state_.state;
00144 unsigned char command[4];
00145 P2OSPacket packet;
00146 command[0] = ENABLE;
00147 command[1] = ARGINT;
00148 command[2] = val;
00149 command[3] = 0;
00150 packet.Build(command,4);
00151
00152
00153 p2os_data.motors.state = cmdmotor_state_.state;
00154 SendReceive(&packet,false);
00155 }
00156
00157 void P2OSNode::check_and_set_gripper_state()
00158 {
00159 if(!gripper_dirty_) return;
00160 gripper_dirty_ = false;
00161
00162
00163 unsigned char grip_val = (unsigned char) gripper_state_.grip.state;
00164 unsigned char grip_command[4];
00165
00166 P2OSPacket grip_packet;
00167 grip_command[0] = GRIPPER;
00168 grip_command[1] = ARGINT;
00169 grip_command[2] = grip_val;
00170 grip_command[3] = 0;
00171 grip_packet.Build(grip_command,4);
00172 SendReceive(&grip_packet, false);
00173
00174
00175 unsigned char lift_val = (unsigned char) gripper_state_.lift.state;
00176 unsigned char lift_command[4];
00177
00178 P2OSPacket lift_packet;
00179 lift_command[0] = GRIPPER;
00180 lift_command[1] = ARGINT;
00181 lift_command[2] = lift_val;
00182 lift_command[3] = 0;
00183 lift_packet.Build(lift_command,4);
00184
00185 SendReceive(&lift_packet,false);
00186 }
00187
00188 void P2OSNode::cmdvel_cb(const geometry_msgs::TwistConstPtr &msg)
00189 {
00190 if(fabs(msg->linear.x - cmdvel_.linear.x) > 0.01 || fabs(msg->angular.z - cmdvel_.angular.z) > 0.01) {
00191 veltime = ros::Time::now();
00192 ROS_DEBUG("new speed: [%0.2f,%0.2f](%0.3f)", msg->linear.x*1e3, msg->angular.z, veltime.toSec());
00193 vel_dirty = true;
00194 cmdvel_ = *msg;
00195 } else {
00196 ros::Duration veldur = ros::Time::now() - veltime;
00197 if(veldur.toSec() > 2.0 && ((fabs(cmdvel_.linear.x) > 0.01) || (fabs(cmdvel_.angular.z) > 0.01))) {
00198 ROS_DEBUG("maintaining old speed: %0.3f|%0.3f", veltime.toSec(), ros::Time::now().toSec());
00199 vel_dirty = true;
00200 veltime = ros::Time::now();
00201 }
00202 }
00203
00204 }
00205
00206 void P2OSNode::check_and_set_vel()
00207 {
00208 if(!vel_dirty) return;
00209
00210 ROS_DEBUG("setting vel: [%0.2f,%0.2f]",cmdvel_.linear.x,cmdvel_.angular.z);
00211 vel_dirty = false;
00212
00213 unsigned short absSpeedDemand, absturnRateDemand;
00214 unsigned char motorcommand[4];
00215 P2OSPacket motorpacket;
00216
00217 int vx = (int) (cmdvel_.linear.x*1e3);
00218 int va = (int) rint(RTOD(cmdvel_.angular.z));
00219
00220
00221 motorcommand[0] = VEL;
00222 motorcommand[1] = (vx >= 0) ? ARGINT : ARGNINT;
00223
00224 absSpeedDemand = (unsigned short) abs(vx);
00225
00226 if(absSpeedDemand <= this->motor_max_speed) {
00227 motorcommand[2] = absSpeedDemand & 0x00FF;
00228 motorcommand[3] = (absSpeedDemand & 0xFF00) >> 8;
00229 } else {
00230 ROS_WARN("speed demand thresholded! (true: %u, max: %u)", absSpeedDemand, motor_max_speed);
00231 motorcommand[2] = motor_max_speed & 0x00FF;
00232 motorcommand[3] = (motor_max_speed & 0xFF00) >> 8;
00233 }
00234
00235 motorpacket.Build(motorcommand, 4);
00236 SendReceive(&motorpacket);
00237
00238 motorcommand[0] = RVEL;
00239 motorcommand[1] = (va >= 0) ? ARGINT : ARGNINT;
00240
00241 absturnRateDemand = (unsigned short) (va >= 0) ? va : (-1 * va);
00242
00243 if(absturnRateDemand <= motor_max_turnspeed) {
00244 motorcommand[2] = absturnRateDemand & 0x00FF;
00245 motorcommand[3] = (absturnRateDemand & 0xFF00) >> 8;
00246 } else {
00247 ROS_WARN("Turn rate demand threshholded!");
00248 motorcommand[2] = this->motor_max_turnspeed & 0x00FF;
00249 motorcommand[3] = (this->motor_max_turnspeed & 0xFF00) >> 8;
00250 }
00251
00252 motorpacket.Build(motorcommand,4);
00253 SendReceive(&motorpacket);
00254 }
00255
00256 void P2OSNode::gripperCallback(const p2os_msgs::GripperStateConstPtr &msg)
00257 {
00258 gripper_dirty_ = true;
00259 gripper_state_ = *msg;
00260 }
00261
00262 int P2OSNode::Setup()
00263 {
00264 int i;
00265 int bauds[] = {B9600, B38400, B19200, B115200, B57600};
00266 int numbauds = sizeof(bauds);
00267 int currbaud = 0;
00268 sippacket = NULL;
00269 lastPulseTime = 0.0;
00270
00271 struct termios term;
00272 unsigned char command;
00273 P2OSPacket packet, receivedpacket;
00274 int flags=0;
00275 bool sent_close = false;
00276
00277 enum
00278 {
00279 NO_SYNC,
00280 AFTER_FIRST_SYNC,
00281 AFTER_SECOND_SYNC,
00282 READY
00283 } psos_state;
00284
00285 psos_state = NO_SYNC;
00286
00287 char name[20], type[20], subtype[20];
00288 int cnt;
00289
00290
00291
00292
00293 ROS_INFO("P2OS connection opening serial port %s...",psos_serial_port.c_str());
00294
00295 if((this->psos_fd = open(this->psos_serial_port.c_str(),
00296 O_RDWR | O_SYNC | O_NONBLOCK, S_IRUSR | S_IWUSR)) < 0)
00297 {
00298 ROS_ERROR("P2OS::Setup():open():");
00299 return(1);
00300 }
00301
00302 if(tcgetattr(this->psos_fd, &term) < 0)
00303 {
00304 ROS_ERROR("P2OS::Setup():tcgetattr():");
00305 close(this->psos_fd);
00306 this->psos_fd = -1;
00307 return(1);
00308 }
00309
00310 cfmakeraw(&term);
00311 cfsetispeed(&term, bauds[currbaud]);
00312 cfsetospeed(&term, bauds[currbaud]);
00313
00314 if(tcsetattr(this->psos_fd, TCSAFLUSH, &term) < 0)
00315 {
00316 ROS_ERROR("P2OS::Setup():tcsetattr():");
00317 close(this->psos_fd);
00318 this->psos_fd = -1;
00319 return(1);
00320 }
00321
00322 if(tcflush(this->psos_fd, TCIOFLUSH) < 0)
00323 {
00324 ROS_ERROR("P2OS::Setup():tcflush():");
00325 close(this->psos_fd);
00326 this->psos_fd = -1;
00327 return(1);
00328 }
00329
00330 if((flags = fcntl(this->psos_fd, F_GETFL)) < 0)
00331 {
00332 ROS_ERROR("P2OS::Setup():fcntl()");
00333 close(this->psos_fd);
00334 this->psos_fd = -1;
00335 return(1);
00336 }
00337
00338
00339 int num_sync_attempts = 3;
00340 while(psos_state != READY)
00341 {
00342 switch(psos_state)
00343 {
00344 case NO_SYNC:
00345 command = SYNC0;
00346 packet.Build(&command, 1);
00347 packet.Send(this->psos_fd);
00348 usleep(P2OS_CYCLETIME_USEC);
00349 break;
00350 case AFTER_FIRST_SYNC:
00351 ROS_INFO("turning off NONBLOCK mode...");
00352 if(fcntl(this->psos_fd, F_SETFL, flags ^ O_NONBLOCK) < 0)
00353 {
00354 ROS_ERROR("P2OS::Setup():fcntl()");
00355 close(this->psos_fd);
00356 this->psos_fd = -1;
00357 return(1);
00358 }
00359 command = SYNC1;
00360 packet.Build(&command, 1);
00361 packet.Send(this->psos_fd);
00362 break;
00363 case AFTER_SECOND_SYNC:
00364 command = SYNC2;
00365 packet.Build(&command, 1);
00366 packet.Send(this->psos_fd);
00367 break;
00368 default:
00369 ROS_WARN("P2OS::Setup():shouldn't be here...");
00370 break;
00371 }
00372 usleep(P2OS_CYCLETIME_USEC);
00373
00374 if(receivedpacket.Receive(this->psos_fd))
00375 {
00376 if((psos_state == NO_SYNC) && (num_sync_attempts >= 0))
00377 {
00378 num_sync_attempts--;
00379 usleep(P2OS_CYCLETIME_USEC);
00380 continue;
00381 }
00382 else
00383 {
00384
00385 if(++currbaud < numbauds)
00386 {
00387 cfsetispeed(&term, bauds[currbaud]);
00388 cfsetospeed(&term, bauds[currbaud]);
00389 if(tcsetattr(this->psos_fd, TCSAFLUSH, &term) < 0)
00390 {
00391 ROS_ERROR("P2OS::Setup():tcsetattr():");
00392 close(this->psos_fd);
00393 this->psos_fd = -1;
00394 return(1);
00395 }
00396
00397 if(tcflush(this->psos_fd, TCIOFLUSH) < 0)
00398 {
00399 ROS_ERROR("P2OS::Setup():tcflush():");
00400 close(this->psos_fd);
00401 this->psos_fd = -1;
00402 return(1);
00403 }
00404 num_sync_attempts = 3;
00405 continue;
00406 }
00407 else
00408 {
00409
00410 break;
00411 }
00412 }
00413 }
00414 switch(receivedpacket.packet[3])
00415 {
00416 case SYNC0:
00417 ROS_INFO("SYNC0");
00418 psos_state = AFTER_FIRST_SYNC;
00419 break;
00420 case SYNC1:
00421 ROS_INFO("SYNC1");
00422 psos_state = AFTER_SECOND_SYNC;
00423 break;
00424 case SYNC2:
00425 ROS_INFO("SYNC2");
00426 psos_state = READY;
00427 break;
00428 default:
00429
00430
00431 if(!sent_close)
00432 {
00433 ROS_DEBUG("sending CLOSE");
00434 command = CLOSE;
00435 packet.Build(&command, 1);
00436 packet.Send(this->psos_fd);
00437 sent_close = true;
00438 usleep(2*P2OS_CYCLETIME_USEC);
00439 tcflush(this->psos_fd,TCIFLUSH);
00440 psos_state = NO_SYNC;
00441 }
00442 break;
00443 }
00444 usleep(P2OS_CYCLETIME_USEC);
00445 }
00446 if(psos_state != READY)
00447 {
00448 if(this->psos_use_tcp)
00449 ROS_INFO("Couldn't synchronize with P2OS.\n"
00450 " Most likely because the robot is not connected %s %s",
00451 this->psos_use_tcp ? "to the ethernet-serial bridge device " : "to the serial port",
00452 this->psos_use_tcp ? this->psos_tcp_host.c_str() : this->psos_serial_port.c_str());
00453 close(this->psos_fd);
00454 this->psos_fd = -1;
00455 return(1);
00456 }
00457 cnt = 4;
00458 cnt += snprintf(name, sizeof(name), "%s", &receivedpacket.packet[cnt]);
00459 cnt++;
00460 cnt += snprintf(type, sizeof(type), "%s", &receivedpacket.packet[cnt]);
00461 cnt++;
00462 cnt += snprintf(subtype, sizeof(subtype), "%s", &receivedpacket.packet[cnt]);
00463 cnt++;
00464
00465 std::string hwID = std::string(name) + ": " + std::string(type) + "/" + std::string(subtype);
00466 diagnostic_.setHardwareID(hwID);
00467
00468 command = OPEN;
00469 packet.Build(&command, 1);
00470 packet.Send(this->psos_fd);
00471 usleep(P2OS_CYCLETIME_USEC);
00472 command = PULSE;
00473 packet.Build(&command, 1);
00474 packet.Send(this->psos_fd);
00475 usleep(P2OS_CYCLETIME_USEC);
00476
00477 ROS_INFO("Done.\n Connected to %s, a %s %s", name, type, subtype);
00478
00479
00480 for(i=0;i<PLAYER_NUM_ROBOT_TYPES;i++)
00481 {
00482 if(!strcasecmp(PlayerRobotParams[i].Class.c_str(),type) &&
00483 !strcasecmp(PlayerRobotParams[i].Subclass.c_str(),subtype))
00484 {
00485 param_idx = i;
00486 break;
00487 }
00488 }
00489 if(i == PLAYER_NUM_ROBOT_TYPES)
00490 {
00491 ROS_WARN("P2OS: Warning: couldn't find parameters for this robot; "
00492 "using defaults");
00493 param_idx = 0;
00494 }
00495
00496
00497
00498
00499 if(!sippacket)
00500 {
00501 sippacket = new SIP(param_idx);
00502 sippacket->odom_frame_id = odom_frame_id;
00503 sippacket->base_link_frame_id = base_link_frame_id;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513 this->ToggleSonarPower(0);
00514
00515 P2OSPacket accel_packet;
00516 unsigned char accel_command[4];
00517 if(this->motor_max_trans_accel > 0)
00518 {
00519 accel_command[0] = SETA;
00520 accel_command[1] = ARGINT;
00521 accel_command[2] = this->motor_max_trans_accel & 0x00FF;
00522 accel_command[3] = (this->motor_max_trans_accel & 0xFF00) >> 8;
00523 accel_packet.Build(accel_command, 4);
00524 this->SendReceive(&accel_packet,false);
00525 }
00526
00527 if(this->motor_max_trans_decel < 0)
00528 {
00529 accel_command[0] = SETA;
00530 accel_command[1] = ARGNINT;
00531 accel_command[2] = -1 *(this->motor_max_trans_decel) & 0x00FF;
00532 accel_command[3] = (-1 *(this->motor_max_trans_decel) & 0xFF00) >> 8;
00533 accel_packet.Build(accel_command, 4);
00534 this->SendReceive(&accel_packet,false);
00535 }
00536 if(this->motor_max_rot_accel > 0)
00537 {
00538 accel_command[0] = SETRA;
00539 accel_command[1] = ARGINT;
00540 accel_command[2] = this->motor_max_rot_accel & 0x00FF;
00541 accel_command[3] = (this->motor_max_rot_accel & 0xFF00) >> 8;
00542 accel_packet.Build(accel_command, 4);
00543 this->SendReceive(&accel_packet,false);
00544 }
00545 if(this->motor_max_rot_decel < 0)
00546 {
00547 accel_command[0] = SETRA;
00548 accel_command[1] = ARGNINT;
00549 accel_command[2] = -1*(this->motor_max_rot_decel) & 0x00FF;
00550 accel_command[3] = (-1*(this->motor_max_rot_decel) & 0xFF00) >> 8;
00551 accel_packet.Build(accel_command, 4);
00552 this->SendReceive(&accel_packet,false);
00553 }
00554
00555
00556
00557 P2OSPacket pid_packet;
00558 unsigned char pid_command[4];
00559 if(this->rot_kp >= 0)
00560 {
00561 pid_command[0] = ROTKP;
00562 pid_command[1] = ARGINT;
00563 pid_command[2] = this->rot_kp & 0x00FF;
00564 pid_command[3] = (this->rot_kp & 0xFF00) >> 8;
00565 pid_packet.Build(pid_command, 4);
00566 this->SendReceive(&pid_packet);
00567 }
00568 if(this->rot_kv >= 0)
00569 {
00570 pid_command[0] = ROTKV;
00571 pid_command[1] = ARGINT;
00572 pid_command[2] = this->rot_kv & 0x00FF;
00573 pid_command[3] = (this->rot_kv & 0xFF00) >> 8;
00574 pid_packet.Build(pid_command, 4);
00575 this->SendReceive(&pid_packet);
00576 }
00577 if(this->rot_ki >= 0)
00578 {
00579 pid_command[0] = ROTKI;
00580 pid_command[1] = ARGINT;
00581 pid_command[2] = this->rot_ki & 0x00FF;
00582 pid_command[3] = (this->rot_ki & 0xFF00) >> 8;
00583 pid_packet.Build(pid_command, 4);
00584 this->SendReceive(&pid_packet);
00585 }
00586 if(this->trans_kp >= 0)
00587 {
00588 pid_command[0] = TRANSKP;
00589 pid_command[1] = ARGINT;
00590 pid_command[2] = this->trans_kp & 0x00FF;
00591 pid_command[3] = (this->trans_kp & 0xFF00) >> 8;
00592 pid_packet.Build(pid_command, 4);
00593 this->SendReceive(&pid_packet);
00594 }
00595 if(this->trans_kv >= 0)
00596 {
00597 pid_command[0] = TRANSKV;
00598 pid_command[1] = ARGINT;
00599 pid_command[2] = this->trans_kv & 0x00FF;
00600 pid_command[3] = (this->trans_kv & 0xFF00) >> 8;
00601 pid_packet.Build(pid_command, 4);
00602 this->SendReceive(&pid_packet);
00603 }
00604 if(this->trans_ki >= 0)
00605 {
00606 pid_command[0] = TRANSKI;
00607 pid_command[1] = ARGINT;
00608 pid_command[2] = this->trans_ki & 0x00FF;
00609 pid_command[3] = (this->trans_ki & 0xFF00) >> 8;
00610 pid_packet.Build(pid_command, 4);
00611 this->SendReceive(&pid_packet);
00612 }
00613
00614
00615
00616
00617
00618
00619
00620 if(this->bumpstall >= 0)
00621 {
00622 if(this->bumpstall > 3)
00623 ROS_INFO("ignoring bumpstall value %d; should be 0, 1, 2, or 3",
00624 this->bumpstall);
00625 else
00626 {
00627 ROS_INFO("setting bumpstall to %d", this->bumpstall);
00628 P2OSPacket bumpstall_packet;;
00629 unsigned char bumpstall_command[4];
00630 bumpstall_command[0] = BUMP_STALL;
00631 bumpstall_command[1] = ARGINT;
00632 bumpstall_command[2] = (unsigned char)this->bumpstall;
00633 bumpstall_command[3] = 0;
00634 bumpstall_packet.Build(bumpstall_command, 4);
00635 this->SendReceive(&bumpstall_packet,false);
00636 }
00637 }
00638
00639
00640 if(use_sonar_) {
00641 this->ToggleSonarPower(1);
00642 ROS_DEBUG("Sonar array powered on.");
00643 }
00644 ptz_.setup();
00645
00646 return(0);
00647 }
00648
00649 int P2OSNode::Shutdown()
00650 {
00651 unsigned char command[20],buffer[20];
00652 P2OSPacket packet;
00653
00654 if (ptz_.isOn())
00655 {
00656 ptz_.shutdown();
00657 }
00658
00659 memset(buffer,0,20);
00660
00661 if(this->psos_fd == -1)
00662 return -1;
00663
00664 command[0] = STOP;
00665 packet.Build(command, 1);
00666 packet.Send(this->psos_fd);
00667 usleep(P2OS_CYCLETIME_USEC);
00668
00669 command[0] = CLOSE;
00670 packet.Build(command, 1);
00671 packet.Send(this->psos_fd);
00672 usleep(P2OS_CYCLETIME_USEC);
00673
00674 close(this->psos_fd);
00675 this->psos_fd = -1;
00676 ROS_INFO("P2OS has been shutdown");
00677 delete this->sippacket;
00678 this->sippacket = NULL;
00679
00680 return 0;
00681 }
00682
00683
00684 void
00685 P2OSNode::StandardSIPPutData(ros::Time ts)
00686 {
00687
00688 p2os_data.position.header.stamp = ts;
00689 pose_pub_.publish(p2os_data.position);
00690 p2os_data.odom_trans.header.stamp = ts;
00691 odom_broadcaster.sendTransform(p2os_data.odom_trans);
00692
00693 p2os_data.batt.header.stamp = ts;
00694 batt_pub_.publish(p2os_data.batt);
00695 mstate_pub_.publish(p2os_data.motors);
00696
00697
00698 p2os_data.sonar.header.stamp = ts;
00699 sonar_pub_.publish(p2os_data.sonar);
00700
00701
00702 aio_pub_.publish(p2os_data.aio);
00703
00704 dio_pub_.publish(p2os_data.dio);
00705
00706
00707 grip_state_pub_.publish(p2os_data.gripper);
00708 ptz_state_pub_.publish(ptz_.getCurrentState());
00709
00710
00711
00712
00713 }
00714
00715
00716 int P2OSNode::SendReceive(P2OSPacket* pkt, bool publish_data)
00717 {
00718 P2OSPacket packet;
00719
00720 if((this->psos_fd >= 0) && this->sippacket)
00721 {
00722 if(pkt)
00723 pkt->Send(this->psos_fd);
00724
00725
00726 pthread_testcancel();
00727 if(packet.Receive(this->psos_fd))
00728 {
00729 ROS_ERROR("RunPsosThread(): Receive errored");
00730 pthread_exit(NULL);
00731 }
00732
00733 if(packet.packet[0] == 0xFA && packet.packet[1] == 0xFB &&
00734 (packet.packet[3] == 0x30 || packet.packet[3] == 0x31 ||
00735 packet.packet[3] == 0x32 || packet.packet[3] == 0x33 ||
00736 packet.packet[3] == 0x34))
00737 {
00738
00739
00740 this->sippacket->ParseStandard(&packet.packet[3]);
00741 this->sippacket->FillStandard(&(this->p2os_data));
00742
00743 if(publish_data)
00744 this->StandardSIPPutData(packet.timestamp);
00745 }
00746 else if(packet.packet[0] == 0xFA && packet.packet[1] == 0xFB &&
00747 packet.packet[3] == SERAUX)
00748 {
00749
00750 if(ptz_.isOn())
00751 {
00752 int len = packet.packet[2] - 3;
00753 if (ptz_.cb_.gotPacket())
00754 {
00755 ROS_ERROR("PTZ got a message, but alread has the complete packet.");
00756 }
00757 else
00758 {
00759 for (int i=4; i < 4+len; ++i)
00760 {
00761 ptz_.cb_.putOnBuf(packet.packet[i]);
00762 }
00763 }
00764 }
00765 }
00766 else
00767 {
00768 ROS_ERROR("Received other packet!");
00769 packet.PrintHex();
00770 }
00771 }
00772
00773 return(0);
00774 }
00775
00776 void P2OSNode::updateDiagnostics()
00777 {
00778 diagnostic_.update();
00779 }
00780
00781 void P2OSNode::check_voltage(diagnostic_updater::DiagnosticStatusWrapper &stat)
00782 {
00783 double voltage = sippacket->battery / 10.0;
00784 if(voltage < 11.0) stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "battery voltage critically low");
00785 else if (voltage < 11.75) stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "battery voltage getting low");
00786 else stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "battery voltage OK");
00787
00788 stat.add("voltage", voltage);
00789 }
00790
00791 void P2OSNode::check_stall(diagnostic_updater::DiagnosticStatusWrapper &stat)
00792 {
00793 if(sippacket->lwstall||sippacket->rwstall) stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR,
00794 "wheel stalled");
00795 else stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "no wheel stall");
00796
00797 stat.add("left wheel stall", sippacket->lwstall);
00798 stat.add("right wheel stall", sippacket->rwstall);
00799 }
00800
00801 void P2OSNode::ResetRawPositions()
00802 {
00803 P2OSPacket pkt;
00804 unsigned char p2oscommand[4];
00805
00806 if(this->sippacket) {
00807 this->sippacket->rawxpos = 0;
00808 this->sippacket->rawypos = 0;
00809 this->sippacket->xpos = 0;
00810 this->sippacket->ypos = 0;
00811 p2oscommand[0] = SETO;
00812 p2oscommand[1] = ARGINT;
00813 pkt.Build(p2oscommand, 2);
00814 this->SendReceive(&pkt,false);
00815 ROS_INFO("resetting raw positions");
00816 }
00817 }
00818
00819
00820 void P2OSNode::ToggleSonarPower(unsigned char val)
00821 {
00822 unsigned char command[4];
00823 P2OSPacket packet;
00824
00825 command[0] = SONAR;
00826 command[1] = ARGINT;
00827 command[2] = val;
00828 command[3] = 0;
00829 packet.Build(command, 4);
00830 SendReceive(&packet,false);
00831 }
00832
00838 void P2OSNode::ToggleMotorPower(unsigned char val)
00839 {
00840 unsigned char command[4];
00841 P2OSPacket packet;
00842 ROS_INFO("motor state: %d\n", p2os_data.motors.state);
00843 p2os_data.motors.state = (int) val;
00844 command[0] = ENABLE;
00845 command[1] = ARGINT;
00846 command[2] = val;
00847 command[3] = 0;
00848 packet.Build(command, 4);
00849 SendReceive(&packet,false);
00850 }
00851
00853
00855
00856
00858 inline double P2OSNode::TicksToDegrees (int joint, unsigned char ticks)
00859 {
00860 if ((joint < 0) || (joint >= sippacket->armNumJoints))
00861 return 0;
00862
00863 double result;
00864 int pos = ticks - sippacket->armJoints[joint].centre;
00865 result = 90.0 / static_cast<double> (sippacket->armJoints[joint].ticksPer90);
00866 result = result * pos;
00867 if ((joint >= 0) && (joint <= 2))
00868 result = -result;
00869
00870 return result;
00871 }
00872
00873
00875 inline unsigned char P2OSNode::DegreesToTicks (int joint, double degrees)
00876 {
00877 double val;
00878
00879 if ((joint < 0) || (joint >= sippacket->armNumJoints))
00880 return 0;
00881
00882 val = static_cast<double> (sippacket->armJoints[joint].ticksPer90) * degrees / 90.0;
00883 val = round (val);
00884 if ((joint >= 0) && (joint <= 2))
00885 val = -val;
00886 val += sippacket->armJoints[joint].centre;
00887
00888 if (val < sippacket->armJoints[joint].min) return sippacket->armJoints[joint].min;
00889 else if (val > sippacket->armJoints[joint].max) return sippacket->armJoints[joint].max;
00890 else return static_cast<int> (round (val));
00891 }
00892
00894 inline double P2OSNode::TicksToRadians (int joint, unsigned char ticks)
00895 {
00896 double result = DTOR (TicksToDegrees (joint, ticks));
00897 return result;
00898 }
00899
00901 inline unsigned char P2OSNode::RadiansToTicks (int joint, double rads)
00902 {
00903 unsigned char result = static_cast<unsigned char> (DegreesToTicks (joint, RTOD (rads)));
00904 return result;
00905 }
00906
00908 inline double P2OSNode::RadsPerSectoSecsPerTick (int joint, double speed)
00909 {
00910 double degs = RTOD (speed);
00911 double ticksPerDeg = static_cast<double> (sippacket->armJoints[joint].ticksPer90) / 90.0;
00912 double ticksPerSec = degs * ticksPerDeg;
00913 double secsPerTick = 1000.0f / ticksPerSec;
00914
00915 if (secsPerTick > 127)
00916 return 127;
00917 else if (secsPerTick < 1)
00918 return 1;
00919 return secsPerTick;
00920 }
00921
00923 inline double P2OSNode::SecsPerTicktoRadsPerSec (int joint, double msecs)
00924 {
00925 double ticksPerSec = 1.0 / (static_cast<double> (msecs) / 1000.0);
00926 double ticksPerDeg = static_cast<double> (sippacket->armJoints[joint].ticksPer90) / 90.0;
00927 double degs = ticksPerSec / ticksPerDeg;
00928 double rads = DTOR (degs);
00929
00930 return rads;
00931 }
00932
00933 void P2OSNode::SendPulse (void)
00934 {
00935 unsigned char command;
00936 P2OSPacket packet;
00937
00938 command = PULSE;
00939 packet.Build(&command, 1);
00940 SendReceive(&packet);
00941 }