Go to the documentation of this file.00001 #include <cstring>
00002 #include <stdexcept>
00003
00004 #include <boost/format.hpp>
00005
00006 #include <LinearMath/btMatrix3x3.h>
00007 #include <LinearMath/btQuaternion.h>
00008 #include <tf/transform_datatypes.h>
00009
00010 #include <sensor_msgs/Image.h>
00011 #include <sensor_msgs/image_encodings.h>
00012 #include <sensor_msgs/distortion_models.h>
00013
00014 #include <visp/vpImage.h>
00015
00016 #define protected public
00017 # include <visp/vpMbEdgeTracker.h>
00018 #undef protected
00019
00020 #define protected public
00021 # include <visp/vpMbKltTracker.h>
00022 #undef protected
00023
00024 #include "conversion.hh"
00025
00026 void rosImageToVisp(vpImage<unsigned char>& dst,
00027 const sensor_msgs::Image::ConstPtr& src)
00028 {
00029 using sensor_msgs::image_encodings::RGB8;
00030 using sensor_msgs::image_encodings::RGBA8;
00031 using sensor_msgs::image_encodings::BGR8;
00032 using sensor_msgs::image_encodings::BGRA8;
00033 using sensor_msgs::image_encodings::MONO8;
00034 using sensor_msgs::image_encodings::MONO16;
00035 using sensor_msgs::image_encodings::numChannels;
00036
00037
00038 if (src->width != dst.getWidth() || src->height != dst.getHeight())
00039 {
00040 ROS_INFO
00041 ("dst is %dx%d but src size is %dx%d, resizing.",
00042 src->width, src->height,
00043 dst.getWidth (), dst.getHeight ());
00044 dst.resize (src->height, src->width);
00045 }
00046
00047 if(src->encoding == MONO8)
00048 memcpy(dst.bitmap,
00049 &src->data[0],
00050 dst.getHeight () * src->step * sizeof(unsigned char));
00051 else if(src->encoding == RGB8 || src->encoding == RGBA8
00052 || src->encoding == BGR8 || src->encoding == BGRA8)
00053 {
00054 unsigned nc = numChannels(src->encoding);
00055 unsigned cEnd =
00056 (src->encoding == RGBA8 || src->encoding == BGRA8) ? nc - 1 : nc;
00057
00058 for(unsigned i = 0; i < dst.getWidth (); ++i)
00059 for(unsigned j = 0; j < dst.getHeight (); ++j)
00060 {
00061 int acc = 0;
00062 for(unsigned c = 0; c < cEnd; ++c)
00063 acc += src->data[j * src->step + i * nc + c];
00064 dst[j][i] = acc / nc;
00065 }
00066 }
00067 else
00068 {
00069 boost::format fmt("bad encoding '%1'");
00070 fmt % src->encoding;
00071 throw std::runtime_error(fmt.str());
00072 }
00073 }
00074
00075 void vispImageToRos(sensor_msgs::Image& dst,
00076 const vpImage<unsigned char>& src)
00077 {
00078 dst.width = src.getWidth();
00079 dst.height = src.getHeight();
00080 dst.encoding = sensor_msgs::image_encodings::MONO8;
00081 dst.step = src.getWidth();
00082 dst.data.resize(dst.height * dst.step);
00083 for(unsigned i = 0; i < src.getWidth (); ++i)
00084 for(unsigned j = 0; j < src.getHeight (); ++j)
00085 dst.data[j * dst.step + i] = src[j][i];
00086 }
00087
00088 void vpHomogeneousMatrixToTransform(geometry_msgs::Transform& dst,
00089 const vpHomogeneousMatrix& src)
00090 {
00091 btMatrix3x3 rotation;
00092 btQuaternion quaternion;
00093 for(unsigned i = 0; i < 3; ++i)
00094 for(unsigned j = 0; j < 3; ++j)
00095 rotation[i][j] = src[i][j];
00096 rotation.getRotation(quaternion);
00097
00098 dst.translation.x = src[0][3];
00099 dst.translation.y = src[1][3];
00100 dst.translation.z = src[2][3];
00101
00102 dst.rotation.x = quaternion.x();
00103 dst.rotation.y = quaternion.y();
00104 dst.rotation.z = quaternion.z();
00105 dst.rotation.w = quaternion.w();
00106 }
00107
00108 void transformToVpHomogeneousMatrix(vpHomogeneousMatrix& dst,
00109 const geometry_msgs::Transform& src)
00110 {
00111 btQuaternion quaternion
00112 (src.rotation.x, src.rotation.y, src.rotation.z, src.rotation.w);
00113 btMatrix3x3 rotation(quaternion);
00114
00115
00116 for(unsigned i = 0; i < 3; ++i)
00117 for(unsigned j = 0; j < 3; ++j)
00118 dst[i][j] = rotation[i][j];
00119
00120
00121 dst[0][3] = src.translation.x;
00122 dst[1][3] = src.translation.y;
00123 dst[2][3] = src.translation.z;
00124 }
00125
00126 void transformToVpHomogeneousMatrix(vpHomogeneousMatrix& dst,
00127 const geometry_msgs::Pose& src)
00128 {
00129 btQuaternion quaternion
00130 (src.orientation.x, src.orientation.y, src.orientation.z,
00131 src.orientation.w);
00132 btMatrix3x3 rotation(quaternion);
00133
00134
00135 for(unsigned i = 0; i < 3; ++i)
00136 for(unsigned j = 0; j < 3; ++j)
00137 dst[i][j] = rotation[i][j];
00138
00139
00140 dst[0][3] = src.position.x;
00141 dst[1][3] = src.position.y;
00142 dst[2][3] = src.position.z;
00143 }
00144
00145 void transformToVpHomogeneousMatrix(vpHomogeneousMatrix& dst,
00146 const tf::Transform& src)
00147 {
00148
00149 for(unsigned i = 0; i < 3; ++i)
00150 for(unsigned j = 0; j < 3; ++j)
00151 dst[i][j] = src.getBasis ()[i][j];
00152
00153
00154 for (unsigned i = 0; i < 3; ++i)
00155 dst[i][3] = src.getOrigin ()[i];
00156 dst[3][3] = 1.;
00157 }
00158
00159 void convertModelBasedSettingsConfigToVpMe(const visp_tracker::ModelBasedSettingsConfig& config,
00160 vpMe& moving_edge,
00161 vpMbTracker* tracker)
00162 {
00163 vpMbEdgeTracker* t = dynamic_cast<vpMbEdgeTracker*>(tracker);
00164
00165 moving_edge.mask_size = config.mask_size;
00166 moving_edge.n_mask = config.n_mask;
00167 moving_edge.range = config.range;
00168 moving_edge.threshold = config.threshold;
00169 moving_edge.mu1 = config.mu1;
00170 moving_edge.mu2 = config.mu2;
00171 moving_edge.sample_step = config.sample_step;
00172 moving_edge.ntotal_sample = config.ntotal_sample;
00173
00174 moving_edge.strip = config.strip;
00175 moving_edge.min_samplestep = config.min_samplestep;
00176 moving_edge.aberration = config.aberration;
00177 moving_edge.init_aberration = config.init_aberration;
00178
00179 t->setLambda(config.lambda);
00180 t->setFirstThreshold(config.first_threshold);
00181
00182
00183 moving_edge.initMask();
00184
00185 t->setMovingEdge(moving_edge);
00186 }
00187
00188 void convertVpMeToModelBasedSettingsConfig(const vpMe& moving_edge,
00189 const vpMbTracker* tracker,
00190 visp_tracker::ModelBasedSettingsConfig& config)
00191 {
00192 const vpMbEdgeTracker* t = dynamic_cast<const vpMbEdgeTracker*>(tracker);
00193
00194 config.mask_size = moving_edge.mask_size;
00195 config.n_mask = moving_edge.n_mask;
00196 config.range = moving_edge.range;
00197 config.threshold = moving_edge.threshold;
00198 config.mu1 = moving_edge.mu1;
00199 config.mu2 = moving_edge.mu2;
00200 config.sample_step = moving_edge.sample_step;
00201 config.ntotal_sample = moving_edge.ntotal_sample;
00202
00203 config.strip = moving_edge.strip;
00204 config.min_samplestep = moving_edge.min_samplestep;
00205 config.aberration = moving_edge.aberration;
00206 config.init_aberration = moving_edge.init_aberration;
00207
00208 config.lambda = t->lambda;
00209 config.first_threshold = t->percentageGdPt;
00210 }
00211
00212 void convertModelBasedSettingsConfigToVpKltOpencv(const visp_tracker::ModelBasedSettingsConfig& config,
00213 vpKltOpencv& klt,
00214 vpMbTracker* tracker)
00215 {
00216 vpMbKltTracker* t = dynamic_cast<vpMbKltTracker*>(tracker);
00217
00218 klt.setMaxFeatures(config.max_features);
00219 klt.setWindowSize(config.window_size);
00220 klt.setQuality(config.quality);
00221 klt.setMinDistance(config.min_distance);
00222 klt.setHarrisFreeParameter(config.harris);
00223 klt.setBlockSize(config.size_block);
00224 klt.setPyramidLevels(config.pyramid_lvl);
00225
00226 t->setAngleAppear(vpMath::rad(config.angle_appear));
00227 t->setAngleDisappear(vpMath::rad(config.angle_disappear));
00228 t->setMaskBorder((unsigned)config.mask_border);
00229
00230 t->setKltOpencv(klt);
00231 }
00232
00233 void convertVpKltOpencvToModelBasedSettingsConfig(const vpKltOpencv& klt,
00234 const vpMbTracker* tracker,
00235 visp_tracker::ModelBasedSettingsConfig& config)
00236 {
00237 const vpMbKltTracker* t = dynamic_cast<const vpMbKltTracker*>(tracker);
00238
00239 config.max_features = klt.getMaxFeatures();
00240 config.window_size = klt.getWindowSize();
00241 config.quality = klt.getQuality();
00242 config.min_distance = klt.getMinDistance();
00243 config.harris = klt.getHarrisFreeParameter();
00244 config.size_block = klt.getBlockSize();
00245 config.pyramid_lvl = klt.getPyramidLevels();
00246
00247 config.angle_appear = vpMath::deg(t->angleAppears);
00248 config.angle_disappear = vpMath::deg(t->angleDisappears);
00249 config.mask_border = t->maskBorder;
00250 }
00251
00252 void convertVpMeToInitRequest(const vpMe& moving_edge,
00253 const vpMbTracker* tracker,
00254 visp_tracker::Init& srv)
00255 {
00256 const vpMbEdgeTracker* t = dynamic_cast<const vpMbEdgeTracker*>(tracker);
00257
00258 srv.request.moving_edge.mask_size = moving_edge.mask_size;
00259 srv.request.moving_edge.n_mask = moving_edge.n_mask;
00260 srv.request.moving_edge.range = moving_edge.range;
00261 srv.request.moving_edge.threshold = moving_edge.threshold;
00262 srv.request.moving_edge.mu1 = moving_edge.mu1;
00263 srv.request.moving_edge.mu2 = moving_edge.mu2;
00264 srv.request.moving_edge.sample_step = moving_edge.sample_step;
00265 srv.request.moving_edge.ntotal_sample = moving_edge.ntotal_sample;
00266
00267 srv.request.moving_edge.strip = moving_edge.strip;
00268 srv.request.moving_edge.min_samplestep = moving_edge.min_samplestep;
00269 srv.request.moving_edge.aberration = moving_edge.aberration;
00270 srv.request.moving_edge.init_aberration = moving_edge.init_aberration;
00271
00272 srv.request.moving_edge.lambda = t->lambda;
00273 srv.request.moving_edge.first_threshold = t->percentageGdPt;
00274 }
00275
00276 void convertInitRequestToVpMe(const visp_tracker::Init::Request& req,
00277 vpMbTracker* tracker,
00278 vpMe& moving_edge)
00279 {
00280 vpMbEdgeTracker* t = dynamic_cast<vpMbEdgeTracker*>(tracker);
00281
00282 moving_edge.mask_size = req.moving_edge.mask_size;
00283 moving_edge.n_mask = req.moving_edge.n_mask;
00284 moving_edge.range = req.moving_edge.range;
00285 moving_edge.threshold = req.moving_edge.threshold;
00286 moving_edge.mu1 = req.moving_edge.mu1;
00287 moving_edge.mu2 = req.moving_edge.mu2;
00288 moving_edge.sample_step = req.moving_edge.sample_step;
00289 moving_edge.ntotal_sample = req.moving_edge.ntotal_sample;
00290
00291 moving_edge.strip = req.moving_edge.strip;
00292 moving_edge.min_samplestep = req.moving_edge.min_samplestep;
00293 moving_edge.aberration = req.moving_edge.aberration;
00294 moving_edge.init_aberration = req.moving_edge.init_aberration;
00295
00296 t->setLambda(req.moving_edge.lambda);
00297 t->setFirstThreshold(req.moving_edge.first_threshold);
00298 }
00299
00300 void convertVpKltOpencvToInitRequest(const vpKltOpencv& klt,
00301 const vpMbTracker* tracker,
00302 visp_tracker::Init& srv)
00303 {
00304 const vpMbKltTracker* t = dynamic_cast<const vpMbKltTracker*>(tracker);
00305
00306 srv.request.klt_param.max_features = klt.getMaxFeatures();
00307 srv.request.klt_param.window_size = klt.getWindowSize();
00308 srv.request.klt_param.quality = klt.getQuality();
00309 srv.request.klt_param.min_distance = klt.getMinDistance();
00310 srv.request.klt_param.harris = klt.getHarrisFreeParameter();
00311 srv.request.klt_param.size_block = klt.getBlockSize();
00312 srv.request.klt_param.pyramid_lvl = klt.getPyramidLevels();
00313
00314 srv.request.klt_param.angle_appear = vpMath::deg(t->angleAppears);
00315 srv.request.klt_param.angle_disappear = vpMath::deg(t->angleDisappears);
00316 srv.request.klt_param.mask_border = t->maskBorder;
00317 }
00318
00319 void convertInitRequestToVpKltOpencv(const visp_tracker::Init::Request& req,
00320 vpMbTracker* tracker,
00321 vpKltOpencv& klt)
00322 {
00323 vpMbKltTracker* t = dynamic_cast<vpMbKltTracker*>(tracker);
00324
00325 klt.setMaxFeatures(req.klt_param.max_features);
00326 klt.setWindowSize(req.klt_param.window_size);
00327 klt.setQuality(req.klt_param.quality);
00328 klt.setMinDistance(req.klt_param.min_distance);
00329 klt.setHarrisFreeParameter(req.klt_param.harris);
00330 klt.setBlockSize(req.klt_param.size_block);
00331 klt.setPyramidLevels(req.klt_param.pyramid_lvl);
00332
00333 t->setAngleAppear(vpMath::rad(req.klt_param.angle_appear));
00334 t->setAngleDisappear(vpMath::rad(req.klt_param.angle_disappear));
00335 t->setMaskBorder((unsigned)req.klt_param.mask_border);
00336 }
00337
00338 void initializeVpCameraFromCameraInfo(vpCameraParameters& cam,
00339 sensor_msgs::CameraInfoConstPtr info)
00340 {
00341 if (!info)
00342 throw std::runtime_error ("missing camera calibration data");
00343
00344
00345
00346 if (info->K.size() != 3 * 3 || info->K[0] == 0.)
00347 throw std::runtime_error ("uncalibrated camera");
00348
00349
00350 if (!info || info->P.size() != 3 * 4)
00351 throw std::runtime_error
00352 ("camera calibration P matrix has an incorrect size");
00353
00354 if (info->distortion_model.empty ())
00355 {
00356 const double& px = info->K[0 * 3 + 0];
00357 const double& py = info->K[1 * 3 + 1];
00358 const double& u0 = info->K[0 * 3 + 2];
00359 const double& v0 = info->K[1 * 3 + 2];
00360 cam.initPersProjWithoutDistortion(px, py, u0, v0);
00361 return;
00362 }
00363
00364 if (info->distortion_model == sensor_msgs::distortion_models::PLUMB_BOB)
00365 {
00366 const double& px = info->P[0 * 4 + 0];
00367 const double& py = info->P[1 * 4 + 1];
00368 const double& u0 = info->P[0 * 4 + 2];
00369 const double& v0 = info->P[1 * 4 + 2];
00370 cam.initPersProjWithoutDistortion(px, py, u0, v0);
00371 return;
00372 }
00373
00374 throw std::runtime_error ("unsupported distortion model");
00375 }