Go to the documentation of this file.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 
00031 
00032 
00033 
00034 
00035 
00036 #include "jsk_pcl_ros/viewpoint_sampler.h"
00037 #include <angles/angles.h>
00038 #include <opencv2/opencv.hpp>
00039 
00040 namespace jsk_pcl_ros
00041 {
00042   ViewpointSampler::ViewpointSampler(
00043     double angle_step, double angle_min, double angle_max,
00044     double radius_step, double radius_min, double radius_max, int n_points):
00045     angle_step_(angle_step), angle_min_(angle_min), angle_max_(angle_max),
00046     radius_step_(radius_step), radius_min_(radius_min), radius_max_(radius_max),
00047     index_(0),
00048     angle_(angle_min),
00049     radius_(radius_min),
00050     n_points_(n_points)
00051   {
00052     
00053   }
00054 
00055   void ViewpointSampler::reset()
00056   {
00057     index_ = 0;
00058     angle_ = angle_min_;
00059     radius_ = radius_min_;
00060   }
00061 
00062   void ViewpointSampler::next()
00063   {
00064     angle_ += angle_step_;
00065     if (angle_ > angle_max_ * 1.001) { 
00066       angle_ = angle_min_;
00067       radius_ += radius_step_;
00068       if (radius_ > radius_max_ * 1.001) { 
00069         radius_ = radius_min_;
00070         ++index_;
00071       }
00072     }
00073   }
00074 
00075   size_t ViewpointSampler::sampleNum()
00076   {
00077     return ((angle_max_ - angle_min_) / angle_step_ + 1) * n_points_ * ((radius_max_ - radius_min_) / radius_step_ + 1);
00078   }
00079 
00080   void ViewpointSampler::normalizeVector(
00081     double& x, double& y, double& z)
00082   {
00083     double norm = sqrt(x*x + y*y + z*z);
00084     x /= norm;
00085     y /= norm;
00086     z /= norm;
00087   }
00088   
00089   void ViewpointSampler::get(Eigen::Affine3f& transform)
00090   {
00091     
00092     double angle_rad = angles::from_degrees(angle_);
00093     const double inc = CV_PI * (3 - sqrt(5));
00094     const double off = 2.0f / double(n_points_);
00095     double y = index_ * off - 1.0f + (off / 2.0f);
00096     double r = sqrt(1.0f - y * y);
00097     double phi = index_ * inc;
00098     double x = std::cos(phi) * r;
00099     double z = std::sin(phi) * r;
00100     double lat = std::acos(z), lon;
00101     if ((fabs(std::sin(lat)) < 1e-5) || (fabs(y / std::sin(lat)) > 1))
00102       lon = 0;
00103     else
00104       lon = std::asin(y / std::sin(lat));
00105     x *= radius_; 
00106     y *= radius_; 
00107     z *= radius_; 
00108 
00109     cv::Vec3d T(x, y, z);
00110 
00111     
00112     double x_up = radius_ * std::cos(lon) * std::sin(lat - 1e-5) - x;
00113     double y_up = radius_ * std::sin(lon) * std::sin(lat - 1e-5) - y;
00114     double z_up = radius_ * std::cos(lat - 1e-5) - z;
00115     normalizeVector(x_up, y_up, z_up);
00116     
00117     
00118     double x_right = -y_up * z + z_up * y;
00119     double y_right = x_up * z - z_up * x;
00120     double z_right = -x_up * y + y_up * x;
00121     normalizeVector(x_right, y_right, z_right);
00122 
00123     
00124     double x_new_up = x_up * std::cos(angle_rad) + x_right * std::sin(angle_rad);
00125     double y_new_up = y_up * std::cos(angle_rad) + y_right * std::sin(angle_rad);
00126     double z_new_up = z_up * std::cos(angle_rad) + z_right * std::sin(angle_rad);
00127     cv::Vec3d up(x_new_up, y_new_up, z_new_up);
00128 
00129     
00130     cv::Vec3d l;
00131     l = up.cross(T);  
00132     normalizeVector(l(0),l(1),l(2));
00133     
00134     up = T.cross(l);  
00135     normalizeVector(up(0), up(1), up(2));
00136 
00137     
00138     Eigen::Vector3f ez = Eigen::Vector3f(-T[0], -T[1], -T[2]).normalized();
00139     Eigen::Vector3f ey = Eigen::Vector3f(up[0], up[1], up[2]).normalized();
00140     Eigen::Vector3f ex = ey.cross(ez).normalized();
00141     Eigen::Vector3f translation = Eigen::Vector3f(T[0], T[1], T[2]);
00142     Eigen::Matrix3f mat;
00143     mat.col(0) = ex;
00144     mat.col(1) = ey;
00145     mat.col(2) = ez;
00146     
00147     Eigen::Quaternionf q(mat);
00148     transform = Eigen::Translation3f(translation) * Eigen::AngleAxisf(q);
00149   }
00150 }