node.cpp
Go to the documentation of this file.
00001 
00054 #include <sick_3vistort_driver/driver.h>
00055 #include <ros/ros.h>
00056 #include <image_transport/image_transport.h>
00057 #include <sensor_msgs/image_encodings.h>
00058 #include <sensor_msgs/PointCloud2.h>
00059 #include <cv_bridge/cv_bridge.h>
00060 #include <boost/thread.hpp>
00061 #include <sensor_msgs/CameraInfo.h>
00062 #include <std_msgs/ByteMultiArray.h>
00063 
00065 const bool SUPPRESS_INVALID_POINTS = true;
00066 
00068 const uint16_t NARE_DISTANCE_VALUE = 0xffffU;
00069 image_transport::Publisher g_pub_depth, g_pub_confidence, g_pub_intensity;
00070 ros::Publisher g_pub_camera_info, g_pub_points, g_pub_ios;
00071 Driver_3DCS::Control *g_control = NULL;
00072 std::string g_frame_id;
00074 bool g_publish_all = false;
00075 
00076 boost::mutex g_mtx_data;
00077 boost::shared_ptr<Driver_3DCS::Data> g_data;
00078 
00079 void publish_frame(const Driver_3DCS::Data &data);
00080 
00081 void thr_publish_frame() {
00082         g_mtx_data.lock();
00083         publish_frame(*g_data);
00084         g_mtx_data.unlock();
00085 }
00086 
00087 void on_frame(const boost::shared_ptr<Driver_3DCS::Data> &data) {
00088         //update data in queue and
00089         //detach publishing data from network thread
00090         
00091         if(g_publish_all || g_mtx_data.try_lock()) {
00092                 if(g_publish_all)
00093                         g_mtx_data.lock();
00094                 g_data = data;
00095                 g_mtx_data.unlock();
00096                 
00097                 boost::thread thr(thr_publish_frame);
00098         }
00099         else
00100                 ROS_WARN("skipping frame");
00101 }
00102 
00103 void publish_frame(const Driver_3DCS::Data &data) {
00104         bool published_anything = false;
00105         
00106         sensor_msgs::ImagePtr msg;
00107         std_msgs::Header header;
00108         header.stamp = ros::Time::now();
00109         header.frame_id = g_frame_id;
00110         
00111         if(g_pub_camera_info.getNumSubscribers()>0) {
00112                 published_anything = true;
00113                 
00114                 sensor_msgs::CameraInfo ci;
00115                 ci.header = header;
00116                 
00117                 ci.height = data.getCameraParameters().height;
00118                 ci.width  = data.getCameraParameters().width;
00119                 
00120                 ci.D.clear();
00121                 ci.D.resize(5,0);
00122                 ci.D[0] = data.getCameraParameters().k1;
00123                 ci.D[1] = data.getCameraParameters().k2;
00124                 
00125                 for(int i=0; i<9; i++) ci.K[i]=0;
00126                 ci.K[0] = data.getCameraParameters().fx;
00127                 ci.K[4] = data.getCameraParameters().fy;
00128                 ci.K[2] = data.getCameraParameters().cx;
00129                 ci.K[5] = data.getCameraParameters().cy;
00130                 
00131                 for(int i=0; i<12; i++)
00132                         ci.P[i] = 0;//data.getCameraParameters().cam2worldMatrix[i];
00133                 //TODO:....
00134                 ci.P[0] = data.getCameraParameters().fx;
00135                 ci.P[5] = data.getCameraParameters().fy;
00136                 ci.P[10] = 1;
00137                 ci.P[2] = data.getCameraParameters().cx;
00138                 ci.P[6] = data.getCameraParameters().cy;
00139                         
00140                 g_pub_camera_info.publish(ci);
00141         }
00142         
00143         if(g_pub_depth.getNumSubscribers()>0) {
00144                 published_anything = true;
00145                 
00146                 msg = cv_bridge::CvImage(std_msgs::Header(), sensor_msgs::image_encodings::TYPE_16UC1, data.get_distance()).toImageMsg();
00147                 msg->header = header;
00148                 g_pub_depth.publish(msg);
00149         }
00150         if(g_pub_confidence.getNumSubscribers()>0) {
00151                 published_anything = true;
00152                 
00153                 msg = cv_bridge::CvImage(std_msgs::Header(), sensor_msgs::image_encodings::TYPE_16UC1, data.get_confidence()).toImageMsg();
00154                 msg->header = header;
00155                 g_pub_confidence.publish(msg);
00156         }
00157         if(g_pub_intensity.getNumSubscribers()>0) {
00158                 published_anything = true;
00159                 
00160                 msg = cv_bridge::CvImage(std_msgs::Header(), sensor_msgs::image_encodings::TYPE_16UC1, data.get_intensity()).toImageMsg();
00161                 msg->header = header;
00162                 g_pub_intensity.publish(msg);
00163         }
00164         if(g_pub_points.getNumSubscribers()>0) {
00165                 published_anything = true;
00166                 
00167                 typedef sensor_msgs::PointCloud2 PointCloud;
00168                 
00169                 // Allocate new point cloud message
00170                 PointCloud::Ptr cloud_msg (new PointCloud);
00171                 cloud_msg->header = header; // Use depth image time stamp
00172                 cloud_msg->height = data.get_distance().rows;
00173                 cloud_msg->width  = data.get_distance().cols;
00174                 cloud_msg->is_dense = false;
00175                 cloud_msg->is_bigendian = false;
00176 
00177                 cloud_msg->fields.resize (5);
00178                 cloud_msg->fields[0].name = "x"; cloud_msg->fields[1].name = "y"; cloud_msg->fields[2].name = "z";
00179                 cloud_msg->fields[3].name = "confidence"; cloud_msg->fields[4].name = "intensity";
00180                 int offset = 0;
00181                 // All offsets are *4, as all field data types are float32
00182                 for (size_t d = 0; d < cloud_msg->fields.size (); ++d, offset += 4)
00183                 {
00184                         cloud_msg->fields[d].offset = offset;
00185                         cloud_msg->fields[d].datatype = (d<3) ? int(sensor_msgs::PointField::FLOAT32) : int(sensor_msgs::PointField::UINT16);
00186                         cloud_msg->fields[d].count  = 1;
00187                 }
00188                 cloud_msg->point_step = offset;
00189                 cloud_msg->row_step   = cloud_msg->point_step * cloud_msg->width;
00190                 cloud_msg->data.resize (cloud_msg->height * cloud_msg->width * cloud_msg->point_step);
00191 
00192         const float f2rc = data.getCameraParameters().f2rc / 1000.f; // since f2rc is given in [mm], but the pcl message wants [m]
00193                 
00194                 uint16_t *pDepth, *pConf, *pInt;
00195                 int cp=0;
00196                 for(int i = 0; i < data.get_distance().rows; ++i)
00197                 {
00198                         pDepth = (uint16_t*)(data.get_distance()  .data + (data.get_distance()  .step*i) );
00199                         pConf  = (uint16_t*)(data.get_confidence().data + (data.get_confidence().step*i) );
00200                         pInt   = (uint16_t*)(data.get_intensity() .data + (data.get_intensity() .step*i) );
00201                         
00202                         for (int j = 0; j < data.get_distance().cols; ++j, ++cp)
00203                         {
00204                                 if(pDepth[j]==0 || pDepth[j]==NARE_DISTANCE_VALUE) {
00205                                         const float bad_point = std::numeric_limits<float>::quiet_NaN();
00206                                         memcpy (&cloud_msg->data[cp * cloud_msg->point_step + cloud_msg->fields[0].offset], &bad_point, sizeof (float));
00207                                         memcpy (&cloud_msg->data[cp * cloud_msg->point_step + cloud_msg->fields[1].offset], &bad_point, sizeof (float));
00208                                         memcpy (&cloud_msg->data[cp * cloud_msg->point_step + cloud_msg->fields[2].offset], &bad_point, sizeof (float));
00209                                 }
00210                                 else {
00211                                         float xp = (data.getCameraParameters().cx - j) / data.getCameraParameters().fx;
00212                                         float yp = (data.getCameraParameters().cy - i) / data.getCameraParameters().fy;
00213 
00214                                         // Correction of the lens distortion
00215                                         float r2 = (xp * xp + yp * yp);
00216                                         float r4 = r2 * r2;
00217                                         float k = 1 + data.getCameraParameters().k1 * r2 + data.getCameraParameters().k2 * r4;
00218                                         xp = xp * k;
00219                                         yp = yp * k;
00220 
00221                                         // Calculation of the distances
00222                                         float s0 = std::sqrt(xp*xp + yp*yp + 1.f) * 1000.f;
00223 
00224                                         // Calculation of the Cartesian coordinates
00225                                         const float ox = xp * pDepth[j] / s0;
00226                                         const float oy = yp * pDepth[j] / s0;
00227                     const float oz = pDepth[j] / s0 - f2rc;
00228                                         
00229                                         memcpy (&cloud_msg->data[cp * cloud_msg->point_step + cloud_msg->fields[0].offset], &ox, sizeof (float));
00230                                         memcpy (&cloud_msg->data[cp * cloud_msg->point_step + cloud_msg->fields[1].offset], &oy, sizeof (float));
00231                                         memcpy (&cloud_msg->data[cp * cloud_msg->point_step + cloud_msg->fields[2].offset], &oz, sizeof (float));
00232                                 }
00233                                 
00234                                 memcpy (&cloud_msg->data[cp * cloud_msg->point_step + cloud_msg->fields[3].offset], &pConf[j], sizeof (uint16_t));
00235                                 memcpy (&cloud_msg->data[cp * cloud_msg->point_step + cloud_msg->fields[4].offset], &pInt [j], sizeof (uint16_t));
00236                         }
00237                 }
00238                 
00239                 g_pub_points.publish(cloud_msg);
00240         }
00241         
00242         if(!published_anything) {
00243                 if(g_control) g_control->stopStream();
00244         }
00245 }
00246 
00247 void _on_new_subscriber() {        
00248         ROS_DEBUG("Got new subscriber");
00249 
00250         if(!g_control) return;
00251 
00252         bool r=g_control->startStream(); // tell the device to start streaming data
00253         ROS_ASSERT(r);
00254 }
00255 
00256 void on_new_subscriber_ros(const ros::SingleSubscriberPublisher& pub) {        
00257         _on_new_subscriber();
00258 }
00259 
00260 void on_new_subscriber_it(const image_transport::SingleSubscriberPublisher& pub) {        
00261         _on_new_subscriber();
00262 }
00263 
00264 int main(int argc, char **argv) {
00265         ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug);
00266         ros::init(argc, argv, "driver_3DCS");
00267         ros::NodeHandle nh("~");
00268         
00269         bool r;
00270         boost::asio::io_service io_service;
00271         
00272         //default parameters
00273         std::string remote_device_ip="192.168.1.10";
00274         g_frame_id = "camera";
00275         
00276         ros::param::get("~remote_device_ip", remote_device_ip);
00277         ros::param::get("~frame_id", g_frame_id);
00278         ros::param::get("~prevent_frame_skipping", g_publish_all);
00279         
00280         Driver_3DCS::Control control(io_service, remote_device_ip);
00281         r=control.open();
00282         ROS_ASSERT(r);
00283         r=control.initStream();
00284         ROS_ASSERT(r);
00285         
00286         boost::thread thr(boost::bind(&boost::asio::io_service::run, &io_service));
00287         
00288         Driver_3DCS::Streaming device(io_service, remote_device_ip);
00289         device.getSignal().connect( boost::bind(&on_frame, _1) );
00290         r=device.openStream();
00291         ROS_ASSERT(r);
00292         
00293         g_control = &control;
00294         
00295         //make me public (after init.)
00296         
00297         image_transport::ImageTransport it(nh);
00298         g_pub_depth = it.advertise("depth", 1, (image_transport::SubscriberStatusCallback)on_new_subscriber_it, image_transport::SubscriberStatusCallback());
00299         g_pub_points = nh.advertise<sensor_msgs::PointCloud2>("points", 2, (ros::SubscriberStatusCallback)on_new_subscriber_ros, ros::SubscriberStatusCallback());
00300         g_pub_confidence = it.advertise("confidence", 1, (image_transport::SubscriberStatusCallback)on_new_subscriber_it, image_transport::SubscriberStatusCallback());
00301         g_pub_intensity = it.advertise("intensity", 1, (image_transport::SubscriberStatusCallback)on_new_subscriber_it, image_transport::SubscriberStatusCallback());
00302         g_pub_camera_info = nh.advertise<sensor_msgs::CameraInfo>("camera_info", 1, (ros::SubscriberStatusCallback)on_new_subscriber_ros, ros::SubscriberStatusCallback());
00303         g_pub_ios = nh.advertise<std_msgs::ByteMultiArray>("ios", 1, (ros::SubscriberStatusCallback)on_new_subscriber_ros, ros::SubscriberStatusCallback());
00304         
00305         //wait til end of exec.
00306         ros::spin();
00307 
00308         io_service.stop();
00309         device.closeStream();
00310         control.close();
00311         
00312         g_pub_depth.shutdown();
00313         g_pub_confidence.shutdown();
00314         g_pub_intensity.shutdown();
00315         g_pub_camera_info.shutdown();
00316         g_pub_points.shutdown();
00317         g_pub_ios.shutdown();
00318 
00319         return 0;
00320 }


sick_3vistort_driver
Author(s):
autogenerated on Thu Aug 4 2016 04:03:59