$search
00001 // Software License Agreement (BSD License) 00002 // Copyright (c) 2008, Willow Garage, Inc. 00003 // Redistribution and use in source and binary forms, with or without 00004 // modification, are permitted provided that the following conditions are met: 00005 // * Redistributions of source code must retain the above copyright notice, 00006 // this list of conditions and the following disclaimer. 00007 // * Redistributions in binary form must reproduce the above copyright 00008 // notice, this list of conditions and the following disclaimer in the 00009 // documentation and/or other materials provided with the distribution. 00010 // * The name of the author may not be used to endorse or promote products 00011 // derived from this software without specific prior written permission. 00012 // 00013 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00014 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00015 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00016 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00017 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00018 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00019 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00020 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00021 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00022 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00023 // POSSIBILITY OF SUCH DAMAGE. 00024 // 00025 // author: Rosen Diankov 00026 #include <cstdio> 00027 #include <vector> 00028 #include <sstream> 00029 #include <ros/ros.h> 00030 00031 #include <boost/thread/mutex.hpp> 00032 #include <boost/format.hpp> 00033 #include "opencv/cv.h" 00034 #include "opencv/highgui.h" 00035 #include "cv_bridge/CvBridge.h" 00036 #include "sensor_msgs/CameraInfo.h" 00037 #include "sensor_msgs/Image.h" 00038 #include "geometry_msgs/PoseStamped.h" 00039 #include "geometry_msgs/PoseArray.h" 00040 #include "checkerboard_detector2/ObjectDetection.h" 00041 #include "checkerboard_detector2/Detect.h" 00042 #include "checkerboard_detector2/Set.h" 00043 #include "math.h" 00044 #include <image_transport/image_transport.h> 00045 #include <tf/transform_broadcaster.h> 00046 00047 #include <sys/timeb.h> // ftime(), struct timeb 00048 #include <sys/time.h> 00049 00050 #define sqr(a) ((a)*(a)) 00051 00052 using namespace std; 00053 using namespace ros; 00054 using namespace boost; 00055 00056 class CheckerboardDetector 00057 { 00058 template <typename T> 00059 static vector<T> tokenizevector(const string& s) 00060 { 00061 stringstream ss(s); 00062 return vector<T>((istream_iterator<T>(ss)), istream_iterator<T>()); 00063 } 00064 00065 public: 00066 struct CHECKERBOARD 00067 { 00068 CvSize griddims; 00069 vector<Vector> grid3d; 00070 vector<CvPoint2D32f> corners; 00071 TransformMatrix tlocaltrans; 00072 TransformMatrix previous_pose; 00073 double cellwidth; 00074 double cellheight; 00075 }; 00076 00077 checkerboard_detector2::ObjectDetection _objdetmsg; 00078 sensor_msgs::CvBridge _cvbridge; 00079 sensor_msgs::CameraInfo _camInfoMsg; 00080 00081 ros::Subscriber camInfoSubscriber; 00082 image_transport::Subscriber imageSubscriber; 00083 // ros::Publisher _pubDetection; 00084 ros::Publisher _pubPoseArray; 00085 std::vector<ros::Publisher> _pubPose; 00086 00087 ros::ServiceServer service_; 00088 00089 string frame_id; // tf frame id 00090 00091 int display, verbose; 00092 vector<CHECKERBOARD> vcheckers; // grid points for every checkerboard 00093 vector< string > vstrtypes; // type names for every grid point 00094 map<string,int> maptypes; 00095 ros::Time lasttime; 00096 CvMat *intrinsic_matrix; // intrinsic matrices 00097 boost::mutex mutexcalib; 00098 IplImage* frame; 00099 00100 ros::NodeHandle _node_private; 00101 ros::NodeHandle _node_pub; 00102 00103 bool _active; 00104 tf::TransformBroadcaster br_; 00105 00107 // Constructor 00108 CheckerboardDetector() : intrinsic_matrix(NULL), frame(NULL), _node_private("~"), _active(true) 00109 { 00110 _node_private.param("display", display, 0); 00111 _node_private.param("verbose", verbose, 1); 00112 _node_private.param("start_active", _active, _active); 00113 00114 char str[32]; 00115 int index = 0; 00116 00117 while(1) { 00118 int dimx, dimy; 00119 double fRectSize[2]; 00120 string type; 00121 00122 sprintf(str,"grid%d_size_x",index); 00123 if( !_node_private.getParam(str,dimx) ) 00124 break; 00125 if (dimx < 3) { 00126 ROS_ERROR("Param: %s must be greater than 2",str); 00127 return; 00128 } 00129 00130 sprintf(str,"grid%d_size_y",index); 00131 if( !_node_private.getParam(str,dimy) ) 00132 break; 00133 if (dimy < 3) { 00134 ROS_ERROR("Param: %s must be greater than 2",str); 00135 return; 00136 } 00137 00138 sprintf(str,"rect%d_size_x",index); 00139 if( !_node_private.getParam(str,fRectSize[0]) ) 00140 break; 00141 00142 sprintf(str,"rect%d_size_y",index); 00143 if( !_node_private.getParam(str,fRectSize[1]) ) 00144 break; 00145 00146 sprintf(str,"type%d",index); 00147 if( !_node_private.getParam(str,type) ) { 00148 sprintf(str,"checker%dx%d", dimx, dimy); 00149 type = str; 00150 } 00151 00152 string strtranslation,strrotation; 00153 sprintf(str,"translation%d",index); 00154 _node_private.param(str,strtranslation,string()); 00155 00156 vector<float> vtranslation = tokenizevector<float>(strtranslation); 00157 sprintf(str,"rotation%d",index); 00158 _node_private.param(str,strrotation,string()); 00159 00160 vector<float> vrotation = tokenizevector<float>(strrotation); 00161 00162 CHECKERBOARD cb; 00163 cb.griddims = cvSize(dimx,dimy); 00164 cb.cellwidth = fRectSize[0]; 00165 cb.cellheight = fRectSize[0]; 00166 00167 cb.grid3d.resize(dimx*dimy); 00168 int j=0; 00169 for(int y=0; y<dimy; ++y) 00170 for(int x=0; x<dimx; ++x) 00171 cb.grid3d[j++] = Vector(x*fRectSize[0], y*fRectSize[1], 0); 00172 00173 if( vtranslation.size() == 3 ) 00174 cb.tlocaltrans.trans = 00175 Vector(vtranslation[0],vtranslation[1],vtranslation[2]); 00176 00177 if( vrotation.size() == 9 ) { 00178 for(int k = 0; k < 3; ++k) { 00179 cb.tlocaltrans.m[4*k+0] = vrotation[3*k+0]; 00180 cb.tlocaltrans.m[4*k+1] = vrotation[3*k+1]; 00181 cb.tlocaltrans.m[4*k+2] = vrotation[3*k+2]; 00182 } 00183 } 00184 00185 vcheckers.push_back(cb); 00186 vstrtypes.push_back(type); 00187 maptypes[vstrtypes.back()] = index; 00188 index++; 00189 } 00190 00191 _node_private.param("frame_id", frame_id,string("")); 00192 00193 if( maptypes.size() == 0 ) { 00194 ROS_ERROR("no checkerboards to detect"); 00195 return; 00196 } 00197 00198 if( display ) { 00199 cvNamedWindow("Checkerboard Detector", CV_WINDOW_AUTOSIZE); 00200 cvStartWindowThread(); 00201 } 00202 00203 lasttime = ros::Time::now(); 00204 // _pubDetection = _node_pub.advertise<checkerboard_detector2::ObjectDetection>("ObjectDetection",1); 00205 _pubPoseArray = _node_pub.advertise<geometry_msgs::PoseArray>("pose_array",1); 00206 00207 cout <<"vcheckers.size()=="<<vcheckers.size()<<endl; 00208 for(size_t i=0;i<vcheckers.size();i++) { 00209 _pubPose.push_back( _node_pub.advertise<geometry_msgs::PoseStamped>( boost::str(format("pose%d")%i),1) ); 00210 } 00211 00212 00213 service_ =_node_pub.advertiseService("set_detect_checkerboard", &CheckerboardDetector::serviceCallback, this); 00214 if(_active) this->activate(true); 00215 } 00216 00218 // Destructor 00219 virtual ~CheckerboardDetector() 00220 { 00221 if( frame ) 00222 cvReleaseImage(&frame); 00223 if( this->intrinsic_matrix ) 00224 cvReleaseMat(&this->intrinsic_matrix); 00225 this->camInfoSubscriber.shutdown(); 00226 this->imageSubscriber.shutdown(); 00227 } 00228 00230 // Camera info callback 00231 void caminfo_cb(const sensor_msgs::CameraInfoConstPtr &msg) 00232 { 00233 boost::mutex::scoped_lock lock(this->mutexcalib); 00234 00235 this->_camInfoMsg = *msg; 00236 00237 // only get the camera info once <- this is dumb 00238 //this->camInfoSubscriber.shutdown(); 00239 //this->camInfoSubscriber2.shutdown(); 00240 } 00241 00242 00244 // Image data callback 00245 void image_cb(const sensor_msgs::ImageConstPtr &msg) 00246 { 00247 boost::mutex::scoped_lock lock(this->mutexcalib); 00248 if( Detect(_objdetmsg,*msg,this->_camInfoMsg) ) { 00249 _objdetmsg.header = msg->header; 00250 // _pubDetection.publish(_objdetmsg); 00251 geometry_msgs::PoseArray array; 00252 array.header = _objdetmsg.header; 00253 array.poses.resize(vcheckers.size()); 00254 for(size_t i=0;i<_objdetmsg.objects.size();i++) { 00255 array.poses[_objdetmsg.objects[i].id] = _objdetmsg.objects[i].pose; 00256 } 00257 _pubPoseArray.publish(array); 00258 vector<tf::StampedTransform> transforms; 00259 for(size_t i=0;i<_objdetmsg.objects.size();i++) { 00260 geometry_msgs::PoseStamped pose; 00261 pose.header = _objdetmsg.header; 00262 pose.pose = _objdetmsg.objects[i].pose; 00263 _pubPose[_objdetmsg.objects[i].id].publish( pose ); 00264 00265 tf::Stamped<tf::Transform> trnsfm; 00266 poseStampedMsgToTF (pose, trnsfm); 00267 char cb_frame_id[100]; 00268 sprintf(cb_frame_id, "/checkerboard_%lu", i); 00269 00270 transforms.push_back(tf::StampedTransform(trnsfm, trnsfm.stamp_, trnsfm.frame_id_, cb_frame_id)); 00271 } 00272 br_.sendTransform(transforms); 00273 } 00274 } 00275 00276 bool detect_cb(checkerboard_detector2::Detect::Request& req, checkerboard_detector2::Detect::Response& res) 00277 { 00278 if(!_active) 00279 return true; 00280 else 00281 return Detect(res.object_detection,req.image,req.camera_info); 00282 } 00283 00284 bool Detect(checkerboard_detector2::ObjectDetection& objdetmsg, const sensor_msgs::Image& imagemsg, const sensor_msgs::CameraInfo& camInfoMsg) 00285 { 00286 if( this->intrinsic_matrix == NULL ) 00287 this->intrinsic_matrix = cvCreateMat(3,3,CV_32FC1); 00288 00289 for(int i = 0; i < 3; ++i) 00290 for(int j = 0; j < 3; ++j) 00291 this->intrinsic_matrix->data.fl[3*i+j] = camInfoMsg.P[4*i+j]; 00292 00293 if( !_cvbridge.fromImage(imagemsg, "mono8") ) { 00294 ROS_ERROR("failed to get image"); 00295 return false; 00296 } 00297 00298 IplImage *pimggray = _cvbridge.toIpl(); 00299 if( display ) { 00300 // copy the raw image 00301 if( frame != NULL && (frame->width != (int)imagemsg.width || frame->height != (int)imagemsg.height) ) { 00302 cvReleaseImage(&frame); 00303 frame = NULL; 00304 } 00305 00306 if( frame == NULL ) 00307 frame = cvCreateImage(cvSize(imagemsg.width,imagemsg.height),IPL_DEPTH_8U, 3); 00308 00309 cvCvtColor(pimggray,frame,CV_GRAY2RGB); 00310 } 00311 00312 vector<checkerboard_detector2::Object6DPose> vobjects; 00313 00314 //#pragma omp parallel for schedule(dynamic,1) 00315 for(int i = 0; i < (int)vcheckers.size(); ++i) { 00316 CHECKERBOARD& cb = vcheckers[i]; 00317 int ncorners; 00318 checkerboard_detector2::Object6DPose objpose; 00319 00320 // do until no more checkerboards detected 00321 while(1) { 00322 cb.corners.resize(200); 00323 int allfound = cvFindChessboardCorners( pimggray, cb.griddims, &cb.corners[0], &ncorners, 00324 CV_CALIB_CB_ADAPTIVE_THRESH ); 00325 cb.corners.resize(ncorners); 00326 00327 //cvDrawChessboardCorners(pimgGray, itbox->second.griddims, &corners[0], ncorners, allfound); 00328 //cvSaveImage("temp.jpg", pimgGray); 00329 00330 if(!allfound || ncorners != (int)cb.grid3d.size()) 00331 break; 00332 00333 // remove any corners that are close to the border 00334 const int borderthresh = 30; 00335 00336 for(int j = 0; j < ncorners; ++j) { 00337 int x = cb.corners[j].x; 00338 int y = cb.corners[j].y; 00339 if( x < borderthresh || x > pimggray->width-borderthresh || 00340 y < borderthresh || y > pimggray->height-borderthresh ) 00341 { 00342 allfound = 0; 00343 break; 00344 } 00345 } 00346 00347 // mark out the image 00348 CvPoint upperleft, lowerright; 00349 upperleft.x = lowerright.x = cb.corners[0].x; 00350 upperleft.y = lowerright.y = cb.corners[0].y; 00351 for(int j = 1; j < (int)cb.corners.size(); ++j) { 00352 if( upperleft.x > cb.corners[j].x ) upperleft.x = cb.corners[j].x; 00353 if( upperleft.y > cb.corners[j].y ) upperleft.y = cb.corners[j].y; 00354 if( lowerright.x < cb.corners[j].x ) lowerright.x = cb.corners[j].x; 00355 if( lowerright.y < cb.corners[j].y ) lowerright.y = cb.corners[j].y; 00356 } 00357 00358 if( allfound ) { 00359 cvFindCornerSubPix(pimggray, &cb.corners[0], cb.corners.size(), cvSize(5,5),cvSize(-1,-1), 00360 cvTermCriteria(CV_TERMCRIT_ITER,20,1e-2)); 00361 CHECKERBOARD cb_copy = cb; 00362 objpose.pose = FindTransformation(cb.corners, cb.grid3d, cb.tlocaltrans,cb_copy); 00363 00364 // now check for proximity of other previously markers, outliers are bad for tracking 00365 double mindist2 = sqr(cb.cellwidth*cb.griddims.width) + sqr(cb.cellheight*cb.griddims.height); 00366 for(int j = 0; j < (int)vcheckers.size(); ++j) { 00367 if(j != i) { 00368 double dist2 = sqr(objpose.pose.position.x - vcheckers[j].previous_pose.trans.x) + 00369 sqr(objpose.pose.position.y - vcheckers[j].previous_pose.trans.y) + 00370 sqr(objpose.pose.position.z - vcheckers[j].previous_pose.trans.z); 00371 if(dist2 < mindist2) { 00372 cout << "skipping marker, because "<<dist2<<" < "<<mindist2<<endl; 00373 allfound = false; // ignore this detection, too close to another previously seen marker 00374 } 00375 } 00376 } 00377 if(allfound) { 00378 cb = cb_copy; 00379 } 00380 } 00381 00382 //#pragma omp critical 00383 { 00384 if( allfound ) { 00385 vobjects.push_back(objpose); 00386 vobjects.back().type = vstrtypes[i]; 00387 vobjects.back().id = i; 00388 } 00389 00390 cvRectangle(pimggray, upperleft, lowerright, CV_RGB(0,0,0),CV_FILLED); 00391 } 00392 } 00393 00394 //cvSaveImage("temp.jpg", pimggray); 00395 } 00396 00397 objdetmsg.objects = vobjects; 00398 objdetmsg.header.stamp = imagemsg.header.stamp; 00399 if( frame_id.size() > 0 ) 00400 objdetmsg.header.frame_id = frame_id; 00401 else 00402 objdetmsg.header.frame_id = imagemsg.header.frame_id; 00403 00404 if( verbose > 0 ) 00405 ROS_INFO("checkerboard: image: %ux%u (size=%u), num: %u, total: %.3fs",imagemsg.width,imagemsg.height, 00406 (unsigned int)imagemsg.data.size(), (unsigned int)objdetmsg.objects.size(), 00407 (float)(ros::Time::now()-lasttime).toSec()); 00408 lasttime = ros::Time::now(); 00409 00410 if( display ) { 00411 // draw each found checkerboard 00412 for(size_t i = 0; i < vobjects.size(); ++i) { 00413 int itype = maptypes[vobjects[i].type]; 00414 CHECKERBOARD& cb = vcheckers[itype]; 00415 Transform tglobal; 00416 tglobal.trans = Vector(vobjects[i].pose.position.x,vobjects[i].pose.position.y,vobjects[i].pose.position.z); 00417 tglobal.rot = Vector(vobjects[i].pose.orientation.w,vobjects[i].pose.orientation.x,vobjects[i].pose.orientation.y, vobjects[i].pose.orientation.z); 00418 Transform tlocal = tglobal * cb.tlocaltrans.inverse(); 00419 00420 CvPoint X[4]; 00421 00422 Vector vaxes[4]; 00423 vaxes[0] = Vector(0,0,0); 00424 vaxes[1] = Vector(0.05f,0,0); 00425 vaxes[2] = Vector(0,0.05f,0); 00426 vaxes[3] = Vector(0,0,0.05f); 00427 00428 for(int i = 0; i < 4; ++i) { 00429 Vector p = tglobal*vaxes[i]; 00430 dReal fx = p.x*camInfoMsg.P[0] + p.y*camInfoMsg.P[1] + p.z*camInfoMsg.P[2] + camInfoMsg.P[3]; 00431 dReal fy = p.x*camInfoMsg.P[4] + p.y*camInfoMsg.P[5] + p.z*camInfoMsg.P[6] + camInfoMsg.P[7]; 00432 dReal fz = p.x*camInfoMsg.P[8] + p.y*camInfoMsg.P[9] + p.z*camInfoMsg.P[10] + camInfoMsg.P[11]; 00433 X[i].x = (int)(fx/fz); 00434 X[i].y = (int)(fy/fz); 00435 } 00436 00437 // draw three lines 00438 CvScalar col0 = CV_RGB(255,0,(64*itype)%256); 00439 CvScalar col1 = CV_RGB(0,255,(64*itype)%256); 00440 CvScalar col2 = CV_RGB((64*itype)%256,(64*itype)%256,255); 00441 cvLine(frame, X[0], X[1], col0, 1); 00442 cvLine(frame, X[0], X[2], col1, 1); 00443 cvLine(frame, X[0], X[3], col2, 1); 00444 00445 // draw all the points 00446 for(size_t i = 0; i < cb.grid3d.size(); ++i) { 00447 Vector p = tlocal * cb.grid3d[i]; 00448 dReal fx = p.x*camInfoMsg.P[0] + p.y*camInfoMsg.P[1] + p.z*camInfoMsg.P[2] + camInfoMsg.P[3]; 00449 dReal fy = p.x*camInfoMsg.P[4] + p.y*camInfoMsg.P[5] + p.z*camInfoMsg.P[6] + camInfoMsg.P[7]; 00450 dReal fz = p.x*camInfoMsg.P[8] + p.y*camInfoMsg.P[9] + p.z*camInfoMsg.P[10] + camInfoMsg.P[11]; 00451 int x = (int)(fx/fz); 00452 int y = (int)(fy/fz); 00453 cvCircle(frame, cvPoint(x,y), 6, CV_RGB(0,0,0), 2); 00454 cvCircle(frame, cvPoint(x,y), 2, CV_RGB(0,0,0), 2); 00455 cvCircle(frame, cvPoint(x,y), 4, CV_RGB(128,128,64*itype), 3); 00456 } 00457 00458 cvCircle(frame, X[0], 3, CV_RGB(255,255,128), 3); 00459 } 00460 00461 cvShowImage("Checkerboard Detector",frame); 00462 } 00463 00464 return true; 00465 } 00466 00467 00469 // FindTransformation 00470 geometry_msgs::Pose FindTransformation(const vector<CvPoint2D32f> &imgpts, const vector<Vector> &objpts, const Transform& tlocal, CHECKERBOARD &cb) 00471 { 00472 CvMat *objpoints = cvCreateMat(3,objpts.size(),CV_32FC1); 00473 for(size_t i=0; i<objpts.size(); ++i) { 00474 cvSetReal2D(objpoints, 0,i, objpts[i].x); 00475 cvSetReal2D(objpoints, 1,i, objpts[i].y); 00476 cvSetReal2D(objpoints, 2,i, objpts[i].z); 00477 } 00478 00479 geometry_msgs::Pose pose; 00480 Transform tchecker; 00481 assert(sizeof(tchecker.trans.x)==sizeof(float)); 00482 float fR3[3]; 00483 CvMat R3, T3; 00484 assert(sizeof(pose.position.x) == sizeof(double)); 00485 cvInitMatHeader(&R3, 3, 1, CV_32FC1, fR3); 00486 cvInitMatHeader(&T3, 3, 1, CV_32FC1, &tchecker.trans.x); 00487 00488 float kc[4] = {0}; 00489 CvMat kcmat; 00490 cvInitMatHeader(&kcmat,1,4,CV_32FC1,kc); 00491 00492 CvMat img_points; 00493 cvInitMatHeader(&img_points, 1,imgpts.size(), CV_32FC2, const_cast<CvPoint2D32f*>(&imgpts[0])); 00494 00495 cvFindExtrinsicCameraParams2(objpoints, &img_points, this->intrinsic_matrix, &kcmat, &R3, &T3); 00496 cvReleaseMat(&objpoints); 00497 00498 double fang = sqrt(fR3[0]*fR3[0] + fR3[1]*fR3[1] + fR3[2]*fR3[2]); 00499 if( fang >= 1e-6 ) { 00500 double fmult = sin(fang/2)/fang; 00501 tchecker.rot = Vector(cos(fang/2),fR3[0]*fmult, fR3[1]*fmult, fR3[2]*fmult); 00502 } 00503 00504 // move pose to center of marker 00505 Transform center(Vector(1,0,0,0),Vector( 00506 cb.cellwidth*(cb.griddims.width-1)/2.0, 00507 cb.cellheight*(cb.griddims.height-1)/2.0, 00508 0)); 00509 00510 // disambiguate by tracking.. 00511 Transform rot180(Vector(1,0,0,0),Vector(0,0,0)); 00512 rot180.rotfromaxisangle(Vector(0,0,1),(float)M_PI); 00513 00514 Transform tglobal1 = tchecker*center*tlocal; 00515 Transform tglobal2 = tchecker*center*rot180*tlocal; 00516 TransformMatrix diff1(cb.previous_pose.inverse() * tglobal1); 00517 TransformMatrix diff2(cb.previous_pose.inverse() * tglobal2); 00518 00519 Transform tglobal; 00520 if(diff1.m[0]>=0) 00521 tglobal = tglobal1; 00522 else 00523 tglobal = tglobal2; 00524 00525 cb.previous_pose = tglobal; 00526 00527 pose.position.x = tglobal.trans.x; 00528 pose.position.y = tglobal.trans.y; 00529 pose.position.z = tglobal.trans.z; 00530 pose.orientation.x = tglobal.rot.y; 00531 pose.orientation.y = tglobal.rot.z; 00532 pose.orientation.z = tglobal.rot.w; 00533 pose.orientation.w = tglobal.rot.x; 00534 return pose; 00535 } 00536 00537 void activate(bool active, string image_topic = std::string(), string camera_info_topic = std::string()){ 00538 if(active){ 00539 image_transport::ImageTransport it(_node_pub); 00540 if(image_topic.empty() || camera_info_topic.empty()) 00541 { 00542 this->camInfoSubscriber = _node_pub.subscribe("camera_info", 1, &CheckerboardDetector::caminfo_cb, this); 00543 this->imageSubscriber = it.subscribe("image_rect", 1, &CheckerboardDetector::image_cb,this); 00544 } 00545 else{ 00546 this->camInfoSubscriber = _node_pub.subscribe(camera_info_topic, 1, &CheckerboardDetector::caminfo_cb, this); 00547 this->imageSubscriber = it.subscribe(image_topic, 1, &CheckerboardDetector::image_cb,this); 00548 } 00549 } 00550 else{ 00551 this->camInfoSubscriber.shutdown(); 00552 this->imageSubscriber.shutdown(); 00553 } 00554 _active = active; 00555 } 00556 00557 bool serviceCallback(checkerboard_detector2::Set::Request &req, 00558 checkerboard_detector2::Set::Response &res) 00559 { 00560 this->activate(req.active, req.image_topic, req.camera_info_topic); 00561 return true; 00562 } 00563 00564 00565 }; 00566 00568 // MAIN 00569 int main(int argc, char **argv) 00570 { 00571 ros::init(argc,argv,"checkerboard_detector"); 00572 if( !ros::master::check() ) 00573 return 1; 00574 00575 CheckerboardDetector cd; 00576 ros::spin(); 00577 00578 return 0; 00579 }