00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdio.h>
00010 #include <math.h>
00011 #include <malloc.h>
00012
00013 #include <ros/ros.h>
00014 #include <tf/transform_broadcaster.h>
00015 #include <tf/LinearMath/Matrix3x3.h>
00016
00017 #include <opencv2/opencv.hpp>
00018 #include <opencv2/core/core.hpp>
00019 #include <opencv2/calib3d/calib3d.hpp>
00020 #include <opencv2/imgproc/imgproc.hpp>
00021
00022 #include "RPP.h"
00023 #include "fiducial_pose/rosrpp.h"
00024
00025
00026 double r2d(double r)
00027 {
00028 return r / M_PI * 180.0;
00029 }
00030
00031
00032 double dist(cv::Mat pts, int i1, int i2)
00033 {
00034 double x1 = pts.at<double>(0, i1);
00035 double y1 = pts.at<double>(1, i1);
00036 double x2 = pts.at<double>(0, i2);
00037 double y2 = pts.at<double>(1, i2);
00038
00039 double dx = x1 - x2;
00040 double dy = y1 - y2;
00041
00042 return sqrt(dx*dx + dy*dy);
00043 }
00044
00045
00046
00047 double calcFiducialArea(cv::Mat pts)
00048 {
00049 double a1 = dist(pts, 0, 1);
00050 double b1 = dist(pts, 0, 3);
00051 double c1 = dist(pts, 1, 3);
00052
00053 double a2 = dist(pts, 1, 2);
00054 double b2 = dist(pts, 2, 3);
00055 double c2 = c1;
00056
00057 double s1 = (a1 + b1 + c1) / 2.0;
00058 double s2 = (a2 + b2 + c2) / 2.0;
00059
00060 a1 = sqrt(s1*(s1-a1)*(s1-b1)*(s1-c1));
00061 a2 = sqrt(s2*(s2-a2)*(s2-b2)*(s2-c2));
00062 return a1+a2;
00063 }
00064
00065
00066 void undistortPoints(cv::Mat pts, cv::Mat K, cv::Mat dist, bool doUndistort)
00067 {
00068 if (!doUndistort) {
00069 printf("fx %lf fy %lf cx %lf cy %lf", K.at<double>(0, 0), K.at<double>(1, 1), K.at<double>(0, 2), K.at<double>(1, 2));
00070 for (int i=0; i<pts.cols; i++) {
00071 pts.at<double>(0, i) = (pts.at<double>(0, i) - K.at<double>(0, 2)) / K.at<double>(0, 0);
00072 pts.at<double>(1, i) = (pts.at<double>(1, i) - K.at<double>(1, 2)) / K.at<double>(1, 1);
00073 }
00074 }
00075 else {
00076 cv::Mat src(1, pts.cols, CV_64FC2);
00077 cv::Mat dst(1, pts.cols, CV_64FC2);
00078
00079 for (int i=0; i<pts.cols; i++) {
00080 src.at<cv::Vec2d>(0, i)[0] = pts.at<double>(0, i);
00081 src.at<cv::Vec2d>(0, i)[1] = pts.at<double>(1, i);
00082 }
00083 std::vector<cv::Point2f> dest;
00084 cv::undistortPoints(src, dst, K, dist);
00085
00086 for (int i=0; i<pts.cols; i++) {
00087 pts.at<double>(0, i) = dst.at<cv::Vec2d>(0, i)[0];
00088 pts.at<double>(1, i) = dst.at<cv::Vec2d>(0, i)[1];
00089 }
00090 }
00091 }
00092
00093
00094 bool RosRpp::fiducialCallback(fiducial_pose::Fiducial* msg,
00095 fiducial_pose::FiducialTransform* ft)
00096 {
00097 ROS_INFO("date %d id %d direction %d",
00098 msg->header.stamp.sec, msg->fiducial_id,
00099 msg->direction);
00100
00101 if (!haveCamInfo) {
00102 ROS_ERROR("No camera info");
00103 return false;
00104 }
00105
00106 if (currentFrame != msg->image_seq) {
00107
00108 frameTime = ros::Time::now();
00109 currentFrame = msg->image_seq;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118 printf("frame %d fid %d dir %d vertices %lf %lf %lf %lf %lf %lf %lf %lf\n",
00119 msg->image_seq, msg->fiducial_id, msg->direction,
00120 msg->x0, msg->y0, msg->x1, msg->y1,
00121 msg->x2, msg->y2, msg->x3, msg->y3);
00122
00123 switch(msg->direction) {
00124 case 0:
00125
00126 ipts.at<double>(0,0) = msg->x0;
00127 ipts.at<double>(1,0) = msg->y0;
00128 ipts.at<double>(0,1) = msg->x1;
00129 ipts.at<double>(1,1) = msg->y1;
00130 ipts.at<double>(0,2) = msg->x2;
00131 ipts.at<double>(1,2) = msg->y2;
00132 ipts.at<double>(0,3) = msg->x3;
00133 ipts.at<double>(1,3) = msg->y3;
00134 break;
00135
00136 case 1:
00137
00138 ipts.at<double>(0,0) = msg->x3;
00139 ipts.at<double>(1,0) = msg->y3;
00140 ipts.at<double>(0,1) = msg->x0;
00141 ipts.at<double>(1,1) = msg->y0;
00142 ipts.at<double>(0,2) = msg->x1;
00143 ipts.at<double>(1,2) = msg->y1;
00144 ipts.at<double>(0,3) = msg->x2;
00145 ipts.at<double>(1,3) = msg->y2;
00146 break;
00147
00148 case 2:
00149
00150 ipts.at<double>(0,0) = msg->x2;
00151 ipts.at<double>(1,0) = msg->y2;
00152 ipts.at<double>(0,1) = msg->x3;
00153 ipts.at<double>(1,1) = msg->y3;
00154 ipts.at<double>(0,2) = msg->x0;
00155 ipts.at<double>(1,2) = msg->y0;
00156 ipts.at<double>(0,3) = msg->x1;
00157 ipts.at<double>(1,3) = msg->y1;
00158 break;
00159
00160 case 3:
00161
00162 ipts.at<double>(0,0) = msg->x1;
00163 ipts.at<double>(1,0) = msg->y1;
00164 ipts.at<double>(0,1) = msg->x2;
00165 ipts.at<double>(1,1) = msg->y2;
00166 ipts.at<double>(0,2) = msg->x3;
00167 ipts.at<double>(1,2) = msg->y3;
00168 ipts.at<double>(0,3) = msg->x0;
00169 ipts.at<double>(1,3) = msg->y0;
00170 break;
00171 }
00172
00173 #if 0
00174
00175
00176
00177 std::vector<cv::Point2f> imagePoints;
00178 std::vector<cv::Point3f> model2;
00179 for (int i=0; i<4; i++) {
00180 imagePoints.push_back(cv::Point2f(ipts.at<double>(0, i), ipts.at<double>(1, i)));
00181 model2.push_back(cv::Point3f(model.at<double>(0, i), model.at<double>(1, i), model.at<double>(2, i)));
00182 ROS_INFO("model %f %f %f", model.at<double>(0, i), model.at<double>(1, i), model.at<double>(2, i));
00183 }
00184
00185 cv::Mat rvec(3,1,cv::DataType<double>::type);
00186 cv::Mat tvec(3,1,cv::DataType<double>::type);
00187
00188 cv::solvePnP(model2, imagePoints, K, dist, rvec, tvec, false, CV_EPNP);
00189
00190 ROS_INFO("tvec %lf %lf %lf", tvec.at<double>(0, 0), tvec.at<double>(1, 0), tvec.at<double>(2, 0));
00191 ROS_INFO("rvec %lf %lf %lf", r2d(rvec.at<double>(0, 0)), r2d(rvec.at<double>(1, 0)), r2d(rvec.at<double>(2, 0)));
00192
00193 tf::Vector3 translation(tvec.at<double>(0, 0), tvec.at<double>(1, 0), tvec.at<double>(2, 0));
00194 tf::Quaternion rotation;
00195 rotation.setRPY(rvec.at<double>(0, 0), rvec.at<double>(1, 0), rvec.at<double>(2, 0));
00196 tf::Transform transform(rotation, translation);
00197
00198 ft->transform.translation.x = translation.x();
00199 ft->transform.translation.y = translation.y();
00200 ft->transform.translation.z = translation.z();
00201
00202 ft->transform.rotation.w = rotation.w();
00203 ft->transform.rotation.x = rotation.x();
00204 ft->transform.rotation.y = rotation.y();
00205 ft->transform.rotation.z = rotation.z();
00206 ft->fiducial_id = msg->fiducial_id;
00207 #else
00208
00209 undistortPoints(ipts, K, dist, doUndistort);
00210
00211 cv::Mat rotation;
00212 cv::Mat translation;
00213 int iterations;
00214 double obj_err;
00215 double img_err;
00216
00217 std::vector<RPP::Solution> sol;
00218
00219 std::map<int, cv::Mat>::iterator it;
00220
00221 it = prevRots.find(msg->fiducial_id);
00222 if (it == prevRots.end())
00223 rotation = cv::Mat();
00224 else
00225 rotation = it->second;
00226
00227 if(!RPP::Rpp(model, ipts, rotation, translation, iterations, obj_err, img_err, sol)) {
00228 ROS_ERROR("Cannot find transform for fiducial %d", msg->fiducial_id);
00229 return false;
00230 }
00231
00232 prevRots[msg->fiducial_id] = rotation;
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 tf::Matrix3x3 m1(rotation.at<double>(0,0), rotation.at<double>(0,1), rotation.at<double>(0,2),
00260 rotation.at<double>(1,0), rotation.at<double>(1,1), rotation.at<double>(1,2),
00261 rotation.at<double>(2,0), rotation.at<double>(2,1), rotation.at<double>(2,2));
00262 tf::Vector3 t1(translation.at<double>(0), translation.at<double>(1), translation.at<double>(2));
00263
00264 tf::Transform trans1(m1, t1);
00265
00266 frameTransforms[msg->fiducial_id] = trans1;
00267 t1 = trans1.getOrigin();
00268 m1 = trans1.getBasis();
00269
00270 double r, p, y;
00271 m1.getRPY(r, p, y);
00272 ROS_INFO("fid %d T: %.3lf %.3lf %.3lf R: %.2f %.2f %.2f",
00273 msg->fiducial_id,
00274 t1.x(), t1.y(), t1.z(),
00275 r2d(r), r2d(p), r2d(y));
00276
00277
00278
00279
00280
00281
00282
00283
00284 ft->transform.translation.x = t1.x();
00285 ft->transform.translation.y = t1.y();
00286 ft->transform.translation.z = t1.z();
00287 tf::Quaternion q = trans1.getRotation();
00288 ft->transform.rotation.w = q.w();
00289 ft->transform.rotation.x = q.x();
00290 ft->transform.rotation.y = q.y();
00291 ft->transform.rotation.z = q.z();
00292
00293 ft->fiducial_id = msg->fiducial_id;
00294
00295 ft->image_error = img_err;
00296 ft->object_error = obj_err;
00297 ft->fiducial_area = calcFiducialArea(ipts);
00298 #endif
00299 return true;
00300 }
00301
00302
00303 void RosRpp::camInfoCallback(const sensor_msgs::CameraInfo::ConstPtr& msg)
00304 {
00305 if (haveCamInfo) {
00306 return;
00307 }
00308
00309 for (int i=0; i<3; i++) {
00310 for (int j=0; j<3; j++) {
00311 K.at<double>(i, j) = msg->K[i*3+j];
00312 }
00313 }
00314
00315 printf("camera intrinsics:\n");
00316 RPP::Print(K);
00317
00318 for (int i=0; i<5; i++) {
00319 dist.at<double>(0,i) = msg->D[i];
00320 }
00321
00322 printf("distortion coefficients:\n");
00323 RPP::Print(dist);
00324
00325 haveCamInfo = true;
00326 }
00327
00328
00329 RosRpp::RosRpp(double fiducialLen, bool doUndistort)
00330 {
00331 this->fiducialLen = fiducialLen;
00332 this->doUndistort = doUndistort;
00333
00334
00335 K = cv::Mat::zeros(3, 3, CV_64F);
00336
00337
00338 dist = cv::Mat::zeros(1, 5, CV_64F);
00339
00340
00341 ipts = cv::Mat::ones(3, 4, CV_64F);
00342
00343
00344 model = cv::Mat::zeros(3, 4, CV_64F);
00345
00346 haveCamInfo = false;
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 model.at<double>(0,0) = fiducialLen / 2.0;
00364 model.at<double>(1,0) = -fiducialLen / 2.0;
00365
00366 model.at<double>(0,1) = -fiducialLen / 2.0;
00367 model.at<double>(1,1) = -fiducialLen / 2.0;
00368
00369 model.at<double>(0,2) = -fiducialLen / 2.0;
00370 model.at<double>(1,2) = fiducialLen / 2.0;
00371
00372 model.at<double>(0,3) = fiducialLen / 2.0;
00373 model.at<double>(1,3) = fiducialLen / 2.0;
00374
00375 currentFrame = 0;
00376 }