lizi_node.cpp
Go to the documentation of this file.
00001 #include "ros/ros.h"
00002 #include <lizi/lizi_raw.h>
00003 #include <lizi/lizi_gps.h>
00004 #include <lizi/lizi_pan_tilt.h>
00005 #include <lizi/lizi_command.h>
00006 #include <lizi/set_odom.h>
00007 #include "sensor_msgs/Imu.h"
00008 #include "sensor_msgs/Range.h"
00009 #include "sensor_msgs/NavSatFix.h"
00010 #include "sensor_msgs/NavSatStatus.h"
00011 #include <sensor_msgs/JointState.h>
00012 #include "geometry_msgs/Twist.h"
00013 #include "geometry_msgs/Quaternion.h"
00014 #include "geometry_msgs/Vector3Stamped.h"
00015 #include "nav_msgs/Odometry.h"
00016 #include "tf/transform_datatypes.h"
00017 #include <tf/transform_broadcaster.h>
00018 #include <math.h>
00019 
00020 
00021 ros::Publisher left_urf_pub;
00022 ros::Publisher rear_urf_pub;
00023 ros::Publisher right_urf_pub;
00024 
00025 ros::Publisher odom_pub;
00026 ros::Publisher gps_pub;
00027 ros::Publisher imu_pub;
00028 ros::Publisher command_pub;
00029 ros::Publisher pan_tilt_pub;
00030 
00031 
00032 sensor_msgs::Range left_urf_msg;
00033 sensor_msgs::Range rear_urf_msg;
00034 sensor_msgs::Range right_urf_msg;
00035 
00036 std::string lizi_id;
00037 std::string gps_frame_id;
00038 std::string odom_frame_id;
00039 std::string base_frame_id;
00040 std::string imu_frame_id;
00041 std::string cmd_vel_topic;
00042 std::string pan_tilt_topic;
00043 std::string lizi_command_topic;
00044 std::string gps_pub_topic;
00045 std::string set_odom_srv;
00046 std::string odom_topic;
00047 std::string lizi_raw_topic;
00048 std::string lizi_gps_topic;
00049 std::string left_urf_frame_id;
00050 std::string rear_urf_frame_id;
00051 std::string right_urf_frame_id;
00052 std::string pan_joint_id;
00053 std::string tilt_joint_id;
00054 std::string FR_joint_id;
00055 std::string FL_joint_id;
00056 std::string RR_joint_id;
00057 std::string RL_joint_id;
00058 
00059 std::string joint_states_topic;
00060 
00061 sensor_msgs::JointState jointstate_msg;
00062 
00063 tf::TransformBroadcaster *imu_broadcaster;
00064 tf::TransformBroadcaster *odom_broadcaster;
00065 
00066 double wheel_base_length;
00067 double wheel_diameter;
00068 double encoder_cpr; //=ppr*4
00069 
00070 int l_encoder=0,pre_l_encoder=0;
00071 int r_encoder=0,pre_r_encoder=0;
00072 geometry_msgs::Quaternion q_imu;
00073 double xx = 0, yy = 0, tt = 0;
00074 bool first_enc_read = true;
00075 
00076 bool fuse_imu_roll_pitch;
00077 bool fuse_imu_yaw;
00078 double slip_factor;
00079 
00080 double rot_cov = 0.0;
00081 double pos_cov = 0.0;
00082 ros::Time prev_time;
00083 
00084 bool wd_on=false;
00085 ros::Time wd_time;
00086 
00087 double pan=0;
00088 double tilt=0;
00089 
00090 
00091 
00092 void cmd_velCallback(const geometry_msgs::Twist::ConstPtr& msg) {
00093         
00094         if (wd_on) wd_on=false;
00095         
00096         wd_time = ros::Time::now();
00097         
00098         
00099         double Right_Motor_v = msg->linear.x + msg->angular.z * (wheel_base_length / 2.0);
00100         double Left_Motor_v =  msg->linear.x - msg->angular.z * (wheel_base_length / 2.0);
00101 
00102         lizi::lizi_command command_msg;
00103         command_msg.left_wheel=(int)(Left_Motor_v*encoder_cpr/(M_PI * wheel_diameter)); //tick per sec
00104         command_msg.right_wheel=(int)(Right_Motor_v*encoder_cpr/(M_PI * wheel_diameter)); //tick per sec
00105         command_pub.publish(command_msg);
00106 
00107 
00108 
00109 }
00110 
00111 double wrapToPi(double angle) {
00112         angle += M_PI;
00113         bool is_neg = (angle < 0);
00114         angle = fmod(angle, (2.0 * M_PI));
00115         if (is_neg) {
00116                 angle += (2.0 * M_PI);
00117         }
00118         angle -= M_PI;
00119         return angle;
00120 }
00121 
00122 void encodersCallback(int32_t left_ticks, int32_t right_ticks) {
00123         
00124         ros::Time now = ros::Time::now();
00125                 double delta_time = (now - prev_time).toSec();
00126                 prev_time = now;
00127         
00128                 pre_l_encoder=l_encoder;
00129                 pre_r_encoder=r_encoder;
00130                                 
00131                 l_encoder = left_ticks;
00132                 r_encoder = right_ticks;
00133         
00134 
00136                 double l_tics_per_s=(double)(l_encoder-pre_l_encoder)/delta_time;
00137                 double r_tics_per_s=(double)(r_encoder-pre_r_encoder)/delta_time;
00138                 
00139                 double l_w = l_tics_per_s * 2.0 * M_PI / (double) encoder_cpr;
00140                         double r_w = r_tics_per_s * 2.0 * M_PI / (double) encoder_cpr;
00141                         
00142                 
00143                 
00144                 double l_v = l_w * wheel_diameter / 2.0;
00145                 double r_v = r_w * wheel_diameter / 2.0;
00146 
00147                 double v = (l_v + r_v) / 2.0;
00148 
00149                 double w = (r_v - l_v) / wheel_base_length;
00150 
00151                 if (first_enc_read) {
00152 
00153                                 xx = 0;
00154                                 yy = 0;
00155                                 tt = 0;
00156                                 first_enc_read = false;
00157                         }
00158                 
00159                 tt = tt + w * delta_time*slip_factor;
00160                 tt = wrapToPi(tt);
00161                 xx = xx + (v * cos(tt))*delta_time;
00162                 yy = yy + (v * sin(tt))*delta_time;
00163 
00164                 
00165                 
00166                 nav_msgs::Odometry odom_msg;
00167 
00168                 geometry_msgs::Quaternion q_odom;
00169                 
00170                 odom_msg.header.stamp = now;
00171                 odom_msg.header.frame_id = odom_frame_id;
00172                 odom_msg.pose.pose.position.x = xx;
00173                 odom_msg.pose.pose.position.y = yy;
00174                 odom_msg.pose.pose.position.z = 0;
00175                 double roll = 0, pitch = 0, yaw = 0;
00176                 if ((fuse_imu_roll_pitch)&&(fuse_imu_yaw)) {
00177                         q_odom =q_imu;  
00178                         tf::Quaternion q;               
00179                         tf::quaternionMsgToTF(q_imu, q);                                
00180                         tf::Matrix3x3(q).getRPY(roll, pitch, yaw);
00181                         tt=yaw;         
00182                 }
00183                 else if ((!fuse_imu_roll_pitch)&&(fuse_imu_yaw)) {
00184                         tf::Quaternion q;               
00185                         tf::quaternionMsgToTF(q_imu, q);                                
00186                         tf::Matrix3x3(q).getRPY(roll, pitch, yaw);      
00187                         q_odom =tf::createQuaternionMsgFromRollPitchYaw(0,0, yaw);
00188                         tt=yaw;
00189                 }
00190                 else if ((fuse_imu_roll_pitch)&&(!fuse_imu_yaw)) {
00191                                         tf::Quaternion q;               
00192                                         tf::quaternionMsgToTF(q_imu, q);                                
00193                                         tf::Matrix3x3(q).getRPY(roll, pitch, yaw);      
00194                                         q_odom =tf::createQuaternionMsgFromRollPitchYaw(roll,pitch, tt);
00195                                 }       
00196                 else if ((!fuse_imu_roll_pitch)&&(!fuse_imu_yaw)) {
00197                         q_odom =tf::createQuaternionMsgFromRollPitchYaw(0,0, tt);
00198                 }
00199         
00200                 odom_msg.pose.pose.orientation=q_odom;
00201                 
00202                 odom_msg.child_frame_id = base_frame_id;
00203                 odom_msg.twist.twist.linear.x = v;
00204                 odom_msg.twist.twist.linear.y = 0;
00205                 odom_msg.twist.twist.angular.z = w;
00206 
00207                 odom_msg.pose.covariance[0] = pos_cov;
00208                 odom_msg.pose.covariance[7] = pos_cov;
00209                 odom_msg.pose.covariance[14] = 1e100;
00210                 odom_msg.pose.covariance[21] = 1e100;
00211                 odom_msg.pose.covariance[28] = 1e100;
00212                 odom_msg.pose.covariance[35] = rot_cov;
00213                 odom_msg.twist.covariance = odom_msg.pose.covariance;
00214 
00215                 odom_pub.publish(odom_msg);
00216 
00217                 //Add TF broadcaster
00218                 geometry_msgs::TransformStamped odom_trans;
00219                 odom_trans.header.stamp = now;
00220                 odom_trans.header.frame_id = odom_frame_id;
00221                 odom_trans.child_frame_id = base_frame_id;
00222                 odom_trans.transform.translation.x = xx;
00223                 odom_trans.transform.translation.y = yy;
00224                 odom_trans.transform.translation.z = 0.0;
00225         odom_trans.transform.rotation = q_odom;
00226         
00227                         
00228                 odom_broadcaster->sendTransform(odom_trans);
00229 
00230 
00231         jointstate_msg.header.stamp = ros::Time::now();
00232         jointstate_msg.position[0]=pan;
00233         jointstate_msg.position[1]=tilt;
00234 
00235         //TODO: Publish wheels joints
00236 
00237         pan_tilt_pub.publish(jointstate_msg);
00238 
00239 }
00240 
00241 void gpsCallback(const lizi::lizi_gps::ConstPtr& msg) {
00242 
00243         
00244         sensor_msgs::NavSatFix gps_msg;
00245         gps_msg.header.frame_id = gps_frame_id;
00246         gps_msg.header.stamp = ros::Time::now();
00247         gps_msg.latitude = msg->Lat;
00248         gps_msg.longitude = msg->Lon;
00249         gps_msg.altitude = msg->Alt;
00250 
00251         sensor_msgs::NavSatStatus gps_status_msg;
00252 
00253         gps_status_msg.service = 1; //SERVICE_GPS;
00254         if (msg->Status == 0) {
00255                 gps_status_msg.status = 1; //STATUS_NO_FIX;
00256         }
00257         else {//==1
00258                 gps_status_msg.status = 0; //STATUS_FIX;
00259         //ROS_INFO("lat:%.7f  lon:%.7f",msg->Lat,msg->Lon  );
00260         }
00261 
00262         gps_msg.status = gps_status_msg;
00263 
00264         gps_msg.position_covariance_type = 1;
00265         //uint8 COVARIANCE_TYPE_UNKNOWN = 0
00266         //uint8 COVARIANCE_TYPE_APPROXIMATED = 1
00267         //uint8 COVARIANCE_TYPE_DIAGONAL_KNOWN = 2
00268         //uint8 COVARIANCE_TYPE_KNOWN = 3
00269         //float64[9] position_covariance;
00270         
00271         float cov =  (msg->HDOP) * (msg->HDOP);  //TODO: CHECK UNITS /100
00272         gps_msg.position_covariance[0] = cov;
00273         gps_msg.position_covariance[4] = cov;
00274         gps_msg.position_covariance[8] = cov;
00275 
00276         gps_pub.publish(gps_msg);
00277         //gps status:
00278         //NO_GPS = 0,             ///< No GPS connected/detected
00279         //  NO_FIX = 1,             ///< Receiving valid GPS messages but no lock
00280         //  GPS_OK = 2              ///< Receiving valid messages and locked
00281 }
00282 
00283 void urfCallback(float left_urf,float rear_urf,float right_urf) {
00284         
00285         
00286         ros::Time now = ros::Time::now();
00287 
00288         left_urf_msg.header.stamp = now;
00289         left_urf_msg.range = left_urf ;
00290 
00291         rear_urf_msg.header.stamp = now;
00292         rear_urf_msg.range = rear_urf ;
00293         
00294         right_urf_msg.header.stamp = now;
00295         right_urf_msg.range = right_urf ;
00296 
00297         
00298         left_urf_pub.publish(left_urf_msg);
00299         rear_urf_pub.publish(rear_urf_msg);
00300         right_urf_pub.publish(right_urf_msg);
00301         
00302 }
00303 
00304 
00305 
00306 void imuCallback(float qw,float qx,float qy,float qz) {
00307 
00308 
00309         sensor_msgs::Imu imu_msg;
00310         
00311         imu_msg.header.frame_id = imu_frame_id;
00312         imu_msg.header.stamp = ros::Time::now();
00313         q_imu.w=qw;
00314         q_imu.x=qx;
00315         q_imu.y=qy;
00316         q_imu.z=qz;
00317         
00318         double roll = 0, pitch = 0, yaw = 0;                                                    
00319         tf::Quaternion q;                       
00320         tf::quaternionMsgToTF(q_imu, q);                                                        
00321         tf::Matrix3x3(q).getRPY(roll, pitch, yaw);
00322         
00323         q_imu =tf::createQuaternionMsgFromRollPitchYaw(roll,-pitch, -yaw);
00324 
00325         imu_msg.orientation=q_imu;
00326                 
00327 
00328         double angular_velocity_stdev_ = 0.012;
00329         double orientation_stdev_ = 0.035;
00330         double linear_acceleration_stdev_ = 0.098;
00331         
00332         double angular_velocity_covariance = angular_velocity_stdev_
00333                         * angular_velocity_stdev_;
00334         double orientation_covariance = orientation_stdev_ * orientation_stdev_;
00335         double linear_acceleration_covariance = linear_acceleration_stdev_
00336                         * linear_acceleration_stdev_;
00337 
00338         imu_msg.linear_acceleration_covariance[0] = linear_acceleration_covariance;
00339         imu_msg.linear_acceleration_covariance[4] = linear_acceleration_covariance;
00340         imu_msg.linear_acceleration_covariance[8] = linear_acceleration_covariance;
00341 
00342         imu_msg.angular_velocity_covariance[0] = angular_velocity_covariance;
00343         imu_msg.angular_velocity_covariance[4] = angular_velocity_covariance;
00344         imu_msg.angular_velocity_covariance[8] = angular_velocity_covariance;
00345 
00346         imu_msg.orientation_covariance[0] = orientation_covariance;
00347         imu_msg.orientation_covariance[4] = orientation_covariance;
00348         imu_msg.orientation_covariance[8] = orientation_covariance;
00349         imu_pub.publish(imu_msg);
00350         
00351         /*
00352         geometry_msgs::TransformStamped imu_trans;
00353          imu_trans.header.stamp = ros::Time::now();
00354          imu_trans.header.frame_id = odom_frame_id;
00355          imu_trans.child_frame_id = imu_frame_id;
00356          imu_trans.transform.rotation=q_imu;
00357 
00358          imu_broadcaster->sendTransform(imu_trans);
00359 */
00360 
00361 
00362 }
00363 void rawCallback(const lizi::lizi_raw::ConstPtr& msg) {
00364 float qw=msg->qw;
00365 float qx=msg->qx;
00366 float qy=msg->qy;
00367 float qz=msg->qz;
00368 imuCallback(qw,qx,qy,qz);
00369 
00370 int32_t left_ticks=msg->left_ticks;
00371 int32_t right_ticks=msg->right_ticks;
00372 encodersCallback( left_ticks,  right_ticks);
00373 
00374 float left_urf=msg->left_urf;
00375 float rear_urf=msg->rear_urf;
00376 float right_urf=msg->right_urf;
00377 urfCallback(left_urf, rear_urf, right_urf);
00378 
00379 }
00380 
00381 bool set_odom(lizi::set_odom::Request  &req, lizi::set_odom::Response &res)
00382 {
00383 
00384         xx=req.x;
00385         yy=req.y;
00386         tt=req.theta;
00387  ROS_INFO("Set odometry to: x=%.3f, y=%.3f, theta=%.3f", xx, yy,tt);
00388  
00389  return true;
00390 }
00391 
00392 
00393 void pan_tiltCallback(const lizi::lizi_pan_tilt::ConstPtr& msg) {
00394 
00395         
00396         
00397         pan=-1.0*msg->pan_angle;
00398         tilt=-1.0*msg->tilt_angle;
00399         if (pan*180/M_PI>35) pan=35*M_PI/180;
00400         else if (pan*180/M_PI<-35) pan=-35*M_PI/180;
00401 
00402         if (tilt*180/M_PI>30) tilt=30*M_PI/180;
00403         else if (tilt*180/M_PI<-30) tilt=-30*M_PI/180;
00404 
00405 
00406 }
00407 int main(int argc, char **argv) {
00408 
00409         // ros::init(argc, argv, "apm_talker");
00410         ros::init(argc, argv, "lizi_node", ros::init_options::AnonymousName);
00411 
00412         ros::NodeHandle n;
00413         int liziID;
00414         n.param("Lizi_ID", lizi_id, std::string("0"));
00415 
00416         std::string pre="lizi_";
00417         pre+=lizi_id;
00418         n.param("GPS_frame_id", gps_frame_id, std::string("/map"));
00419         
00420 
00421         std::string pre1="lizi_";
00422         pre1+=lizi_id;
00423         n.param("odom_frame_id", odom_frame_id, std::string(pre1+"_odom"));
00424         n.param("base_frame_id", base_frame_id, std::string(pre1+"_base_link"));
00425         n.param("imu_frame_id", imu_frame_id, std::string(pre1+"_imu_link"));
00426         n.param("left_urf_frame_id", left_urf_frame_id, std::string(pre1+"_Left_URF_link"));
00427         n.param("rear_urf_frame_id", rear_urf_frame_id, std::string(pre1+"_Rear_URF_link"));
00428         n.param("right_urf_frame_id", right_urf_frame_id, std::string(pre1+"_Right_URF_link"));
00429         n.param("pan_joint_id", pan_joint_id, std::string(pre1+"_Asus_Pan_Joint"));
00430         n.param("tilt_joint_id", tilt_joint_id, std::string(pre1+"_Asus_Tilt_Joint"));
00431         n.param("FR_joint_id", FR_joint_id, std::string(pre1+"_FR_Wheel_Joint"));
00432         n.param("FL_joint_id", FL_joint_id, std::string(pre1+"_FL_Wheel_Joint"));
00433         n.param("RR_joint_id", RR_joint_id, std::string(pre1+"_RR_Wheel_Joint"));
00434         n.param("RL_joint_id", RL_joint_id, std::string(pre1+"_RL_Wheel_Joint"));
00435 
00436 
00437         n.param("cmd_vel_sub_topic", cmd_vel_topic, std::string("cmd_vel"));
00438         n.param("pan_tilt_sub_topic", pan_tilt_topic, std::string("pan_tilt"));
00439         
00440         n.param("lizi_raw_sub_topic", lizi_raw_topic, std::string("lizi_raw"));
00441         n.param("lizi_gps_sub_topic", lizi_gps_topic, std::string("raw_gps"));
00442 
00443         n.param("odom_pub_topic", odom_topic, std::string("odom_pub"));
00444         n.param("gps_pub_topic", gps_pub_topic, std::string("gps_pub"));        
00445 
00446         n.param("joint_states_topic", joint_states_topic, std::string("joint_states")); 
00447 
00448         n.param("lizi_command_pub_topic", lizi_command_topic, std::string("command"));
00449 
00450         n.param("set_odom_srv", set_odom_srv, std::string("set_odom"));
00451 
00452         n.param("wheel_diameter", wheel_diameter, 0.12);
00453         n.param("wheel_base_length", wheel_base_length, 0.275);
00454         n.param("encoder_cpr", encoder_cpr, 4288.0);
00455         n.param("rotation_covariance", rot_cov, 1.0);
00456         n.param("position_covariance", pos_cov, 1.0);
00457         n.param("fuse_imu_roll_pitch", fuse_imu_roll_pitch, true);
00458         n.param("fuse_imu_yaw", fuse_imu_yaw, false);
00459         n.param("slip_factor", slip_factor, 0.85); 
00460         
00461         q_imu.x=0;
00462         q_imu.y=0;
00463         q_imu.z=1;
00464         q_imu.w=0;
00465         
00466 
00467         ros::ServiceServer service = n.advertiseService(set_odom_srv, set_odom);
00468                 
00469         
00470         ros::Subscriber raw_sub = n.subscribe(lizi_raw_topic, 10, rawCallback);
00471         ros::Subscriber gps_sub = n.subscribe(lizi_gps_topic, 10, gpsCallback);
00472         ros::Subscriber vel_sub = n.subscribe(cmd_vel_topic, 5, cmd_velCallback);
00473 
00474         ros::Subscriber pan_tilt_sub = n.subscribe(pan_tilt_topic, 1, pan_tiltCallback);
00475 
00476         imu_pub = n.advertise < sensor_msgs::Imu > ("imu_pub", 10);
00477 
00478         
00479         jointstate_msg.name.push_back(pan_joint_id);
00480         jointstate_msg.position.push_back(0);
00481         jointstate_msg.name.push_back(tilt_joint_id);
00482         jointstate_msg.position.push_back(0);
00483 
00484         jointstate_msg.name.push_back(FR_joint_id);
00485         jointstate_msg.position.push_back(0);
00486         jointstate_msg.name.push_back(FL_joint_id);
00487         jointstate_msg.position.push_back(0);
00488         jointstate_msg.name.push_back(RR_joint_id);
00489         jointstate_msg.position.push_back(0);
00490         jointstate_msg.name.push_back(RL_joint_id);
00491         jointstate_msg.position.push_back(0);
00492 
00493         right_urf_msg.header.frame_id = right_urf_frame_id;
00494         right_urf_msg.field_of_view = 0.7;
00495         right_urf_msg.radiation_type = 0; //us
00496         right_urf_msg.min_range = 0.25;
00497         right_urf_msg.max_range = 6;
00498 
00499         rear_urf_msg.header.frame_id = rear_urf_frame_id;
00500         rear_urf_msg.field_of_view = 0.7;
00501         rear_urf_msg.radiation_type = 0; //us
00502         rear_urf_msg.min_range = 0.25;
00503         rear_urf_msg.max_range = 6;
00504 
00505         left_urf_msg.header.frame_id = left_urf_frame_id;
00506         left_urf_msg.field_of_view = 0.7;
00507         left_urf_msg.radiation_type = 0; //us
00508         left_urf_msg.min_range = 0.25;
00509         left_urf_msg.max_range = 6;
00510 
00511 
00512         right_urf_pub = n.advertise < sensor_msgs::Range > ("Rangers/Right_URF", 5);
00513         rear_urf_pub = n.advertise < sensor_msgs::Range > ("Rangers/Rear_URF", 5);
00514         left_urf_pub = n.advertise < sensor_msgs::Range > ("Rangers/Left_URF", 5);
00515         
00516         odom_pub = n.advertise < nav_msgs::Odometry > (odom_topic, 10);
00517 
00518 
00519         command_pub = n.advertise < lizi::lizi_command > (lizi_command_topic, 5);
00520         pan_tilt_pub = n.advertise < sensor_msgs::JointState > (joint_states_topic, 5); //
00521 
00522         //pan_tilt_pub.publish(jointstate_msg);
00523 
00524         gps_pub = n.advertise < sensor_msgs::NavSatFix > (gps_pub_topic, 5);
00525 
00526 
00527         imu_broadcaster = new tf::TransformBroadcaster;
00528 
00529         odom_broadcaster = new tf::TransformBroadcaster;
00530         wd_time=ros::Time::now();
00531         while (n.ok()) {
00532 
00533 /*       if (((ros::Time::now() - wd_time).toSec()>3)&&(!wd_on)) {          
00534                  wd_on=true;
00535                  lizi::lizi_command command_msg;                
00536                  command_msg.left_wheel=0;
00537                  command_msg.right_wheel=0;             
00538                  command_pub.publish(command_msg);
00539          }*/
00540          ros::spinOnce();
00541         }
00542                 
00543         //ros::spin();
00544 
00545         return 0;
00546 }
00547 


lizi
Author(s): RoboTiCan
autogenerated on Wed Aug 26 2015 12:24:18