00001 #include <omnix/omnix.h>
00002
00003
00004 OmnixNode::OmnixNode():
00005 n_("~")
00006 {
00007 n_.param("omnix_ip_addr",hostname,std::string("130.207.32.211"));
00008
00009 n_.param("omnix_port",portno,5555);
00010 n_.param("omnix_port_rec",portno_rec,5556);
00011 n_.param("open_rec_socket",open_rec_socket,true);
00012
00013 initCommands();
00014 emergency_stop = true;
00015 brake_engaged = true;
00016 joystick_controlled = true;
00017 first_write = true;
00018 recv_odom = false;
00019 counter = 1;
00020 rec_buf_size = 1024;
00021 verbose = false;
00022
00023
00024 estop_timer_ = n_.createTimer(ros::Duration(0.1),&OmnixNode::timerCallback,this);
00025 estop_timeout_ = ros::Duration(0.1);
00026
00027 read_timer_ = n_.createTimer(ros::Duration(0.02),&OmnixNode::readTimerCallback,this);
00028
00029 engage_brake_service_ = n_.advertiseService("engage_brake",&OmnixNode::EngageBrakeCallback,this);
00030 disengage_brake_service_ = n_.advertiseService("disengage_brake",&OmnixNode::ReleaseBrakeCallback,this);
00031 disable_joystick_service_ = n_.advertiseService("disable_joystick",&OmnixNode::DisableJoystickCallback,this);
00032
00033 odom_pub_ = n_.advertise<nav_msgs::Odometry>("/odom", 1);
00034
00035
00036
00037
00038 last_vel_cmd_sent = ros::Time::now();
00039 last_vel_cmd = new geometry_msgs::Twist();
00040 last_vel_cmd->linear.x = 0;
00041 last_vel_cmd->linear.y = 0;
00042 last_vel_cmd->angular.z = 0;
00043
00044 odom_x = odom_y = odom_yaw = 0.0;
00045 prev_j1 = prev_j2 = prev_j3 = prev_j4 = 0.0;
00046 vx = vy = vt = 0.0;
00047 prev_time = ros::Time::now();
00048
00049 joy_sub_ = n_.subscribe<sensor_msgs::Joy>("/joy", 1, &OmnixNode::joyCallback, this);
00050
00051 cmd_vel_sub_ = n_.subscribe<geometry_msgs::Twist>("/cmd_vel",1,boost::bind(&OmnixNode::cmdvelCallback, this, _1));
00052
00053 openOmnixSocket();
00054 ROS_INFO("Opening receiving socket...");
00055 if(open_rec_socket){
00056 openOmnixSocketRec();
00057 ROS_INFO("Receive socket online, ready to stream odometry.");
00058 }
00059 }
00060
00061 OmnixNode::~OmnixNode()
00062 {
00063 closeOmnixSocket();
00064 }
00065
00066 void OmnixNode::openOmnixSocket()
00067 {
00068 ROS_INFO("Attempting to open socket to Omnix at %s : %d",hostname.c_str(),portno);
00069
00070 gethostbyname(hostname.c_str());
00071 ROS_INFO("Got host by name");
00072
00073 if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
00074 ROS_ERROR("OmnixNode: Error opening UDP socket. Exiting!");
00075 exit(1);
00076 }
00077
00078 ROS_INFO("Socket opened.");
00079 memset((char *) &server_addr, 0, sizeof(server_addr));
00080 server_addr.sin_family = AF_INET;
00081 server_addr.sin_port = htons(portno);
00082 if(inet_aton(hostname.c_str(), &server_addr.sin_addr)==0){
00083 ROS_ERROR("OmnixNode: inet_aton() failed. Exiting!");
00084 exit(1);
00085 }
00086 server_addr_len = sizeof(server_addr);
00087 ROS_INFO("Ready for communication!");
00088 }
00089
00090 void OmnixNode::openOmnixSocketRec()
00091 {
00092 ROS_INFO("Attempting to open recieving socket to Omnix at port %d",portno_rec);
00093
00094
00095
00096
00097 if((sock_rec = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
00098 ROS_ERROR("OmnixNode: Error opening UDP receiving socket. Exiting!");
00099 exit(1);
00100 }
00101
00102 ROS_INFO("Recv Socket opened.");
00103 memset((char *) &server_addr_rec, 0, sizeof(server_addr_rec));
00104 server_addr_rec.sin_family = AF_INET;
00105 server_addr_rec.sin_port = htons(portno_rec);
00106 server_addr_rec.sin_addr.s_addr = htonl(INADDR_ANY);
00107
00108
00109
00110
00111 server_addr_rec_len = sizeof(server_addr_rec);
00112 server_addr_rec_other_len = sizeof(server_addr_rec_other);
00113 if(bind(sock_rec, (struct sockaddr*)&server_addr_rec, server_addr_rec_len)==-1){
00114 ROS_ERROR("OmnixNode: Error binding recv socket, exiting!");
00115 exit(1);
00116 }
00117
00118 ROS_INFO("Ready for recv communication!");
00119 }
00120
00121 void OmnixNode::closeOmnixSocket()
00122 {
00123 close(sock);
00124 close(sock_rec);
00125 }
00126
00127 void OmnixNode::joyCallback(const sensor_msgs::Joy::ConstPtr& joy)
00128 {
00129 if(joy->buttons[PS3_SHOULDER_L2]){
00130 last_estop_recd = ros::Time::now();
00131 emergency_stop = false;
00132 }
00133 }
00134
00135 void OmnixNode::readTimerCallback(const ros::TimerEvent& e)
00136 {
00137 recvResponse(false);
00138 }
00139
00140 void OmnixNode::timerCallback(const ros::TimerEvent& e)
00141 {
00142
00143 if((ros::Time::now() - last_estop_recd) > estop_timeout_){
00144 emergency_stop = true;
00145 }
00146 if(!emergency_stop){
00147
00148 }
00149
00150
00151
00152
00153 if(recv_odom){
00154
00155 sendGetJointPosition();
00156
00157
00158 tf::Transform odom = tf::Transform(tf::createQuaternionFromYaw(odom_yaw),tf::Point(odom_x,odom_y,0.0));
00159 tf_.sendTransform(tf::StampedTransform(odom, ros::Time::now(),"odom","base_link"));
00160
00161
00162 nav_msgs::Odometry odom_msg;
00163 odom_msg.header.stamp = ros::Time::now();
00164 odom_msg.header.frame_id = "odom";
00165 odom_msg.pose.pose.position.x = odom_x;
00166 odom_msg.pose.pose.position.y = odom_y;
00167 odom_msg.pose.pose.position.z = 0.0;
00168 odom_msg.pose.pose.orientation = tf::createQuaternionMsgFromYaw(odom_yaw);
00169
00170 odom_msg.child_frame_id = "base_link";
00171 odom_msg.twist.twist.linear.x = vx;
00172 odom_msg.twist.twist.linear.y = vy;
00173 odom_msg.twist.twist.angular.z = vt;
00174
00175 for(int i = 0; i < 35; i++){
00176 odom_msg.pose.covariance[i] = 0.000;
00177 odom_msg.twist.covariance[i] = 0.000;
00178 }
00179 odom_msg.pose.covariance[0] = 0.1;
00180 odom_msg.pose.covariance[7] = 0.1;
00181 odom_msg.pose.covariance[14] = 0.1;
00182 odom_msg.pose.covariance[21] = 0.1;
00183 odom_msg.pose.covariance[28] = 0.1;
00184 odom_msg.pose.covariance[35] = 0.1;
00185 odom_msg.twist.covariance[0] = 0.1;
00186 odom_msg.twist.covariance[7] = 0.1;
00187 odom_msg.twist.covariance[14] = 0.1;
00188 odom_msg.twist.covariance[21] = 0.1;
00189 odom_msg.twist.covariance[28] = 0.1;
00190 odom_msg.twist.covariance[35] = 0.1;
00191
00192
00193 odom_pub_.publish(odom_msg);
00194 }
00195 }
00196
00197 bool OmnixNode::sendCommand(const std::string& cmd)
00198 {
00199 char buf[2048];
00200 int c = counter % 1000;
00201 sprintf(buf,"%d %s\n",c,cmd.c_str());
00202 int cmdlen = strlen(buf)+1;
00203 if(sendto(sock,buf,cmdlen,0,(struct sockaddr*)&server_addr,server_addr_len) != cmdlen){
00204 ROS_ERROR("OmnixNode: Error sending on socket to Omnix!");
00205 return false;
00206 }
00207 counter++;
00208
00209
00210 return true;
00211 }
00212
00213 bool OmnixNode::peekForNewline()
00214 {
00215 int recd_size;
00216 int flags = 0 | MSG_PEEK | MSG_DONTWAIT;
00217 bool done = false;
00218 while(!done){
00219 ROS_INFO("Peeking for newline...");
00220 recd_size = recvfrom(sock_rec, rec_buf, rec_buf_size, flags, (struct sockaddr*)&server_addr_rec_other, (socklen_t*)&server_addr_rec_other_len);
00221 ROS_INFO("Got %d bytes",recd_size);
00222 size_t found;
00223 std::string recd_str = std::string(rec_buf);
00224 found = recd_str.find("\n");
00225 if(found==std::string::npos){
00226 ros::Duration(0.1).sleep();
00227 } else {
00228 ROS_INFO("Found a newline!");
00229 done = true;
00230 }
00231 }
00232 }
00233
00234 bool OmnixNode::recvResponse(bool blocking)
00235 {
00236 if(!open_rec_socket){
00237 return false;
00238 }
00239
00240
00241 int recd_size;
00242 int flags = 0;
00243 if(!blocking){
00244 flags |= MSG_DONTWAIT;
00245 }
00246
00247
00248 recd_size = recvfrom(sock_rec, rec_buf, rec_buf_size, flags, (struct sockaddr*)&server_addr_rec_other, (socklen_t*)&server_addr_rec_other_len);
00249
00250 if(recd_size==-1){
00251 if(blocking){
00252 ROS_ERROR("OmnixNode: Error receiving from Omnix socket!");
00253 }
00254 return false;
00255 } else {
00256 if(verbose){
00257 ROS_INFO("Got string: %s \n",rec_buf);
00258 }
00259 }
00260
00261 char* tok_ptr;
00262 tok_ptr = strtok(rec_buf," ");
00263 if(tok_ptr != NULL){
00264 if(strcmp(tok_ptr,"OK")==0){
00265 if(verbose){
00266 ROS_INFO("OmnixNode OK: %s\n",rec_buf);
00267 }
00268 tok_ptr = strtok(NULL," ");
00269
00270 if(tok_ptr == NULL){
00271 ROS_INFO("Error parsing repsonse!");
00272 return false;
00273 }
00274 if(strcmp(tok_ptr,"SOV")==0){
00275 return true;
00276 }
00277 if(strcmp(tok_ptr,"GJP")==0){
00278 double j1,j2,j3,j4 = 0;
00279 tok_ptr = strtok(NULL," ");
00280 if(tok_ptr == NULL){
00281 ROS_INFO("Error parsing repsonse!");
00282 return false;
00283 }
00284 sscanf(tok_ptr,"%lf",&j1);
00285 tok_ptr = strtok(NULL," ");
00286 if(tok_ptr == NULL){
00287 ROS_INFO("Error parsing repsonse!");
00288 return false;
00289 }
00290 sscanf(tok_ptr,"%lf",&j2);
00291 tok_ptr = strtok(NULL," ");
00292 if(tok_ptr == NULL){
00293 ROS_INFO("Error parsing repsonse!");
00294 return false;
00295 }
00296 sscanf(tok_ptr,"%lf",&j3);
00297 tok_ptr = strtok(NULL," ");
00298 if(tok_ptr == NULL){
00299 ROS_INFO("Error parsing repsonse!");
00300 return false;
00301 }
00302 sscanf(tok_ptr,"%lf",&j4);
00303
00304
00305
00306 double dj1 = j1 - prev_j1;
00307 double dj2 = j2 - prev_j2;
00308 double dj3 = j3 - prev_j3;
00309 double dj4 = j4 - prev_j4;
00310
00311
00312 double dx = 0.0;
00313 double dy = 0.0;
00314 double dt = 0.0;
00315
00316 bool rotating = false;
00317 if(((dj2 > 0.0) && (dj4 < 0.0)) || ((dj2 < 0.0) && (dj4 > 0.0))){
00318 rotating = true;
00319
00320 dj3 = -dj1;
00321 } else {
00322
00323 dj3 = dj1;
00324 }
00325
00326 if(true){
00327 dx = (dj1 + dj2 + dj3 + dj4) / 4.0;
00328 dy = (dj1 - dj2 + dj3 - dj4) / 4.0;
00329
00330 dt = -(dj2 - dj4) / 2.0;
00331 } else {
00332
00333
00334 dx = (dj1 + ((dj2 + dj4)/2.0)) / 2.0;
00335 dy = (dj1 + ((-dj2 - dj4)/2.0)) / 2.0;
00336 dt = -(dj2 - dj4) / 2.0;
00337 }
00338
00339
00340
00341 if((dx > 0.01) || (dy > 0.01)){
00342 ROS_INFO("Jump detected: %lf %lf %lf",dx,dy,dt);
00343 ROS_INFO("Joint Jumps: %lf %lf %lf %lf",dj1,dj2,dj3,dj4);
00344 ROS_INFO("Curr joints: %lf %lf %lf %lf", j1, j2, j3, j4);
00345 ROS_INFO("Prev joints: %lf %lf %lf %lf", prev_j1, prev_j2, prev_j3, prev_j4);
00346 }
00347
00348
00349 ros::Duration dtime = ros::Time::now() - prev_time;
00350 vx = dx / dtime.toSec();
00351 vy = dy / dtime.toSec();
00352 vt = dt / dtime.toSec();
00353
00354
00355 odom_x += dx;
00356 odom_y += dy;
00357 odom_yaw += dt;
00358
00359
00360
00361
00362 prev_j1 = j1;
00363 prev_j2 = j2;
00364 prev_j3 = j3;
00365 prev_j4 = j4;
00366 prev_time = ros::Time::now();
00367
00368 }
00369
00370 } else if (strcmp(tok_ptr,"ERR")==0) {
00371 ROS_INFO("OmnixNode ERR: %s\n",rec_buf);
00372 }
00373
00374 } else {
00375 if(blocking){
00376 ROS_INFO("Got NULL str!");
00377 }
00378 }
00379
00380 }
00381
00382 void OmnixNode::sendGetJointPosition()
00383 {
00384 char buf[2048];
00385 int c = counter % 1000;
00386 sprintf(buf,"%d GJP",c);
00387
00388 if(sendto(sock,buf,strlen(buf)+1,0,(struct sockaddr*)&server_addr,sizeof(server_addr)) != strlen(buf)+1){
00389 ROS_ERROR("OmnixNode: Error sending on socket to Omnix!");
00390 }
00391 counter++;
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 }
00453
00454
00455
00456 void OmnixNode::cmdvelCallback(const geometry_msgs::Twist::ConstPtr& cmd_vel)
00457 {
00458 if(joystick_controlled){
00459 ROS_ERROR("OmnixNode: Movement requested while ODV is in hardware joystick-controlled mode. Ignoring!");
00460 return;
00461 }
00462 if(brake_engaged){
00463 ROS_ERROR("OmnixNode: Movement requested while brakes are on. Ignoring!");
00464 return;
00465 }
00466 if(emergency_stop){
00467 if(verbose){
00468 ROS_ERROR("OmnixNode: Velocity Requested without deadman switch signal");
00469 }
00470 return;
00471 }
00472
00473 if(this->first_write){
00474 last_vel_cmd = new geometry_msgs::Twist(*cmd_vel);
00475 this->first_write = false;
00476 }
00477 last_vel_cmd_recd = ros::Time::now();
00478
00479
00480 last_vel_cmd = new geometry_msgs::Twist(*cmd_vel);
00481
00482 char tempbuf[1024];
00483 sprintf(tempbuf," %lf %lf %lf", last_vel_cmd->linear.x, last_vel_cmd->linear.y, last_vel_cmd->angular.z);
00484
00485 std::string vel_string = SetVelocityCommand + std::string(tempbuf);
00486
00487 if(verbose){
00488 ROS_INFO("Would publish: %s",vel_string.c_str());
00489 }
00490 if(ros::Time::now() - last_vel_cmd_sent > ros::Duration(0.1)){
00491 sendCommand(vel_string);
00492 last_vel_cmd_sent = ros::Time::now();
00493 }
00494
00495
00496 if(verbose){
00497 ROS_INFO("OmnixNode: Got vel command: (X: %lf Y: %lf Theta: %lf",cmd_vel->linear.x,cmd_vel->linear.y,cmd_vel->angular.z);
00498 }
00499 }
00500
00501 bool OmnixNode::EngageBrakeCallback(omnix::EngageBrake::Request &req, omnix::EngageBrake::Response &res)
00502 {
00503 if(joystick_controlled){
00504 ROS_ERROR("OmnixNode: ODV currently in hardware joystick controlled mode. Switch this off to first to enable UDP control.");
00505 return false;
00506 }
00507 return sendCommand(EngageBrakeCommand);
00508 }
00509
00510 bool OmnixNode::ReleaseBrakeCallback(omnix::ReleaseBrake::Request &req, omnix::ReleaseBrake::Response &res)
00511 {
00512 if(joystick_controlled){
00513 ROS_ERROR("OmnixNode: ODV currently in hardware joystick controlled mode. Switch this off to first to enable UDP control.");
00514 return false;
00515 }
00516 bool result = sendCommand(ReleaseBrakeCommand);
00517 if(result){
00518 ROS_INFO("OmnixNode: Successfully released brake.");
00519 brake_engaged = false;
00520 recv_odom = true;
00521 } else {
00522 ROS_ERROR("OmnixNode: Error sending RBK command!");
00523 }
00524 }
00525
00526 bool OmnixNode::DisableJoystickCallback(omnix::DisableJoystick::Request &req, omnix::DisableJoystick::Response &res)
00527 {
00528 ROS_INFO("OmnixNode: Disabling joystick control, moving to UDP control.");
00529 bool result = sendCommand(DisableJoystickCommand);
00530 if(result){
00531 ROS_INFO("OmnixNode: Successfully disabled joystick control.");
00532 joystick_controlled = false;
00533 } else {
00534 ROS_ERROR("OmnixNode: Error sending DJS command!");
00535 }
00536 return true;
00537 }
00538
00539
00540 bool OmnixNode::EnableJoystickCallback(omnix::EnableJoystick::Request &req, omnix::EnableJoystickResponse &res)
00541 {
00542 ROS_INFO("OmnixNode: EJS is NYI.");
00543 return false;
00544 }
00545
00546 int main(int argc, char** argv)
00547 {
00548 ros::init(argc, argv, "omnix");
00549 OmnixNode omnix;
00550 ros::spin();
00551 return 0;
00552 }
00553