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