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
00029
00030 #include <ias_drawer_executive/Perception3d.h>
00031 #include <ias_drawer_executive/Geometry.h>
00032 #include <pcl/ros/conversions.h>
00033
00034 boost::mutex Perception3d::handle_mutex;
00035 boost::mutex Perception3d::plane_mutex;
00036
00037 std::vector<tf::Stamped<tf::Pose> *> Perception3d::handlePoses = *(new std::vector<tf::Stamped<tf::Pose> *> ());
00038 std::vector<tf::Stamped<tf::Pose> *> Perception3d::planePoses = *(new std::vector<tf::Stamped<tf::Pose> *> ());
00039
00040 boost::mutex Perception3d::handle_cloud_mutex;
00041 PointCloudT Perception3d::lastCloud;
00042 int op_handle_cloud_cnt = 0;
00043
00044 btVector3 Perception3d::handleHint;
00045 btVector3 Perception3d::handleResult;
00046 double Perception3d::handleMinDist;
00047 ros::Time Perception3d::cloud_time;
00048 ros::Time Perception3d::query_time;
00049
00050
00051 void Perception3d::handleCallback(const geometry_msgs::PoseStamped::ConstPtr& msg)
00052 {
00053
00054 tf::Stamped<tf::Pose> *newPose = new tf::Stamped<tf::Pose>();
00055 newPose->frame_id_ = msg->header.frame_id;
00056 newPose->stamp_ = msg->header.stamp;
00057 newPose->setOrigin(btVector3(msg->pose.position.x,msg->pose.position.y,msg->pose.position.z));
00058 newPose->setRotation(btQuaternion(msg->pose.orientation.x,msg->pose.orientation.y,msg->pose.orientation.z,msg->pose.orientation.w));
00059 ROS_INFO("CALLBACK GOT HANDLE AT %f %f %f", msg->pose.position.x,msg->pose.position.y,msg->pose.position.z);
00060 handle_mutex.lock();
00061 handlePoses.push_back(newPose);
00062 handle_mutex.unlock();
00063 }
00064
00065
00066
00067 tf::Stamped<tf::Pose> Perception3d::getHandlePoseFromLaser(int pos)
00068 {
00069
00070
00071 system("rosservice call laser_tilt_controller/set_periodic_cmd '{ command: { header: { stamp: 0 }, profile: \"linear\" , period: 10 , amplitude: 0.8 , offset: 0.3 }}'");
00072
00073 handlePoses.clear();
00074 ros::NodeHandle n_;
00075 ros::Subscriber sub_= n_.subscribe("/handle_detector/pointcloud_line_pose_node/handle_pose", 100, &Perception3d::handleCallback);
00076
00077 size_t numHandles = 0;
00078 ros::Rate rate(20);
00079 while (ros::ok() && (numHandles < 10))
00080 {
00081 handle_mutex.lock();
00082 if (Perception3d::handlePoses.size() > numHandles)
00083 {
00084 ROS_INFO("LAST HANDLE: %f %f %f ", handlePoses[numHandles]->getOrigin().x(),handlePoses[numHandles]->getOrigin().y(),handlePoses[numHandles]->getOrigin().z());
00085 numHandles = handlePoses.size();
00086 }
00087 handle_mutex.unlock();
00088 rate.sleep();
00089 ros::spinOnce();
00090 }
00091
00092 return *handlePoses[0];
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 }
00122
00123 btQuaternion resOri;
00124
00125 void Perception3d::handleCloudCallback(const sensor_msgs::PointCloud2::ConstPtr& msg)
00126 {
00127
00128 ros::Time t(msg->header.stamp);
00129 cloud_time = t;
00130
00131 if (t < query_time)
00132 return;
00133
00134 handle_cloud_mutex.lock();
00135 pcl::fromROSMsg(*msg,lastCloud);
00136
00137 bool takethisone = false;
00138 for (size_t k = 0; k < lastCloud.points.size(); k++)
00139 {
00140 btVector3 act(lastCloud.points[k].x,lastCloud.points[k].y,lastCloud.points[k].z);
00141 double dist = btVector3(act - handleHint).length();
00142 if (dist < handleMinDist)
00143 {
00144 handleMinDist = dist;
00145 handleResult = act;
00146 takethisone = true;
00147 }
00148 }
00149
00150
00151 if (takethisone) {
00152 btVector3 l(lastCloud.points[0].x,lastCloud.points[0].y,lastCloud.points[0].z);
00153 btVector3 r(lastCloud.points[lastCloud.points.size() / 2].x,lastCloud.points[lastCloud.points.size() / 2].y,lastCloud.points[lastCloud.points.size() / 2].z);
00154 btVector3 rel = r - l;
00155 double at2 = atan2(rel.y(), rel.z());
00156 btQuaternion ori(btVector3(1,0,0), at2);
00157 resOri = ori;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 op_handle_cloud_cnt++;
00177
00178 ROS_INFO("GOT CLOUD %i", op_handle_cloud_cnt);
00179 handle_cloud_mutex.unlock();
00180 }
00181
00182 tf::Stamped<tf::Pose> Perception3d::getHandlePoseFromLaser(tf::Stamped<tf::Pose> hint, double timeout)
00183 {
00184
00185 system("rosservice call laser_tilt_controller/set_periodic_cmd '{ command: { header: { stamp: 0 }, profile: \"linear\" , period: 10 , amplitude: 0.8 , offset: 0.3 }}'");
00186
00187 query_time = ros::Time::now();
00188 cloud_time = ros::Time(0);
00189
00190 tf::Stamped<tf::Pose> inBase = Geometry::getPoseIn("base_link", hint);
00191
00192 ROS_INFO("HINT in map");
00193 Geometry::printPose(hint);
00194 ROS_INFO("HINT in base");
00195 Geometry::printPose(inBase);
00196
00197 ros::NodeHandle n_;
00198 ros::Subscriber subHandleInliers = n_.subscribe("/handle_detector/handle_projected_inliers/output", 10, Perception3d::handleCloudCallback);
00199
00200
00201 bool found = false;
00202 ros::Rate rate(3);
00203
00204 int maxNum = 5;
00205
00206 btVector3 best(0,0,0);
00207
00208 handleHint = inBase.getOrigin();
00209 handleMinDist = 100;
00210 double curBestDist = 100;
00211 int goodcloud = op_handle_cloud_cnt + 100000;
00212
00213 ROS_INFO("Waiting for handles published after query");
00214
00215 while (cloud_time < query_time) {
00216 rate.sleep();
00217 ros::spinOnce();
00218
00219 if ((timeout > 0) && (ros::Time::now() > query_time + ros::Duration(timeout)))
00220 return hint;
00221 }
00222
00223 ros::Time current_timeslice = cloud_time;
00224
00225 ROS_INFO("Waiting done");
00226
00227
00228
00229
00230 while (cloud_time == current_timeslice)
00231 {
00232 rate.sleep();
00233 ros::spinOnce();
00234 if (handleMinDist < curBestDist)
00235 {
00236
00237
00238
00239 found = true;
00240 best = handleResult;
00241 curBestDist = handleMinDist;
00242 }
00243 ROS_INFO("Dist : %f", handleMinDist);
00244
00245 if ((timeout > 0) && (ros::Time::now() > query_time + ros::Duration(timeout)))
00246 return hint;
00247 }
00248
00249 tf::Stamped<tf::Pose> ret;
00250 ret.frame_id_ = "base_link";
00251 ret.setOrigin(best);
00252
00253 ret.setRotation(resOri);
00254
00255 if (maxNum <= 0)
00256 ret.setOrigin(btVector3(0,0,-1));
00257
00258 ROS_INFO("RET");
00259 Geometry::printPose(ret);
00260
00261 ret = Geometry::getPoseIn(hint.frame_id_.c_str(), ret);
00262
00263 return ret;
00264 }
00265
00266
00267 void Perception3d::bottleCallback(const ias_table_msgs::TableCluster::ConstPtr& msg)
00268 {
00269
00270 tf::Stamped<tf::Pose> *newPose = new tf::Stamped<tf::Pose>();
00271 newPose->frame_id_ = msg->header.frame_id;
00272 newPose->stamp_ = msg->header.stamp;
00273 newPose->setOrigin(btVector3(msg->center.x,msg->center.y,msg->center.z));
00274
00275 ROS_INFO("CALLBACK GOT HANDLE AT %f %f %f", msg->center.x,msg->center.y,msg->center.z);
00276 handle_mutex.lock();
00277 handlePoses.push_back(newPose);
00278 handle_mutex.unlock();
00279 }
00280
00281
00282 tf::Stamped<tf::Pose> Perception3d::getBottlePose()
00283 {
00284
00285
00286
00287 int sysret = system("rosrun dynamic_reconfigure dynparam set /camera_synchronizer_node '{projector_mode: 3, narrow_stereo_trig_mode: 3}'");
00288 ROS_INFO("%i rosrun dynamic_reconfigure dynparam set /camera_synchronizer_node '{projector_mode: 3, narrow_stereo_trig_mode: 3}'", sysret);
00289
00290
00291
00292
00293
00294 ros::NodeHandle n_;
00295 ros::Subscriber sub_= n_.subscribe("/stereo_table_cluster_detector/pointcloud_minmax_3d_node/cluster", 100, &Perception3d::bottleCallback);
00296
00297 size_t numHandles = 0;
00298 ros::Rate rate(20);
00299
00300 btVector3 average(0,0,0);
00301 double numav = 0;
00302
00303 tf::Stamped<tf::Pose> ret;
00304
00305 while (ros::ok() && (numHandles < 1))
00306 {
00307 handle_mutex.lock();
00308 if (Perception3d::handlePoses.size() > numHandles)
00309 {
00310 ROS_INFO("LAST HANDLE: %f %f %f ", handlePoses[numHandles]->getOrigin().x(),handlePoses[numHandles]->getOrigin().y(),handlePoses[numHandles]->getOrigin().z());
00311 average += btVector3(handlePoses[numHandles]->getOrigin().x(),handlePoses[numHandles]->getOrigin().y(),handlePoses[numHandles]->getOrigin().z());
00312 ret.stamp_ = handlePoses[numHandles]->stamp_;
00313 ret.frame_id_ = handlePoses[numHandles]->frame_id_;
00314 numav++;
00315 numHandles = handlePoses.size();
00316 }
00317
00318 handle_mutex.unlock();
00319 rate.sleep();
00320 ros::spinOnce();
00321 }
00322
00323 average *= 1.0f / numav;
00324 ret.setOrigin(average);
00325
00326 ret = Geometry::getPoseIn("map", ret);
00327
00328 system("rosrun dynamic_reconfigure dynparam set /camera_synchronizer_node projector_mode 1");
00329
00330 return ret;
00331 }
00332
00333 void Perception3d::fridgePlaneCloudCallback(const sensor_msgs::PointCloud2::ConstPtr& msg)
00334 {
00335
00336 tf::Stamped<tf::Pose> *newPose = new tf::Stamped<tf::Pose>();
00337 newPose->frame_id_ = msg->header.frame_id;
00338 newPose->stamp_ = msg->header.stamp;
00339 pcl::PointXYZ point_max, point_min, point_center;
00340 pcl::PointCloud<pcl::PointXYZ> cloud;
00341 pcl::fromROSMsg(*msg, cloud);
00342 pcl::getMinMax3D (cloud, point_min, point_max);
00343
00344 point_center.x = (point_max.x + point_min.x)/2;
00345 point_center.y = (point_max.y + point_min.y)/2;
00346 point_center.z = (point_max.z + point_min.z)/2;
00347
00348 newPose->setOrigin(btVector3(point_center.x,point_center.y,point_center.z));
00349
00350 ROS_INFO("CALLBACK GOT PLANE CENTER AT %f %f %f", point_center.x,point_center.y,point_center.z);
00351 plane_mutex.lock();
00352 planePoses.push_back(newPose);
00353 plane_mutex.unlock();
00354 }
00355
00356 tf::Stamped<tf::Pose> Perception3d::getFridgePlaneCenterPose()
00357 {
00358 int sysret = system("rosrun dynamic_reconfigure dynparam set /camera_synchronizer_node '{projector_mode: 3, narrow_stereo_trig_mode: 3}'");
00359 ROS_INFO("%i rosrun dynamic_reconfigure dynparam set /camera_synchronizer_node '{projector_mode: 3, narrow_stereo_trig_mode: 3}'", sysret);
00360
00361 ros::NodeHandle n_;
00362 ros::Subscriber sub_= n_.subscribe("/stereo_table_cluster_detector/extract_clusters_on_table/table_inliers", 100, &Perception3d::fridgePlaneCloudCallback);
00363
00364 size_t numPlanes = 0;
00365 ros::Rate rate(20);
00366
00367 btVector3 average(0,0,0);
00368 double numav = 0;
00369
00370 tf::Stamped<tf::Pose> ret;
00371
00372 while (ros::ok() && (numPlanes < 1))
00373 {
00374 plane_mutex.lock();
00375 if (Perception3d::planePoses.size() > numPlanes)
00376 {
00377 ROS_INFO("LAST PLANE: %f %f %f ", planePoses[numPlanes]->getOrigin().x(),planePoses[numPlanes]->getOrigin().y(),planePoses[numPlanes]->getOrigin().z());
00378 average += btVector3(planePoses[numPlanes]->getOrigin().x(),planePoses[numPlanes]->getOrigin().y(),planePoses[numPlanes]->getOrigin().z());
00379 ret.stamp_ = planePoses[numPlanes]->stamp_;
00380 ret.frame_id_ = planePoses[numPlanes]->frame_id_;
00381 numav++;
00382 numPlanes = planePoses.size();
00383 }
00384
00385 plane_mutex.unlock();
00386 rate.sleep();
00387 ros::spinOnce();
00388 }
00389
00390 average *= 1.0f / numav;
00391 ret.setOrigin(average);
00392
00393 ret = Geometry::getPoseIn("map", ret);
00394
00395 system("rosrun dynamic_reconfigure dynparam set /camera_synchronizer_node projector_mode 1");
00396
00397 return ret;
00398 }