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 #define BOOST_PARAMETER_MAX_ARITY 7
00036
00037 #include "jsk_recognition_utils/geo/cube.h"
00038 #include "jsk_recognition_utils/geo_util.h"
00039
00040 namespace jsk_recognition_utils
00041 {
00042 Cube::Cube(const Eigen::Vector3f& pos, const Eigen::Quaternionf& rot):
00043 pos_(pos), rot_(rot)
00044 {
00045 dimensions_.resize(3);
00046 }
00047
00048 Cube::Cube(const Eigen::Vector3f& pos, const Eigen::Quaternionf& rot,
00049 const std::vector<double>& dimensions):
00050 pos_(pos), rot_(rot), dimensions_(dimensions)
00051 {
00052
00053 }
00054 Cube::Cube(const Eigen::Vector3f& pos, const Eigen::Quaternionf& rot,
00055 const Eigen::Vector3f& dimensions):
00056 pos_(pos), rot_(rot)
00057 {
00058 dimensions_.resize(3);
00059 dimensions_[0] = dimensions[0];
00060 dimensions_[1] = dimensions[1];
00061 dimensions_[2] = dimensions[2];
00062 }
00063
00064 Cube::Cube(const Eigen::Vector3f& pos,
00065 const Line& line_a, const Line& line_b, const Line& line_c)
00066 {
00067 double distance_a_b = line_a.distance(line_b);
00068 double distance_a_c = line_a.distance(line_c);
00069 double distance_b_c = line_b.distance(line_c);
00070 Line::Ptr axis;
00071 dimensions_.resize(3);
00072 Eigen::Vector3f ex, ey, ez;
00073 if (distance_a_b >= distance_a_c &&
00074 distance_a_b >= distance_b_c) {
00075 axis = line_a.midLine(line_b);
00076 line_a.parallelLineNormal(line_c, ex);
00077 line_c.parallelLineNormal(line_b, ey);
00078
00079 }
00080 else if (distance_a_c >= distance_a_b &&
00081 distance_a_c >= distance_b_c) {
00082 axis = line_a.midLine(line_c);
00083 line_a.parallelLineNormal(line_b, ex);
00084 line_b.parallelLineNormal(line_c, ey);
00085 }
00086 else {
00087
00088
00089 axis = line_b.midLine(line_c);
00090 line_b.parallelLineNormal(line_a, ex);
00091 line_a.parallelLineNormal(line_c, ey);
00092 }
00093 dimensions_[0] = ex.norm();
00094 dimensions_[1] = ey.norm();
00095 axis->getDirection(ez);
00096 ez.normalize();
00097 ex.normalize();
00098 ey.normalize();
00099 if (ex.cross(ey).dot(ez) < 0) {
00100 ez = - ez;
00101 }
00102 rot_ = rotFrom3Axis(ex, ey, ez);
00103 axis->foot(pos, pos_);
00104 }
00105
00106 Cube::~Cube()
00107 {
00108
00109 }
00110
00111 std::vector<Segment::Ptr> Cube::edges()
00112 {
00113 std::vector<Segment::Ptr> ret;
00114 Eigen::Vector3f A = pos_
00115 + rot_ * ((+ dimensions_[0] * Eigen::Vector3f::UnitX()) +
00116 (- dimensions_[1] * Eigen::Vector3f::UnitY()) +
00117 (+ dimensions_[2] * Eigen::Vector3f::UnitZ())) / 2.0;
00118 Eigen::Vector3f B = pos_
00119 + rot_ * ((+ dimensions_[0] * Eigen::Vector3f::UnitX()) +
00120 (+ dimensions_[1] * Eigen::Vector3f::UnitY()) +
00121 (+ dimensions_[2] * Eigen::Vector3f::UnitZ())) / 2.0;
00122 Eigen::Vector3f C = pos_
00123 + rot_ * ((- dimensions_[0] * Eigen::Vector3f::UnitX()) +
00124 (+ dimensions_[1] * Eigen::Vector3f::UnitY()) +
00125 (+ dimensions_[2] * Eigen::Vector3f::UnitZ())) / 2.0;
00126 Eigen::Vector3f D = pos_
00127 + rot_ * ((- dimensions_[0] * Eigen::Vector3f::UnitX()) +
00128 (- dimensions_[1] * Eigen::Vector3f::UnitY()) +
00129 (+ dimensions_[2] * Eigen::Vector3f::UnitZ())) / 2.0;
00130 Eigen::Vector3f E = pos_
00131 + rot_ * ((+ dimensions_[0] * Eigen::Vector3f::UnitX()) +
00132 (- dimensions_[1] * Eigen::Vector3f::UnitY()) +
00133 (- dimensions_[2] * Eigen::Vector3f::UnitZ())) / 2.0;
00134 Eigen::Vector3f F = pos_
00135 + rot_ * ((+ dimensions_[0] * Eigen::Vector3f::UnitX()) +
00136 (+ dimensions_[1] * Eigen::Vector3f::UnitY()) +
00137 (- dimensions_[2] * Eigen::Vector3f::UnitZ())) / 2.0;
00138 Eigen::Vector3f G = pos_
00139 + rot_ * ((- dimensions_[0] * Eigen::Vector3f::UnitX()) +
00140 (+ dimensions_[1] * Eigen::Vector3f::UnitY()) +
00141 (- dimensions_[2] * Eigen::Vector3f::UnitZ())) / 2.0;
00142 Eigen::Vector3f H = pos_
00143 + rot_ * ((- dimensions_[0] * Eigen::Vector3f::UnitX()) +
00144 (- dimensions_[1] * Eigen::Vector3f::UnitY()) +
00145 (- dimensions_[2] * Eigen::Vector3f::UnitZ())) / 2.0;
00146
00147 ret.push_back(Segment::Ptr(new Segment(A, B)));
00148 ret.push_back(Segment::Ptr(new Segment(B, C)));
00149 ret.push_back(Segment::Ptr(new Segment(C, D)));
00150 ret.push_back(Segment::Ptr(new Segment(D, A)));
00151 ret.push_back(Segment::Ptr(new Segment(E, F)));
00152 ret.push_back(Segment::Ptr(new Segment(F, G)));
00153 ret.push_back(Segment::Ptr(new Segment(G, H)));
00154 ret.push_back(Segment::Ptr(new Segment(H, E)));
00155 ret.push_back(Segment::Ptr(new Segment(A, E)));
00156 ret.push_back(Segment::Ptr(new Segment(B, F)));
00157 ret.push_back(Segment::Ptr(new Segment(C, G)));
00158 ret.push_back(Segment::Ptr(new Segment(D, H)));
00159 return ret;
00160 }
00161
00162 ConvexPolygon::Ptr Cube::intersectConvexPolygon(Plane& plane)
00163 {
00164 std::vector<Segment::Ptr> candidate_edges = edges();
00165 Vertices intersects;
00166 for (size_t i = 0; i < candidate_edges.size(); i++) {
00167 Segment::Ptr edge = candidate_edges[i];
00168 Eigen::Vector3f p;
00169 if (edge->intersect(plane, p)) {
00170 intersects.push_back(p);
00171 }
00172 }
00173
00174
00175 pcl::ConvexHull<pcl::PointXYZ> chull;
00176 pcl::PointCloud<pcl::PointXYZ>::Ptr chull_input
00177 = verticesToPointCloud<pcl::PointXYZ>(intersects);
00178 pcl::PointCloud<pcl::PointXYZ>::Ptr chull_cloud
00179 (new pcl::PointCloud<pcl::PointXYZ>);
00180 chull.setDimension(2);
00181 chull.setInputCloud(chull_input);
00182 {
00183 boost::mutex::scoped_lock lock(global_chull_mutex);
00184 chull.reconstruct(*chull_cloud);
00185 }
00186
00187 return ConvexPolygon::Ptr(
00188 new ConvexPolygon(pointCloudToVertices(*chull_cloud)));
00189 }
00190
00191 jsk_recognition_msgs::BoundingBox Cube::toROSMsg()
00192 {
00193 jsk_recognition_msgs::BoundingBox ret;
00194 ret.pose.position.x = pos_[0];
00195 ret.pose.position.y = pos_[1];
00196 ret.pose.position.z = pos_[2];
00197 ret.pose.orientation.x = rot_.x();
00198 ret.pose.orientation.y = rot_.y();
00199 ret.pose.orientation.z = rot_.z();
00200 ret.pose.orientation.w = rot_.w();
00201 ret.dimensions.x = dimensions_[0];
00202 ret.dimensions.y = dimensions_[1];
00203 ret.dimensions.z = dimensions_[2];
00204 return ret;
00205 }
00206
00207 Vertices Cube::vertices()
00208 {
00209 Vertices vs;
00210 vs.push_back(buildVertex(0.5, 0.5, 0.5));
00211 vs.push_back(buildVertex(-0.5, 0.5, 0.5));
00212 vs.push_back(buildVertex(-0.5, -0.5, 0.5));
00213 vs.push_back(buildVertex(0.5, -0.5, 0.5));
00214 vs.push_back(buildVertex(0.5, 0.5, -0.5));
00215 vs.push_back(buildVertex(-0.5, 0.5, -0.5));
00216 vs.push_back(buildVertex(-0.5, -0.5, -0.5));
00217 vs.push_back(buildVertex(0.5, -0.5, -0.5));
00218 return vs;
00219 }
00220
00221
00222 Polygon::Ptr Cube::buildFace(const Eigen::Vector3f v0,
00223 const Eigen::Vector3f v1,
00224 const Eigen::Vector3f v2,
00225 const Eigen::Vector3f v3)
00226 {
00227 Vertices vs;
00228 vs.push_back(v0);
00229 vs.push_back(v1);
00230 vs.push_back(v2);
00231 vs.push_back(v3);
00232 Polygon::Ptr(new Polygon(vs));
00233 }
00234
00235 std::vector<Polygon::Ptr> Cube::faces()
00236 {
00237 std::vector<Polygon::Ptr> fs(6);
00238 Vertices vs = vertices();
00239 Eigen::Vector3f A = vs[0];
00240 Eigen::Vector3f B = vs[1];
00241 Eigen::Vector3f C = vs[2];
00242 Eigen::Vector3f D = vs[3];
00243 Eigen::Vector3f E = vs[4];
00244 Eigen::Vector3f F = vs[5];
00245 Eigen::Vector3f G = vs[6];
00246 Eigen::Vector3f H = vs[7];
00247 Vertices vs0, vs1, vs2, vs3, vs4, vs5, vs6;
00248 vs0.push_back(A); vs0.push_back(E); vs0.push_back(F); vs0.push_back(B);
00249 vs1.push_back(B); vs1.push_back(F); vs1.push_back(G); vs1.push_back(C);
00250 vs2.push_back(C); vs2.push_back(G); vs2.push_back(H); vs2.push_back(D);
00251 vs3.push_back(D); vs3.push_back(H); vs3.push_back(E); vs3.push_back(A);
00252 vs4.push_back(A); vs4.push_back(B); vs4.push_back(C); vs4.push_back(D);
00253 vs5.push_back(E); vs5.push_back(H); vs5.push_back(G); vs5.push_back(F);
00254 fs[0].reset(new Polygon(vs0));
00255 fs[1].reset(new Polygon(vs1));
00256 fs[2].reset(new Polygon(vs2));
00257 fs[3].reset(new Polygon(vs3));
00258 fs[4].reset(new Polygon(vs4));
00259 fs[5].reset(new Polygon(vs5));
00260 return fs;
00261 }
00262
00263 Eigen::Vector3f Cube::buildVertex(double i, double j, double k)
00264 {
00265 Eigen::Vector3f local = (Eigen::Vector3f::UnitX() * i * dimensions_[0] +
00266 Eigen::Vector3f::UnitY() * j * dimensions_[1] +
00267 Eigen::Vector3f::UnitZ() * k * dimensions_[2]);
00268 return Eigen::Translation3f(pos_) * rot_ * local;
00269 }
00270
00271 Eigen::Vector3f Cube::nearestPoint(const Eigen::Vector3f& p,
00272 double& distance)
00273 {
00274 std::vector<Polygon::Ptr> current_faces = faces();
00275 double min_distance = DBL_MAX;
00276 Eigen::Vector3f min_point;
00277 for (size_t i = 0; i < current_faces.size(); i++) {
00278 Polygon::Ptr f = current_faces[i];
00279 double d;
00280 Eigen::Vector3f q = f->nearestPoint(p, d);
00281 if (min_distance > d) {
00282 min_distance = d;
00283 min_point = q;
00284 }
00285 }
00286 distance = min_distance;
00287 return min_point;
00288 }
00289 }