openni_thermo_node.cpp
Go to the documentation of this file.
00001 #include "openni_cam.h"
00002 
00003 #include <ros/ros.h>
00004 #include <image_transport/image_transport.h>
00005 #include <sensor_msgs/image_encodings.h>
00006 //
00007 //
00008 //
00009 #include <sensor_msgs/CameraInfo.h>
00010 #include <geometry_msgs/TransformStamped.h>
00011 #include <openni_cam/thermo_info.h>
00012 //#include <tf/tf.h>
00013 //#include <tf/transform_listener.h>
00014 //#include <tf/transform_datatypes.h>
00015 //#include <tf/transform_broadcaster.h>
00016 //
00017 //
00018 //
00019 #include <stdio.h>
00020 //#include "error.h"
00021 #include <cmath>
00022 
00023 #include "camera.h"
00024 #include <stdio.h>
00025 #include "error.h"
00026 
00027 #include "include/Imager.h"
00028 #include "ImagerUVC.h"
00029 
00030 #include <QtGui/QApplication>
00031 #include <QtGui/QKeyEvent>
00032 
00033 using namespace optris;
00034 using namespace exttype;
00035 
00036 image_transport::Publisher publisher1;
00037 image_transport::Publisher publisher2;
00038 image_transport::Publisher publisher_ir;
00039 //image_transport::Publisher publisher_ir2;
00040 ros::Publisher publisher_rgb_info;
00041 ros::Publisher publisher_ir_info;
00042 ros::Publisher publisher_ir_info1;
00043 //
00044 //
00045 //
00046 //
00047 class thermo_node {
00048 public:
00049     camera cam;
00050     Imager * imager;
00051     unsigned long serial;
00052     int Width;
00053     int Height;
00054     int count;
00055     int acq_count;
00056     bool frame_acquired;
00057     bool frame_processed;
00058     bool recali;
00059     unsigned short int bimage[5];
00060     dynamic::num_array<unsigned short int,2> image;
00061     dynamic::num_array<float,2> ftemp;
00062     //dynamic::num_array<unsigned char,2> int8ftemp;
00063     //dynamic::num_array<unsigned char,2> image_normalized;
00064     float t_max;
00065     float t_min;
00066     float t_med;
00067     //dynamic::num_array<unsigned short int,2> image;
00068 public:
00069 
00070     unsigned char * buff;
00071 
00072     thermo_node():buff(0) {
00073     };
00074 
00075     ~thermo_node() {
00076         if(buff)delete buff;
00077         delete imager;
00078     };
00079     void init(fptrOptrisFrame pOnFrame) {
00080         cam.find_device();
00081         cam.init_device();
00082         Width = cam.width;
00083         Height = cam.height-1;
00084         serial = cam.dev_serial;
00085         int frequency = cam.frequency;
00086 
00087         imager = new Imager(serial, Width, Height+1, frequency, "../../thermo_cam/data/config/12050017.xml");
00088         count = 0;
00089         imager->forceRecalibration();
00090         buff = new unsigned char[Width*(Height+1)*2];
00091         imager->setFrameCallback(pOnFrame);
00092         bimage[0] = 0;
00093         acq_count = 0;
00094         recali = true;
00095     };
00096     void triger() {
00097         //if(count==0) {
00098         //    printf("thermo_node %4.4i  ",(count%10000));
00099         //    fflush(stdout);
00100         //};
00101         cam.get_image();
00102         //const char * psym = "-\\|/";
00103         //std::cout<<"\b"<<psym[count % 4];fflush(stdout);
00104         //printf("\b\b\b\b%4.4i",(count%10000));
00105         //fflush(stdout);
00106     };
00107 
00108     void process() {
00109         imager->process((unsigned char *)cam.buffer.start);
00110     };
00111 
00112     void force_recali() {
00113         imager->forceRecalibration();
00114         recali = true;
00115         for(int i=0;i<5;++i){
00116             get_image();
00117         };
00118     };
00119 
00120     void get_image() {
00121         frame_acquired = false;
00122         while(!frame_acquired) {
00123             triger();
00124             process();
00125             const char * psym = "-\\|/";
00126             std::cout<<"\b"<<psym[count % 4];
00127             fflush(stdout);
00128             ++count;
00129         };
00130         ++acq_count;
00131         recali = false;
00132         //filter_ir();
00133     };
00134 
00135  /*
00136     void get_image() {
00137         frame_acquired = false;
00138         while(!frame_acquired) {
00139             triger();
00140             frame_processed = false;
00141             process();
00142             if(0 && !recali) { // normal frame, wait until it is processed
00143                 int i=0;
00144                 for(; i<10 && !frame_processed; ++i) {
00145                     usleep(500);
00146                 };
00147                 if(i>10) {
00148                     std::cout<<" timeout \n";
00149                     fflush(stdout);
00150                 };
00151             } else { //push more frames
00152                 //usleep(1000);
00153                 // print to indicate this case
00154                 const char * psym = "-\\|/";
00155                 std::cout<<"\b"<<psym[count % 4];
00156                 fflush(stdout);
00157             };
00158             ++count;
00159         };
00160         ++acq_count;
00161         recali = false;
00162         filter_ir();
00163     };
00164  */
00165     void filter_ir() {
00166         exttype::mint2 sz = image.size();
00167         dynamic::num_array<float,2> vals; //C
00168         ftemp.resize(sz);
00169         vals.resize(sz);
00170         //image_normalized.resize(sz);
00171         //int8ftemp.resize(sz);
00172         for(int i=0; i<image.length(); ++i) {
00173             vals[i] = ((float)(image[i])-1000.0)*0.1;
00174         };
00175         ftemp << 0;
00176         int Width = sz[0];
00177         int Height = sz[1];
00178 
00179         float max=-1e6;
00180         float min=+1e6;
00181         //median filter
00182         std::vector<float> a;
00183         a.resize(9);
00184         for(int i=1; i<Height-1; ++i) {
00185             for(int j=1; j<Width-1; ++j) {
00186                 //int ii = i*Width+(Width-1+j);
00187                 int ii = i*Width+j;
00188                 a[0] = vals[ii];
00189                 a[1] = vals[ii+1];
00190                 a[2] = vals[ii-1];
00191                 a[3] = vals[ii-Width];
00192                 a[4] = vals[ii+Width];
00193                 a[5] = vals[ii-1-Width];
00194                 a[6] = vals[ii-1+Width];
00195                 a[7] = vals[ii+1-Width];
00196                 a[8] = vals[ii+1+Width];
00197                 std::nth_element(a.begin(),a.begin()+5,a.end());
00198                 float pixel = a[5];
00199                 //src->ftemp[i * Width+Width-1-j] = pixel;
00200                 ftemp(j,i) = pixel;
00201                 //int8ftemp(j,i) = int(pixel);
00202                 if(pixel > max)max = pixel;
00203                 if(pixel < min)min = pixel;
00204             };
00205         };
00206         t_max = max;
00207         t_min = min;
00208         //dynamic::num_array<float,2> a = src->IR;
00209         int med_pos = vals.length()/2;
00210         //std::nth_element(vals.begin(),vals.begin()+med_pos,vals.end());
00211         //t_med = vals[med_pos];
00212         /*
00213         for(int i=0; i<image_normalized.length(); ++i) {
00214             image_normalized[i] = (unsigned char)std::max(0.0,std::min(255.0,((ftemp[i]-t_min)/(t_max-t_min)*255.0)));
00215         };
00216         */
00217     };
00218 
00219     void cbOnFrame(unsigned short* image, unsigned int w, unsigned int h) {
00220         //return;
00221         int num_bytes = Width*Height*2;
00222         //
00223         int i0 = num_bytes/4;
00224         if(bimage[0]==0 || bimage[0]==image[i0]) { //same image, skip it, wait for calibration
00225             bimage[0]=image[i0];
00226             // triger next immediately
00227             frame_acquired = false;
00228             frame_processed = true;
00229             return;
00230         };
00231         //different image, remember
00232         bimage[0]=image[i0];
00233         this->image.resize(mint2(w,h));
00234         memcpy(this->image.begin(),image,num_bytes);
00235         frame_acquired = true;
00236         frame_processed = true;
00237         return;
00238     };
00239 
00240     /*
00241         void cbOnFrame(unsigned short* image, unsigned int w, unsigned int h) {
00242             //return;
00243             ++count;
00244             sensor_msgs::ImagePtr msg(new sensor_msgs::Image());
00245             msg->header.stamp = ros::Time::now();
00246             int num_bytes = Width*Height*2;
00247             msg->data.resize(num_bytes);
00248             memcpy(&msg->data[0],image,num_bytes);
00249             msg->encoding = sensor_msgs::image_encodings::MONO16;
00250             msg->step = 2*Width;
00251             msg->height = Height;
00252             msg->width = Width;
00253             msg->header.frame_id = "";
00254             msg->header.seq = count;
00255             publisher_ir.publish(msg);
00256             frame_acquired = true;
00257         };
00258     */
00259 };
00260 
00261 thermo_node tcam;
00262 openni_cam::openni_cam cam;
00263 
00264 
00265 
00266 //___________________________________________________________
00267 
00268 class myApp : public QApplication {
00269 public:
00270     int count;
00271     int rcount;
00272     int recali_time; // recalibrate every 3 seconds
00273     int loop_rate;
00274 public:
00275     myApp(int & argc, char ** argv, ros::NodeHandle & nhh):QApplication(argc,argv) {
00276         count = 0;
00277         rcount = 0;
00278         recali_time = 10; // recalibrate every 10 seconds
00279         //loop_rate = 5;
00280         nhh.param<int>("loop_rate",loop_rate,5);
00281         startTimer(1000/loop_rate);
00282     };
00283     //
00284     ~myApp() {
00285     };
00286     /*
00287         void cbOnFrame(unsigned short* image, unsigned int w, unsigned int h) {
00288             //return;
00289             int num_bytes = tcam.Width*tcam.Height*2;
00290             //
00291             int i0 = num_bytes/4;
00292             if(tcam.bimage[0]==0 || tcam.bimage[0]==image[i0]){//same image, skip it, wait for calibration
00293                 tcam.bimage[0]=image[i0];
00294                 // triger next immediately
00295                 const char * psym = "-\\|/";
00296                 std::cout<<"\b"<<psym[count % 4];fflush(stdout);
00297                 fflush(stdout);
00298                 tcam.triger();
00299                 tcam.process();
00300                 return;
00301             };
00302             //different image, remember
00303             tcam.bimage[0]=image[i0];
00304             //frame acqured!
00305             //
00306         };
00307     */
00308 
00309     void timerEvent(QTimerEvent * event) {
00310         ros::spinOnce();
00311         if(!ros::ok()) {
00312             printf("quitting");
00313             fflush(stdout);
00314             exit(0);
00315         };
00316         ++rcount;
00317         if(rcount>=recali_time*loop_rate) {
00318             tcam.force_recali();
00319             //cam.get_image();
00320             rcount = 0;
00321         };
00322         //tcam.frame_acquired = false;
00323         tcam.get_image();
00324         //tcam.ready();
00325         ros::Time t1 = ros::Time::now();
00326         cam.get_image();
00327         tcam.get_image();//better synchronization with this
00328         tcam.filter_ir();
00329         printf("\b\b\b\b\b\b\b\b\b\b\b\b%4.4i  %4.4i  ",(count%10000),(count%10000));
00330         //printf("%4.4i  %4.4i  \n",(count%10000),(tcam.count%10000));
00331         fflush(stdout);
00332         ++count;
00333         //
00334         {
00335             // publish temperature image in the float 32 bit format
00336             sensor_msgs::ImagePtr msg(new sensor_msgs::Image());
00337             msg->header.stamp = t1;
00338 
00339             int num_bytes = tcam.ftemp.byte_size();
00340             msg->data.resize(num_bytes);
00341             memcpy(&msg->data[0],tcam.ftemp.begin(),num_bytes);
00342             msg->encoding = sensor_msgs::image_encodings::TYPE_32FC1;
00343             msg->step = tcam.ftemp.byte_stride(0,1);
00344             msg->height = tcam.ftemp.size()[1];
00345             msg->width = tcam.ftemp.size()[0];
00346             //msg->header.frame_id = ss.str().c_str();
00347 
00348             /*
00349             int num_bytes = tcam.int8ftemp.byte_size();
00350             //++tcam.count;
00351             msg->data.resize(num_bytes);
00352             memcpy(&msg->data[0],tcam.int8ftemp.begin(),num_bytes);
00353             msg->encoding = sensor_msgs::image_encodings::MONO8;
00354             msg->step = tcam.int8ftemp.byte_stride(0,1);
00355             msg->width = tcam.int8ftemp.size()[0];
00356             msg->height = tcam.int8ftemp.size()[1];
00357             msg->header.frame_id = "thermo_cam";
00358             */
00359             msg->header.seq = count;
00360             publisher_ir.publish(msg);
00361             //
00362             //
00363             openni_cam::thermo_info info;
00364             //std::stringstream ss;
00365             // ss << tcam.serial;
00366             info.serial = tcam.serial;
00367             info.header.stamp = t1;
00368             info.header.seq = count;
00369             info.header.frame_id = "";
00370             info.t_min = tcam.t_min;
00371             info.t_max = tcam.t_max;
00372             publisher_ir_info1.publish(info);
00373             {
00374                 //publish filtered normalized temperature in the mono8 format
00375                 /*
00376                 int num_bytes = tcam.image_normalized.byte_size();
00377                 //++tcam.count;
00378                 sensor_msgs::ImagePtr msg(new sensor_msgs::Image());
00379                 msg->header.stamp = t1;
00380                 msg->data.resize(num_bytes);
00381                 memcpy(&msg->data[0],tcam.image_normalized.begin(),num_bytes);
00382                 msg->encoding = sensor_msgs::image_encodings::MONO8;
00383                 msg->height = tcam.image_normalized.size()[1];
00384                 msg->width = tcam.image_normalized.size()[0];
00385                 msg->step = msg->width*sizeof(unsigned char);
00386                 msg->header.frame_id = "thermo_camera";
00387                 msg->header.seq = count;
00388                 publisher_ir2.publish(msg);
00389                 */
00390                 /*
00391                 sensor_msgs::ImagePtr msg(new sensor_msgs::Image());
00392                 msg->header.stamp = t1;
00393                 int num_bytes = cam.rgb.byte_size();
00394                 msg->data.resize(num_bytes);
00395                 memcpy(&msg->data[0],cam.rgb.begin(),num_bytes);
00396                 msg->encoding = sensor_msgs::image_encodings::RGB8;
00397                 msg->step = cam.rgb.stride(0,0,1);
00398                 msg->width = cam.rgb.size()[1];
00399                 msg->height = cam.rgb.size()[2];
00400                 msg->header.frame_id = "thermo_camera";
00401                 msg->header.seq = count;
00402                 publisher_ir2.publish(msg);
00403                 */
00404                 //publish camera_info
00405                 sensor_msgs::CameraInfoPtr ci(new sensor_msgs::CameraInfo());
00406                 ci->header = msg->header;
00407                 ci->height = msg->height;
00408                 ci->width = msg->width;
00409                 geom::matrix3 K;
00410                 K << 0;
00411                 //fow 45 deg
00412                 double fx = 1.0/(msg->width/2);
00413                 double fy = 1.0/(msg->height/2);
00414                 K(0,0) = fx;
00415                 K(1,1) = fy;
00416                 K(0,2) = msg->width/2;
00417                 K(1,2) = msg->height/2;
00418                 K(2,2) = 1;
00419                 for(int i=0; i<3; ++i) {
00420                     ci->P[i*4 + 3] = 0;
00421                     for(int j=0; j<3; ++j) {
00422                         ci->R[i*3+j] = (i==j);
00423                         ci->P[i*4+j] = K(i,j);
00424                         ci->K[i*3+j] = K(i,j);
00425                     };
00426                 }
00427                 ci->distortion_model = "";//"plumb_bob";
00428                 //
00429                 ci->roi.height = msg->height;
00430                 ci->roi.width = msg->width;
00431                 ci->binning_x = 1;
00432                 ci->binning_y = 1;
00433                 publisher_ir_info.publish(ci);
00434             }
00435         };
00436         //
00437         {
00438             // publish RGB image
00439             sensor_msgs::ImagePtr msg(new sensor_msgs::Image());
00440             msg->header.stamp = t1;
00441             int num_bytes = cam.rgb.byte_size();
00442             msg->data.resize(num_bytes);
00443             memcpy(&msg->data[0],cam.rgb.begin(),num_bytes);
00444             msg->encoding = sensor_msgs::image_encodings::RGB8;
00445             msg->step = cam.rgb.byte_stride(0,0,1);
00446             msg->width = cam.rgb.size()[1];
00447             msg->height = cam.rgb.size()[2];
00448             msg->header.frame_id = "openni_camera";
00449             msg->header.seq = count;
00450             publisher1.publish(msg);
00451             //
00452             //publish camera_info
00453             sensor_msgs::CameraInfoPtr ci(new sensor_msgs::CameraInfo());
00454             ci->header = msg->header;
00455             ci->height = msg->height;
00456             ci->width = msg->width;
00457             for(int i=0; i<3; ++i) {
00458                 ci->P[i*4 + 3] = 0;
00459                 for(int j=0; j<3; ++j) {
00460                     ci->R[i*3+j] = (i==j);
00461                     ci->P[i*4+j] = cam.K(i,j);
00462                     ci->K[i*3+j] = cam.K(i,j);
00463                 };
00464             }
00465             ci->distortion_model = "";//"plumb_bob";
00466             //
00467             ci->roi.height = msg->height;
00468             ci->roi.width = msg->width;
00469             ci->binning_x = 1;
00470             ci->binning_y = 1;
00471             publisher_rgb_info.publish(ci);
00472             // publish tf
00473             //static tf::TransformBroadcaster br;
00474             //tf::Transform transform;
00475             //transform.setOrigin( tf::Vector3(0, 0.0, 0) );
00476             //transform.setRotation( tf::Quaternion(0, 0, 0) );
00477             //br.sendTransform(tf::StampedTransform(transform, msg->header.stamp, "", "/openni_camera"));
00478         };
00479         {
00480             // publish depth image
00481             sensor_msgs::ImagePtr msg(new sensor_msgs::Image());
00482             msg->header.stamp = t1;
00483             int num_bytes = cam.depth.byte_size();
00484             msg->data.resize(num_bytes);
00485             memcpy(&msg->data[0],cam.depth.begin(),num_bytes);
00486             msg->encoding = sensor_msgs::image_encodings::MONO16;
00487             msg->step = cam.depth.byte_stride(0,1);
00488             msg->width = cam.depth.size()[0];
00489             msg->height = cam.depth.size()[1];
00490             msg->header.frame_id = "openni_camera";
00491             msg->header.seq = count;
00492             publisher2.publish(msg);
00493         };
00494     };
00495     //
00496     //
00497     bool notify(QObject * receiver, QEvent * ev) {
00498         if(ev->type() == QEvent::KeyPress) {
00499             QKeyEvent * e = static_cast<QKeyEvent *>(ev);
00500             //QMessageBox* box = new QMessageBox();
00501             //box->setWindowTitle(QString("Hello"));
00502             //box->setText(QString("You Pressed: ")+ e->text());
00503             //box->show();
00504             if(e->key() == Qt::Key_Return) {
00505                 printf("Return");
00506                 fflush(stdout);
00507                 return true;
00508             } else if(e->key() == Qt::Key_Tab) {
00509                 printf("Tab");
00510                 fflush(stdout);
00511                 return true;
00512             } else if(e->key() == Qt::Key_Escape) {
00513                 printf("ESC");
00514                 fflush(stdout);
00515                 exit(0);
00516                 return true;
00517             };
00518         };
00519         return QApplication::notify(receiver,ev);
00520     };
00521 };
00522 
00523 myApp * a;
00524 
00525 void cbOnFrame(unsigned short* image, unsigned int w, unsigned int h) {
00526     tcam.cbOnFrame(image,w,h);
00527 };
00528 
00529 
00530 int main(int argc, char **argv) {
00531     ros::init(argc, argv, "openni_node");
00532     ros::NodeHandle nh;
00533     ros::NodeHandle nhh("~");
00534     image_transport::ImageTransport it(nh);
00535     publisher1 = it.advertise("openni_camera/rgb", 1);
00536     publisher2 = it.advertise("openni_camera/depth", 1);
00537     publisher_ir = it.advertise("thermo_camera/ftemp", 1);
00538     publisher_ir_info = nh.advertise<sensor_msgs::CameraInfo>("/thermo_camera/camera_info", 1);
00539     publisher_ir_info1 = nh.advertise<openni_cam::thermo_info>("thermo_camera/info", 1);
00540     //publisher_ir2 = it.advertise("thermo_camera/image_normalized", 1);
00541     publisher_rgb_info = nh.advertise<sensor_msgs::CameraInfo>("openni_camera/camera_info", 1);
00542     //
00543     cam.init();
00544     tcam.init(cbOnFrame);
00545     //
00546     printf("openni_thermo_node %4.4i  %4.4i  ",0,0);
00547     fflush(stdout);
00548     //int loop_rate;
00549     //nhh.param<int>("loop_rate",loop_rate,5);
00550     a = new myApp(argc, argv, nhh);
00551     a->exec();
00552     delete a;
00553 };
 All Classes Namespaces Files Functions Variables Typedefs Defines


openni_cam
Author(s): Alexander Shekhovtsov
autogenerated on Sun Dec 1 2013 17:19:20