00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <srs_env_model/but_server/compressed_pc_publisher.h>
00029 #include <srs_env_model/topics_list.h>
00030 #include <pcl/ros/conversions.h>
00031 #include <pcl_ros/transforms.h>
00032 #include <pcl/io/io.h>
00033
00034
00038 srs_env_model::CCompressedPCPublisher::CCompressedPCPublisher(ros::NodeHandle & nh)
00039 : m_camera_stereo_offset_left(0)
00040 , m_camera_stereo_offset_right(0)
00041 , m_publishFID(CPC_WORLD_FRAME)
00042 , m_cameraFID(CPC_CAMERA_FRAME)
00043 , m_tfListener()
00044
00045 , m_tfListener2(ros::Duration(30))
00046 {
00047
00048 ros::NodeHandle pnh("~");
00049
00050
00051
00052 m_subscribedTopicName = CPC_INPUT_TOPIC_NAME;
00053
00054
00055
00056 m_publishedTopicName = CPC_OUTPUT_TOPIC_NAME;
00057
00058
00059 pnh.param("world_frame", m_publishFID, CPC_WORLD_FRAME);
00060 pnh.param("camera_frame", m_cameraFID, CPC_CAMERA_FRAME);
00061
00062
00063 m_pub = nh.advertise<sensor_msgs::PointCloud2> (m_publishedTopicName, 5);
00064
00065
00066
00067
00068
00069 m_sub.subscribe(nh, m_subscribedTopicName, 5);
00070 m_tf_filter = new tf::MessageFilter<tInputData>(m_sub, m_tfListener, m_publishFID, 5);
00071 m_tf_filter->registerCallback( boost::bind(&CCompressedPCPublisher::incommingDataCB, this, _1) );
00072
00073
00074
00075
00076
00077 }
00078
00082 void srs_env_model::CCompressedPCPublisher::incommingDataCB( const tInputData::ConstPtr & data )
00083 {
00084 ROS_DEBUG_ONCE("CCompressedPCPublisher::incommingDataCB: message received");
00085
00086
00087 {
00088
00089 tf::StampedTransform pcToPubTf;
00090
00091
00092 try {
00093
00094
00095
00096
00097 m_tfListener.lookupTransform( m_publishFID, data->pointcloud2.header.frame_id,
00098 data->pointcloud2.header.stamp, pcToPubTf );
00099
00100 } catch (tf::TransformException& ex) {
00101 ROS_ERROR_STREAM( "CCompressedPCPublisher::incommingDataCB" << ": Transform error - " << ex.what() << ", quitting callback");
00102 return;
00103 }
00104
00105 m_to_pfid = pcToPubTf;
00106 }
00107
00108
00109 tInputCloudMsg inbuffer;
00110
00111
00112 pcl_ros::transformPointCloud( m_publishFID, m_to_pfid, data->pointcloud2, inbuffer );
00113
00114 if( data->isPartial != 0 )
00115 {
00116
00117
00118
00119
00120 removeFrustumFromCloud( data, m_cloud );
00121
00122
00123 copyCloud( inbuffer, m_cloud, true );
00124
00125
00126
00127
00128 sensor_msgs::PointCloud2 cloud;
00129 pcl::toROSMsg< tPclPoint >(m_cloud, cloud);
00130
00131
00132 cloud.header.frame_id = m_publishFID;
00133 cloud.header.stamp = data->pointcloud2.header.stamp;
00134
00135
00136 m_pub.publish( cloud );
00137
00138
00139 }
00140 else
00141 {
00142
00143
00144
00145 inbuffer.header.frame_id = m_publishFID;
00146 inbuffer.header.stamp = data->pointcloud2.header.stamp;
00147
00148
00149 m_pub.publish( inbuffer );
00150
00151
00152 m_cloud.clear();
00153 copyCloud( inbuffer, m_cloud );
00154 }
00155 }
00159 long srs_env_model::CCompressedPCPublisher::copyCloud( const tInputCloudMsg & input, tPointCloudInternal & output, bool bAdd )
00160 {
00161
00162 if( bAdd )
00163 {
00164 tPointCloudInternal buffer;
00165 output.header = input.header;
00166
00167 if( ! isRGBCloud( input ) )
00168 {
00169 pcl::PointCloud< pcl::PointXYZ >::Ptr bufferCloud( new pcl::PointCloud< pcl::PointXYZ> );
00170
00171 pcl::fromROSMsg(input, *bufferCloud );
00172 pcl::copyPointCloud< pcl::PointXYZ, tPclPoint >( *bufferCloud, buffer );
00173
00174 }
00175 else
00176 {
00177 pcl::PointCloud< pcl::PointXYZRGB >::Ptr bufferCloud( new pcl::PointCloud< pcl::PointXYZRGB > );
00178
00179 pcl::fromROSMsg(input, *bufferCloud);
00180 pcl::copyPointCloud<pcl::PointXYZRGB, tPclPoint>( *bufferCloud, buffer );
00181 }
00182
00183
00184 output += buffer;
00185
00186 }
00187 else
00188 {
00189 if( ! isRGBCloud( input ) )
00190 {
00191 pcl::PointCloud< pcl::PointXYZ >::Ptr bufferCloud( new pcl::PointCloud< pcl::PointXYZ> );
00192
00193 pcl::fromROSMsg(input, *bufferCloud );
00194 pcl::copyPointCloud< pcl::PointXYZ, tPclPoint >( *bufferCloud, output );
00195
00196 }
00197 else
00198 {
00199 pcl::PointCloud< pcl::PointXYZRGB >::Ptr bufferCloud( new pcl::PointCloud< pcl::PointXYZRGB > );
00200
00201 pcl::fromROSMsg(input, *bufferCloud);
00202 pcl::copyPointCloud<pcl::PointXYZRGB, tPclPoint>( *bufferCloud, output );
00203 }
00204
00205 }
00206
00207
00208
00209 return output.size();
00210 }
00211
00215 bool srs_env_model::CCompressedPCPublisher::isRGBCloud( const tInputCloudMsg & cloud )
00216 {
00217 tInputCloudMsg::_fields_type::const_iterator i, end;
00218
00219 for( i = cloud.fields.begin(), end = cloud.fields.end(); i != end; ++i )
00220 {
00221 if( i->name == "rgb" )
00222 {
00223
00224 return true;
00225 }
00226 }
00227
00228
00229
00230 return false;
00231 }
00232
00236 long srs_env_model::CCompressedPCPublisher::removeFrustumFromCloud( const tInputData::ConstPtr & data, tPointCloudInternal & cloud )
00237 {
00238
00239 {
00240
00241 m_cameraFrameId = data->camera_info.header.frame_id;
00242
00243 ROS_DEBUG("CCompressedPCPublisher::removeFrustumFromCloud: Set camera info: %d x %d\n", data->camera_info.height, data->camera_info.width);
00244
00245 m_camera_model.fromCameraInfo(data->camera_info);
00246 m_camera_size = m_camera_model.fullResolution();
00247 }
00248
00249
00250 {
00251 m_to_sensor = tf::StampedTransform::getIdentity();
00252
00253
00254
00255
00256 if( m_cameraFrameId != m_publishFID )
00257 {
00258
00259 tf::StampedTransform ocToCamTf;
00260
00261 ros::Time stamp( data->header.stamp );
00262
00263 try {
00264
00265 m_tfListener2.waitForTransform(m_cameraFrameId, m_publishFID,
00266 stamp, ros::Duration(5));
00267
00268 m_tfListener2.lookupTransform( m_cameraFrameId, m_publishFID,
00269 stamp, ocToCamTf );
00270
00271 } catch (tf::TransformException& ex) {
00272 ROS_ERROR_STREAM( "CCompressedPCPublisher::removeFrustumFromCloud: Transform error - " << ex.what() << ", quitting callback");
00273 return 0;
00274 }
00275
00276 m_to_sensor = ocToCamTf;
00277 }
00278 }
00279
00280 long count(0);
00281
00282
00283 tPointCloudInternal buffer( cloud );
00284 tPointCloudInternal::iterator p, end(buffer.end());
00285
00286
00287 cloud.clear();
00288
00289
00290
00291
00292 for( p = buffer.begin(); p != end; ++p )
00293 {
00294
00295 tf::Point pos(p->x, p->y, p->z);
00296 tf::Point posRel = m_to_sensor(pos);
00297 cv::Point2d uv = m_camera_model.project3dToPixel(cv::Point3d( posRel.x(), posRel.y(), posRel.z()));
00298
00299
00300 if (!inSensorCone(uv))
00301 {
00302 ++count;
00303 cloud.push_back( *p );
00304 }
00305 }
00306
00307 return count;
00308 }
00309
00313 bool srs_env_model::CCompressedPCPublisher::inSensorCone(const cv::Point2d& uv) const
00314 {
00315
00316
00317
00318
00319
00320
00321 return ((uv.x > m_camera_stereo_offset_left + 1) &&
00322 (uv.x < m_camera_size.width + m_camera_stereo_offset_right - 2) &&
00323 (uv.y > 1) &&
00324 (uv.y < m_camera_size.height - 2));
00325 }
00326