omnix.cpp
Go to the documentation of this file.
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   //n_.param("omnix_ip_addr",hostname,std::string("127.0.0.1"));
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   //wheel_pos_pub_ = n_.advertise<omnix::WheelPos>("/wheel_pos",1);
00035 
00036   //get_joint_position_service_ = n_.advertiseService("/get_joint_position",&OmnixNode::
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   //host = gethostbyname(hostname.c_str());
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   //host = gethostbyname(hostname.c_str());
00094   //gethostbyname(hostname.c_str());
00095   //ROS_INFO("Got host by name");
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 //if(inet_aton(hostname.c_str(), &server_addr_rec.sin_addr)==0){
00108   //    ROS_ERROR("OmnixNode: inet_aton() failed.  Exiting!");
00109   //    exit(1);
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   //Check the emergency stop!
00143   if((ros::Time::now() - last_estop_recd) > estop_timeout_){
00144     emergency_stop = true;
00145   }
00146   if(!emergency_stop){
00147     
00148   }
00149 
00150   //check for data in the pipe
00151   //recvResponse(false);
00152   //Update odom info
00153   if(recv_odom){
00154   //if(false){
00155     sendGetJointPosition();
00156 
00157     //Publish odom via tf
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     //Publish odom via odom
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   //recvResponse();
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   //peekForNewline();
00240 
00241   int recd_size;
00242   int flags = 0;
00243   if(!blocking){
00244     flags |= MSG_DONTWAIT;
00245   }
00246 
00247   //ROS_INFO("Waiting for response from platform.");
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   //ROS_INFO("Got %d bytes",recd_size);
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         //ROS_INFO("Wheel pos: %lf %lf %lf %lf",j1,j2,j3,j4);
00305         //Calc delta joint positions
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         //get delta platform pose from joint positions
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           //ROS_INFO("Rotating!");
00320           dj3 = -dj1;
00321         } else {
00322           //ROS_INFO("Not rotating!");
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           //dt = (dj1 + dj2 - dj3 - dj4) / 4.0;
00330           dt = -(dj2 - dj4) / 2.0; 
00331         } else {
00332           //dx = ((dj1*2.0) + dj2 + dj4) / 3.0;
00333           //dy = ((dj1*2.0) - dj2 - dj4) / 3.0;
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         //ROS_INFO("dx: %lf dy: %lf dt: %lf",dx,dy,dt);
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         //Calc platform velocities
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         //integrate it with previous pose info
00355         odom_x += dx;
00356         odom_y += dy;
00357         odom_yaw += dt;
00358         //ROS_INFO("Platform pos: %lf %lf %lf",odom_x,odom_y,odom_yaw);
00359         //ROS_INFO("Platform vel: %lf %lf %lf",vx,vy,vt);
00360         
00361         //Store previous joint info
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   //ROS_INFO("Sending GJP command!");
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   //recvResponse();
00394   /*
00395   ROS_INFO("Receiving response from platform!");
00396   
00397   //if(recvfrom(sock, rec_buf, rec_buf_size, 0, (struct sockaddr*)&server_addr, sizeof(server_addr)==-1)){
00398   int recd_size;
00399   //int flags = 0 | MSG_DONTWAIT;
00400   int flags = 0;
00401   recd_size = recvfrom(sock_rec, rec_buf, strlen(rec_buf)+1, flags, (struct sockaddr*)&server_addr_rec_other, (socklen_t*)&server_addr_rec_other_len);
00402   ROS_INFO("Got %d bytes",recd_size);
00403   if(recd_size==-1){
00404       ROS_ERROR("OmnixNode: Error receiving from Omnix socket!");
00405   }
00406   ROS_INFO("Got string: %s \n",rec_buf);
00407   double j1,j2,j3,j4 = 0;
00408   ROS_INFO("calling sscanf!");
00409   sscanf(rec_buf,"OK GJP %lf %lf %lf %lf",&j1,&j2,&j3,&j4);
00410   ROS_INFO("Wheel pos: %lf %lf %lf %lf",j1,j2,j3,j4);
00411   omnix::WheelPos wmsg;
00412   wmsg.j1 = j1;
00413   wmsg.j2 = j2;
00414   wmsg.j3 = j3;
00415   wmsg.j4 = j4;
00416   wheel_pos_pub_.publish(wmsg);
00417 
00418   //Calc delta joint positions
00419   double dj1 = j1 - prev_j1;
00420   double dj2 = j2 - prev_j2;
00421   double dj3 = j3 - prev_j3;
00422   double dj4 = j4 - prev_j4;
00423 
00424   //get delta platform pose from joint positions
00425   double dx = (dj1 + dj2 + dj3 + dj4) / 4.0;
00426   double dy = (dj1 - dj2 + dj3 - dj4) / 4.0;
00427   double dt = (dj1 + dj2 - dj3 - dj4) / 4.0;
00428   ROS_INFO("dx: %lf dy: %lf dt: %lf",dx,dy,dt);
00429 
00430   //Calc platform velocities
00431   ros::Duration dtime = ros::Time::now() - prev_time;
00432   vx = dx / dtime.toSec();
00433   vy = dy / dtime.toSec();
00434   vt = dt / dtime.toSec();
00435 
00436   //integrate it with previous pose info
00437   odom_x += dx;
00438   odom_y += dy;
00439   odom_yaw += dt;
00440   ROS_INFO("Platform pos: %lf %lf %lf",odom_x,odom_y,odom_yaw);
00441   ROS_INFO("Platform vel: %lf %lf %lf",vx,vy,vt);
00442 
00443   //Store previous joint info
00444   prev_j1 = j1;
00445   prev_j2 = j2;
00446   prev_j3 = j3;
00447   prev_j4 = j4;
00448   prev_time = ros::Time::now();
00449   */
00450   //Note: publication happens in the timer callback.
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   //  if((last_vel_cmd->linear.x != cmd_vel->linear.x) || (last_vel_cmd->linear.y != cmd_vel->linear.y) || (last_vel_cmd->angular.z != cmd_vel->angular.z)){
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       //build up a command!
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 //TODO: Implement this.
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 


omnix
Author(s): Alexander J Trevor
autogenerated on Wed Nov 27 2013 12:06:10