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
00089
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;
00133
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
00170 PointCloud::Ptr cloud_msg (new PointCloud);
00171 cloud_msg->header = header;
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
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;
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
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
00222 float s0 = std::sqrt(xp*xp + yp*yp + 1.f) * 1000.f;
00223
00224
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();
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
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
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
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 }