00001 #include <hrl_phri_2011/ellipsoid_space.h>
00002 #include <ros/ros.h>
00003 #include <sensor_msgs/PointCloud2.h>
00004 #include <pcl_ros/point_cloud.h>
00005 #include <pcl/point_cloud.h>
00006 #include <pcl/point_types.h>
00007 #include <pcl/kdtree/kdtree_flann.h>
00008 #include <Eigen/Eigen>
00009 #include <tf_conversions/tf_eigen.h>
00010 #include <hrl_phri_2011/EllipsoidParams.h>
00011 #include <hrl_phri_2011/hsl_rgb_conversions.h>
00012 #include <hrl_phri_2011/ForceProcessed.h>
00013 #include <hrl_phri_2011/pcl_basic.h>
00014 #include <hrl_phri_2011/utils.h>
00015
00016 #define NORMAL(x, sig) ( std::exp( - (x) * (x) / (2.0 * (sig) * (sig))) / std::sqrt(2.0 * 3.14159 * (sig) * (sig)))
00017
00018 void projectEllipsoid(Ellipsoid& ell, double ell_height, const PCRGB& pc, PCRGB& pc_ell);
00019 void createForceCloud(const vector<hrl_phri_2011::ForceProcessed::Ptr>& fps, PCRGB& fpc);
00020 void colorPCHSL(const PCRGB& in_pc, const vector<double>& values, PCRGB& out_pc, double hue=0);
00021 void createPriorCloud(const PCRGB& in_pc, const vector<hrl_phri_2011::ForceProcessed::Ptr>& fps, PCRGB& out_pc);
00022 void marginalEllipsoid(const PCRGB& pc, const vector<hrl_phri_2011::ForceProcessed::Ptr>& fps,
00023 const PCRGB& fpc, PCRGB& pc_ell, double sigma = 0.01);
00024 void projectEllipsoidDense(Ellipsoid& ell, double ell_height, const PCRGB& pc,
00025 int num_lat, int num_lon, double sigma = 0.01, int k = 10);
00026
00027 void projectEllipsoid(Ellipsoid& ell, double ell_height, const PCRGB& pc, PCRGB& pc_ell)
00028 {
00029 double lat, lon, height, x, y, z, h, s, l;
00030 BOOST_FOREACH(PRGB const pt, pc.points) {
00031 PRGB npt;
00032 extractHSL(pt.rgb, h, s, l);
00033 ell.cartToEllipsoidal(pt.x, pt.y, pt.z, lat, lon, height);
00034 ell.ellipsoidalToCart(lat, lon, ell_height, x, y, z);
00035 npt.x = x; npt.y = y; npt.z = z;
00036 writeHSL(0, 0, l, npt.rgb);
00037 pc_ell.points.push_back(npt);
00038 }
00039 pc_ell.header.frame_id = "base_link";
00040
00041 }
00042
00043 void createForceCloud(const vector<hrl_phri_2011::ForceProcessed::Ptr>& fps, PCRGB& fpc)
00044 {
00045
00046
00047
00048
00049 for(uint32_t i=0;i<fps.size();i++) {
00050
00051
00052
00053
00054
00055
00056
00057
00058 PRGB pt;
00059 pt.x = fps[i]->tool_frame.transform.translation.x;
00060 pt.y = fps[i]->tool_frame.transform.translation.y;
00061 pt.z = fps[i]->tool_frame.transform.translation.z;
00062 ((uint32_t*) &pt.rgb)[0] = 0xffffffff;
00063 fpc.points.push_back(pt);
00064 }
00065 }
00066
00067 void createPriorCloud(const PCRGB& in_pc, const vector<hrl_phri_2011::ForceProcessed::Ptr>& fps, PCRGB& out_pc)
00068 {
00069 double prior_sigma;
00070 ros::param::param<double>("~prior_sigma", prior_sigma, 0.01);
00071
00072 pcl::KdTreeFLANN<PRGB> kd_tree(new pcl::KdTreeFLANN<PRGB> ());
00073 kd_tree.setInputCloud(in_pc.makeShared());
00074 vector<int> inds1(1), inds2;
00075 vector<float> dists1(1), dists2;
00076 vector<double> pdf(in_pc.size());
00077 double normal, Z = 0;
00078 for(uint32_t i=0;i<fps.size();i++) {
00079 PRGB pt;
00080 pt.x = fps[i]->tool_frame.transform.translation.x;
00081 pt.y = fps[i]->tool_frame.transform.translation.y;
00082 pt.z = fps[i]->tool_frame.transform.translation.z;
00083 inds1[0] = -1;
00084 kd_tree.nearestKSearch(pt, 1, inds1, dists1);
00085 if(inds1[0] == -1)
00086 continue;
00087 inds2.clear(); dists2.clear();
00088 kd_tree.radiusSearch(pt, 3 * prior_sigma, inds2, dists2);
00089 for(size_t j=0;j<inds2.size();j++) {
00090 normal = NORMAL(dists2[j], prior_sigma);
00091 pdf[inds2[j]] += normal;
00092 Z += normal;
00093 }
00094 }
00095 colorPCHSL(in_pc, pdf, out_pc, 0);
00096 }
00097
00098 void colorPCHSL(const PCRGB& in_pc, const vector<double>& values, PCRGB& out_pc, double hue)
00099 {
00100 double max_val = *max_element(values.begin(), values.end());
00101 double h, s, l;
00102 for(size_t i=0;i<in_pc.size();i++) {
00103 const PRGB pt = in_pc.points[i];
00104 PRGB npt;
00105 npt.x = pt.x; npt.y = pt.y; npt.z = pt.z;
00106
00107 extractHSL(in_pc.points[i].rgb, h, s, l);
00108 s = 100.0 * values[i] / max_val;
00109 writeHSL(0, s, l, npt.rgb);
00110 out_pc.points.push_back(npt);
00111 }
00112 }
00113
00114 void marginalEllipsoid(const PCRGB& pc, const vector<hrl_phri_2011::ForceProcessed::Ptr>& fps,
00115 const PCRGB& fpc, PCRGB& pc_ell, double sigma)
00116 {
00117 pcl::KdTreeFLANN<PRGB> kd_tree(new pcl::KdTreeFLANN<PRGB> ());
00118 kd_tree.setInputCloud(fpc.makeShared());
00119 double h, s, l, normal, normal_sum, val_sum, val;
00120 int k = 5;
00121 vector<int> finds;
00122 vector<float> fdists;
00123 for(uint32_t i=0;i<pc.points.size();i++) {
00124 extractHSL(pc_ell.points[i].rgb, h, s, l);
00125 finds.resize(k, 0); fdists.resize(k, 10000);
00126 kd_tree.nearestKSearch(pc, i, 1, finds, fdists);
00127 normal_sum = 0; val_sum = 0;
00128 for(uint32_t j=0;j<finds.size();j++) {
00129 if(sqrt(fdists[j]) > sigma * 3)
00130 continue;
00131 if(fps[finds[j]]->force_normal < 0.2)
00132 continue;
00133 normal = NORMAL(fdists[j], sigma);
00134 val_sum += normal * fps[finds[j]]->force_normal;
00135 normal_sum += normal;
00136 }
00137 if(normal_sum == 0)
00138 continue;
00139 val = val_sum / normal_sum;
00140 s = 20 * val;
00141 if(s < 0)
00142 s = 0;
00143 if(s > 100)
00144 s = 100;
00145 writeHSL(0, s, l, pc_ell.points[i].rgb);
00146 }
00147 }
00148
00149 void projectEllipsoidDense(Ellipsoid& ell, double ell_height, const PCRGB& pc,
00150 int num_lat, int num_lon, double sigma, int k)
00151 {
00152 pcl::KdTreeFLANN<PRGB> kd_tree(new pcl::KdTreeFLANN<PRGB> ());
00153 kd_tree.setInputCloud(pc.makeShared());
00154 PCRGB pc_dense;
00155 vector<int> inds;
00156 vector<float> dists;
00157 double h, s, l, h_sum, s_sum, l_sum, normal, normal_sum;
00158 double x, y, z;
00159 double lat = 0, lon = 0;
00160 for(int i=0;i<num_lat;i++) {
00161 lat += PI / num_lat;
00162 lon = 0;
00163 for(int j=0;j<num_lon;j++) {
00164 lon += 2 * PI / num_lon;
00165 PRGB pt;
00166 ell.ellipsoidalToCart(lat, lon, ell_height, x, y, z);
00167 pt.x = x; pt.y = y; pt.z = z;
00168 inds.clear();
00169 dists.clear();
00170 kd_tree.nearestKSearch(pt, k, inds, dists);
00171 normal_sum = 0; h_sum = 0; s_sum = 0; l_sum = 0;
00172 for(uint32_t inds_i=0;inds_i<inds.size();inds_i++) {
00173 extractHSL(pc.points[inds[inds_i]].rgb, h, s, l);
00174 normal = NORMAL(dists[inds_i], sigma);
00175 normal_sum += normal;
00176 h_sum += normal * h; s_sum += normal * s; l_sum += normal * l;
00177 }
00178 writeHSL(h_sum / normal_sum, s_sum / normal_sum, l_sum / normal_sum, pt.rgb);
00179 pc_dense.points.push_back(pt);
00180 }
00181 }
00182 pc_dense.header.frame_id = "/base_link";
00183 pubLoop(pc_dense, "/proj_head");
00184 }
00185
00186
00187 int main(int argc, char **argv)
00188 {
00189 ros::init(argc, argv, "project_pc_ellipsoid");
00190
00191 PCRGB pc_head;
00192 Ellipsoid ell;
00193 loadRegisteredHead(argv[1], argv[2], pc_head, ell);
00194
00195
00196 vector<hrl_phri_2011::ForceProcessed::Ptr> forces;
00197 readBagTopic<hrl_phri_2011::ForceProcessed>(argv[3], forces, "/force_processed");
00198
00199 PCRGB fpc;
00200 createForceCloud(forces, fpc);
00201 fpc.header.frame_id = "/base_link";
00202 pubLoop(fpc, "force_cloud");
00203 return 0;
00204 PCRGB prior_cloud;
00205 createPriorCloud(pc_head, forces, prior_cloud);
00206 prior_cloud.header.frame_id = "/base_link";
00207 pubLoop(prior_cloud, "prior_cloud");
00208
00209 PCRGB pc_ell;
00210
00211
00212 projectEllipsoid(ell, ell.height, pc_head, pc_ell);
00213 marginalEllipsoid(pc_head, forces, fpc, pc_ell);
00214
00215
00216
00217 int num_lat, num_lon, num_nbrs;
00218 double sigma;
00219 ros::param::param<int>("~num_lat", num_lat, 300);
00220 ros::param::param<int>("~num_lon", num_lon, 300);
00221 ros::param::param<int>("~num_nbrs", num_nbrs, 10);
00222 ros::param::param<double>("~sigma", sigma, 0.01);
00223 projectEllipsoidDense(ell, ell.height, pc_ell, num_lat, num_lon, sigma, num_nbrs);
00224 }