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 <ros/ros.h>
00029
00030 #include <OgreVector3.h>
00031
00032 #include <srs_ui_but/topics_list.h>
00033 #include <srs_ui_but/services_list.h>
00034 #include <srs_ui_but/ButCamMsg.h>
00035
00036 #include <visualization_msgs/Marker.h>
00037 #include <sensor_msgs/Image.h>
00038 #include <sensor_msgs/PointCloud2.h>
00039 #include <sensor_msgs/CameraInfo.h>
00040 #include <sensor_msgs/image_encodings.h>
00041
00042 #include <message_filters/subscriber.h>
00043 #include <message_filters/synchronizer.h>
00044 #include <message_filters/sync_policies/approximate_time.h>
00045
00046 #include <pcl_ros/point_cloud.h>
00047 #include <pcl_ros/transforms.h>
00048
00049 #include <tf/transform_listener.h>
00050 #include <tf/message_filter.h>
00051
00052 #include <stdio.h>
00053 #include <utility>
00054 #include <sstream>
00055 #include <float.h>
00056
00057
00058 #define MAX_FRUSTUM_DEPTH 15.0f
00059
00060
00061 #define MAX_DISPLAY_DEPTH 15.0f
00062
00063 using namespace std;
00064 using namespace sensor_msgs;
00065
00066
00067 void countCameraParams(const CameraInfoConstPtr& camInfo);
00068 pair<float, float> countPclDepths(const PointCloud2ConstPtr& pcl);
00069 void publishViewFrustumMarker(const CameraInfoConstPtr cam_info, float frustum_depth);
00070 void publishButDisplay(const CameraInfoConstPtr cam_info, float display_depth);
00071 void updateCameraTopic(ros::NodeHandle& nh);
00072
00073
00074 float elev_d = 0.0f, steer_r = 0.0f, elev_u = 0.0f, steer_l = 0.0f;
00075
00076
00077 tf::TransformListener *tf_cam_info_Listener;
00078
00079
00080 message_filters::Subscriber<CameraInfo> *cam_info_sub;
00081 message_filters::Subscriber<Image> *cam_image_sub;
00082
00083
00084 ros::Publisher frustum_marker_pub, but_display_pub;
00085
00086
00087
00088 std::string camera_topic_par = srs_ui_but::DEFAULT_CAMERA_INFO;
00089 double depth_par = 1.0f;
00090
00091 #ifndef NDEBUG
00092 void callback1(const CameraInfoConstPtr& cam_info)
00093 {
00094 ROS_DEBUG("got cam_info");
00095 }
00096
00097 void callback2(const PointCloud2ConstPtr& pcl)
00098 {
00099 ROS_DEBUG("got pcl");
00100 }
00101
00102 void callback3(const ImageConstPtr& im)
00103 {
00104 ROS_DEBUG("got image");
00105 }
00106 #endif
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 void callback(ros::NodeHandle& nh, const CameraInfoConstPtr& cam_info, const PointCloud2ConstPtr& pcl)
00119 {
00120 ROS_DEBUG("Got everything synced");
00121
00122
00123 ros::param::getCached(srs_ui_but::Camera_PARAM, camera_topic_par);
00124 if (!camera_topic_par.empty())
00125 updateCameraTopic(nh);
00126
00127
00128 ros::param::getCached(srs_ui_but::Depth_PARAM, depth_par);
00129
00130
00131 countCameraParams(cam_info);
00132
00133
00134 pair<float, float> distances = countPclDepths(pcl);
00135
00136 ROS_DEBUG_STREAM("nearest point " << distances.first << " most distant point " << distances.second);
00137
00138 publishViewFrustumMarker(cam_info, distances.second);
00139
00140 publishButDisplay(cam_info, distances.first * depth_par);
00141 }
00142
00148 void updateCameraTopic(ros::NodeHandle& nh)
00149 {
00150 ROS_DEBUG_STREAM("updateCameraTopic :" << camera_topic_par << "!");
00151
00152 std::string cam3dRGB(srs_ui_but::CAM3D_BASE);
00153 std::string camLeft(srs_ui_but::STEREO_LEFT_BASE);
00154 std::string camRight(srs_ui_but::STEREO_RIGHT_BASE);
00155
00156 if (!camera_topic_par.compare(0, cam3dRGB.size(), cam3dRGB))
00157 {
00158 ROS_DEBUG_STREAM("cam3dRGB");
00159 cam_info_sub->subscribe(nh, cam3dRGB + "camera_info", 10);
00160 cam_image_sub->subscribe(nh, cam3dRGB + "image_raw", 10);
00161 }
00162 else if (!camera_topic_par.compare(0, camLeft.size(), camLeft))
00163 {
00164 ROS_DEBUG_STREAM("left");
00165 cam_info_sub->subscribe(nh, camLeft + "camera_info", 10);
00166 cam_image_sub->subscribe(nh, camRight + "image_raw", 10);
00167 }
00168 else if (!camera_topic_par.compare(0, camRight.size(), camRight))
00169 {
00170 ROS_DEBUG_STREAM("right");
00171 cam_info_sub->subscribe(nh, camRight + "camera_info", 10);
00172 cam_image_sub->subscribe(nh, camRight + "image_raw", 10);
00173 }
00174 else
00175 ROS_ERROR("UNKNOWN CAMERA");
00176
00177 ROS_DEBUG_STREAM("Subscribed to " << cam_info_sub->getTopic() << " and " << cam_image_sub->getTopic());
00178 }
00179
00186 void publishButDisplay(const CameraInfoConstPtr cam_info, float display_depth)
00187 {
00188 ROS_DEBUG("publishButDisplay");
00189
00190
00191 float real_depth = cos(elev_d) * display_depth;
00192
00193 srs_ui_but::ButCamMsg rectangle;
00194
00195 rectangle.header.frame_id = srs_ui_but::MAP_TOPIC;
00196 rectangle.header.stamp = cam_info->header.stamp;
00197
00198
00199 tf::StampedTransform cameraToWorldTf;
00200 try
00201 {
00202 tf_cam_info_Listener->waitForTransform(srs_ui_but::MAP_TOPIC, cam_info->header.frame_id, cam_info->header.stamp,
00203 ros::Duration(0.2));
00204 tf_cam_info_Listener->lookupTransform(srs_ui_but::MAP_TOPIC, cam_info->header.frame_id, cam_info->header.stamp, cameraToWorldTf);
00205 }
00206
00207 catch (tf::TransformException& ex)
00208 {
00209 ROS_ERROR_STREAM("Camera info transform error: " << ex.what() << ", quitting callback");
00210 return;
00211 }
00212
00213 rectangle.pose.orientation.x = cameraToWorldTf.getRotation().x();
00214 rectangle.pose.orientation.y = cameraToWorldTf.getRotation().y();
00215 rectangle.pose.orientation.z = cameraToWorldTf.getRotation().z();
00216 rectangle.pose.orientation.w = cameraToWorldTf.getRotation().w();
00217
00218
00219 geometry_msgs::PointStamped tl, tr, bl;
00220
00221 Ogre::Vector3 tl_vec;
00222 tl_vec.x = +steer_l * real_depth;
00223 tl_vec.y = +elev_u * real_depth;
00224 tl_vec.z = real_depth;
00225
00226 Ogre::Vector3 tr_vec;
00227 tr_vec.x = -steer_r * real_depth;
00228 tr_vec.y = +elev_u * real_depth;
00229 tr_vec.z = real_depth;
00230
00231 Ogre::Vector3 bl_vec;
00232 bl_vec.x = +steer_l * real_depth;
00233 bl_vec.y = -elev_d * real_depth;
00234 bl_vec.z = real_depth;
00235
00236 rectangle.scale.x = (tl_vec.distance(tr_vec));
00237 rectangle.scale.y = (tl_vec.distance(bl_vec));
00238 rectangle.scale.z = 1.0;
00239
00240
00241 geometry_msgs::PointStamped br_map;
00242
00243 br_map.header.frame_id = cam_info->header.frame_id;
00244 br_map.header.stamp = cam_info->header.stamp;
00245 br_map.point.x = -steer_r * real_depth;
00246 br_map.point.y = -elev_d * real_depth;
00247 br_map.point.z = real_depth;
00248
00249 tf_cam_info_Listener->transformPoint(srs_ui_but::MAP_TOPIC, br_map, br_map);
00250
00251 rectangle.pose.position.x = br_map.point.x;
00252 rectangle.pose.position.y = br_map.point.y;
00253 rectangle.pose.position.z = br_map.point.z;
00254
00255
00256 but_display_pub.publish(rectangle);
00257
00258 }
00259
00266 void publishViewFrustumMarker(const CameraInfoConstPtr cam_info, float frustum_depth)
00267 {
00268 ROS_DEBUG("publishViewFrustumMarker");
00269
00270 visualization_msgs::Marker marker;
00271
00272
00273 marker.id = 0;
00274 marker.header.stamp = cam_info->header.stamp;
00275 marker.header.frame_id = srs_ui_but::MAP_TOPIC;
00276 marker.ns = "view_frustum";
00277 marker.type = visualization_msgs::Marker::LINE_LIST;
00278 marker.action = visualization_msgs::Marker::ADD;
00279 marker.pose.position.x = 0;
00280 marker.pose.position.y = 0;
00281 marker.pose.position.z = 0;
00282 marker.pose.orientation.x = 0;
00283 marker.pose.orientation.y = 0;
00284 marker.pose.orientation.z = 0;
00285 marker.pose.orientation.w = 1.0;
00286 marker.scale.x = 0.01;
00287 marker.color.a = 1.0;
00288 marker.color.r = 1.0;
00289
00290
00291
00292 geometry_msgs::PointStamped tl, tr, bl, br, camera;
00293 geometry_msgs::PointStamped tl_map, tr_map, bl_map, br_map, camera_map;
00294
00295
00296
00297
00298 camera.header.frame_id = cam_info->header.frame_id;
00299 camera.header.stamp = cam_info->header.stamp;
00300 camera.point.x = 0.0;
00301 camera.point.y = 0.0;
00302 camera.point.z = 0.0;
00303
00304 tf_cam_info_Listener->transformPoint(srs_ui_but::MAP_TOPIC, camera, camera_map);
00305
00306
00307
00308
00309 br.header.frame_id = cam_info->header.frame_id;
00310 br.header.stamp = cam_info->header.stamp;
00311 br.point.x = -steer_r * frustum_depth;
00312 br.point.y = -elev_d * frustum_depth;
00313 br.point.z = frustum_depth;
00314
00315 tf_cam_info_Listener->transformPoint(srs_ui_but::MAP_TOPIC, br, br_map);
00316
00317
00318
00319
00320 bl.header.frame_id = cam_info->header.frame_id;
00321 bl.header.stamp = cam_info->header.stamp;
00322 bl.point.x = +steer_l * frustum_depth;
00323 bl.point.y = -elev_d * frustum_depth;
00324 bl.point.z = frustum_depth;
00325
00326 tf_cam_info_Listener->transformPoint(srs_ui_but::MAP_TOPIC, bl, bl_map);
00327
00328
00329
00330
00331 tl.header.frame_id = cam_info->header.frame_id;
00332 tl.header.stamp = cam_info->header.stamp;
00333 tl.point.x = +steer_l * frustum_depth;
00334 tl.point.y = +elev_u * frustum_depth;
00335 tl.point.z = frustum_depth;
00336
00337 tf_cam_info_Listener->transformPoint(srs_ui_but::MAP_TOPIC, tl, tl_map);
00338
00339
00340
00341
00342 tr.header.frame_id = cam_info->header.frame_id;
00343 tr.header.stamp = cam_info->header.stamp;
00344 tr.point.x = -steer_r * frustum_depth;
00345 tr.point.y = +elev_u * frustum_depth;
00346 tr.point.z = frustum_depth;
00347
00348 tf_cam_info_Listener->transformPoint(srs_ui_but::MAP_TOPIC, tr, tr_map);
00349
00350
00351
00352 marker.points.push_back(camera_map.point);
00353 marker.points.push_back(br_map.point);
00354 marker.points.push_back(camera_map.point);
00355 marker.points.push_back(bl_map.point);
00356 marker.points.push_back(camera_map.point);
00357 marker.points.push_back(tl_map.point);
00358 marker.points.push_back(camera_map.point);
00359 marker.points.push_back(tr_map.point);
00360
00361
00362 frustum_marker_pub.publish(marker);
00363 return;
00364 }
00365
00366
00367
00368
00369
00370
00371 pair<float, float> countPclDepths(const PointCloud2ConstPtr& pcl)
00372 {
00373 ROS_DEBUG("countPclDepths");
00374
00375
00376 pcl::PointCloud<pcl::PointXYZ> pcl_pointCloud;
00377
00378
00379 pcl::fromROSMsg(*pcl, pcl_pointCloud);
00380
00381
00382 float far_distance = 0.0f;
00383
00384
00385 float near_distance = FLT_MAX;
00386
00387
00388 float dist;
00389
00390 BOOST_FOREACH (const pcl::PointXYZ& pt, pcl_pointCloud.points)
00391 { dist = pt.x*pt.x + pt.y*pt.y + pt.z*pt.z;
00392 if (dist > far_distance) far_distance = dist;
00393 if (dist < near_distance) near_distance = dist;
00394
00395 }
00396
00397 far_distance = sqrt(far_distance);
00398 near_distance = sqrt(near_distance);
00399
00400
00401 if (far_distance > MAX_FRUSTUM_DEPTH)
00402 far_distance = MAX_FRUSTUM_DEPTH;
00403 if (near_distance > MAX_DISPLAY_DEPTH)
00404 near_distance = MAX_DISPLAY_DEPTH;
00405
00406 return make_pair(near_distance, far_distance);
00407 }
00408
00409
00410
00411
00412
00413
00414
00415 void countCameraParams(const CameraInfoConstPtr& camInfo)
00416 {
00417 ROS_DEBUG("countCameraParams");
00418
00419
00420 if (camInfo->distortion_model != "plumb_bob")
00421 {
00422 ROS_ERROR("Unknown distortion model in CameraInfo message.\\"
00423 "Optimized only for plumb bob distortion model.");
00424 }
00425
00426 unsigned int height = 0;
00427 unsigned int width = 0;
00428
00429
00430 float fx, fy, cx, cy;
00431
00432 height = camInfo->height;
00433 width = camInfo->width;
00434
00435
00436
00437
00438
00439 fx = camInfo->K[0];
00440
00441 if (fx == 0)
00442 {
00443 ROS_ERROR("Uncalibrated camera, unable to count view frustum parameters.");
00444 }
00445
00446 fy = camInfo->K[4];
00447 cx = camInfo->K[2];
00448 cy = camInfo->K[5];
00449
00450
00451 elev_d = cy / fy;
00452 steer_r = cx / fx;
00453
00454 elev_u = (height - cy) / fy;
00455 steer_l = (width - cx) / fx;
00456
00457 return;
00458 }
00459
00460 int main(int argc, char** argv)
00461 {
00462 ROS_DEBUG_STREAM("test " << "default_camera_info" << ", " << srs_ui_but::CAM3D_BASE << ", " << srs_ui_but::DEFAULT_CAMERA_INFO << ", " << srs_ui_but::STEREO_LEFT_BASE << ", " << srs_ui_but::STEREO_RIGHT_BASE << ", " << srs_ui_but::MAP_TOPIC << ", " << srs_ui_but::DEPTH_IMAGE_IN << ", " << srs_ui_but::DEFAULT_CAMERA_IMAGE);
00463
00464 ros::init(argc, argv, "view");
00465
00466 ros::NodeHandle nh;
00467
00468
00469
00470 frustum_marker_pub = nh.advertise<visualization_msgs::Marker> (srs_ui_but::ViewFrustum_TOPIC, 1);
00471
00472 but_display_pub = nh.advertise<srs_ui_but::ButCamMsg> (srs_ui_but::CameraView_TOPIC, 1);
00473
00474
00475 cam_info_sub = new message_filters::Subscriber<CameraInfo>(nh, camera_topic_par, 10);
00476
00477 message_filters::Subscriber<PointCloud2> pcl_sub(nh, srs_ui_but::DEPTH_IMAGE_IN, 10);
00478
00479
00480 cam_image_sub = new message_filters::Subscriber<Image>(nh, srs_ui_but::DEFAULT_CAMERA_IMAGE, 10);
00481
00482 #ifndef NDEBUG
00483 cam_info_sub->registerCallback(boost::bind(&callback1, _1));
00484 pcl_sub.registerCallback(boost::bind(&callback2, _1));
00485 cam_image_sub->registerCallback(boost::bind(&callback3, _1));
00486 #endif
00487
00488
00489 tf_cam_info_Listener = new tf::TransformListener();
00490 tf::MessageFilter<CameraInfo> *cam_info_transform_filter = new tf::MessageFilter<CameraInfo>(*cam_info_sub,
00491 *tf_cam_info_Listener,
00492 srs_ui_but::MAP_TOPIC, 10);
00493
00494
00495 typedef message_filters::sync_policies::ApproximateTime<CameraInfo, PointCloud2> App_sync_policy;
00496
00497
00498 message_filters::Synchronizer<App_sync_policy> time_sync(App_sync_policy(10), *cam_info_transform_filter, pcl_sub);
00499
00500
00501
00502
00503
00504 time_sync.registerCallback(boost::bind(&callback, nh, _1, _2));
00505
00506 ros::spin();
00507
00508 return 1;
00509 }