Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

AprilTagData.cc

Go to the documentation of this file.
00001 #include "ShapeFuns.h"
00002 #include "AprilTagData.h"
00003 #include "ShapeAprilTag.h"
00004 #include "MarkerData.h"  // for calculateCameraDistance
00005 #include "VRmixin.h"
00006 #include "Crew/MapBuilderRequest.h"  // for defaultMarkerHeight
00007 #include "Shared/Config.h"
00008 #include "Vision/AprilTags/TagDetector.h"
00009 
00010 namespace DualCoding {
00011 
00012 AprilTagData:: AprilTagData(ShapeSpace& _space, const AprilTags::TagDetection& _tagDetection)
00013   : BaseData(_space, getStaticType()), tagDetection(_tagDetection),
00014     center(Point(_tagDetection.cxy.first, _tagDetection.cxy.second, 0, camcentric)),
00015     q(), bl(getBottomLeftImagePoint()), br(getBottomRightImagePoint()) {}
00016 
00017 AprilTagData::AprilTagData(ShapeSpace& _space, const AprilTags::TagDetection& _tagDetection, const Point &_center, const fmat::Quaternion &_q)
00018   : BaseData(_space, getStaticType()), tagDetection(_tagDetection), center(_center), q(_q), bl(), br() {}
00019 
00020 AprilTagData::AprilTagData(const AprilTagData &other)
00021   : BaseData(other), tagDetection(other.tagDetection), center(other.center), q(other.q),
00022     bl(other.bl), br(other.br) {}
00023   
00024 BoundingBox2D AprilTagData::getBoundingBox() const {
00025   float xmin = min(min(tagDetection.p[0].first,tagDetection.p[1].first),
00026        min(tagDetection.p[2].first,tagDetection.p[3].first));
00027   float xmax = max(max(tagDetection.p[0].first,tagDetection.p[1].first),
00028        max(tagDetection.p[2].first,tagDetection.p[3].first));
00029   float ymin = min(min(tagDetection.p[0].second,tagDetection.p[1].second),
00030        min(tagDetection.p[2].second,tagDetection.p[3].second));
00031   float ymax = max(max(tagDetection.p[0].second,tagDetection.p[1].second),
00032        max(tagDetection.p[2].second,tagDetection.p[3].second));
00033   return BoundingBox2D(xmin,ymin,xmax,ymax);
00034 }
00035 
00036 Point AprilTagData::getTopLeft() const { return Point(tagDetection.p[3].first, tagDetection.p[3].second, 0, camcentric); }
00037 
00038 Point AprilTagData::getTopRight() const { return Point(tagDetection.p[2].first, tagDetection.p[2].second, 0, camcentric); }
00039 
00040 Point AprilTagData::getBottomLeft() const { return Point(tagDetection.p[0].first, tagDetection.p[0].second, 0, camcentric); }
00041 
00042 Point AprilTagData::getBottomRight() const { return Point(tagDetection.p[1].first, tagDetection.p[1].second, 0, camcentric); }
00043 
00044 bool AprilTagData::isMatchFor(const ShapeRoot& other) const {
00045   if ( ! isSameTypeAs(other) ) return false;
00046   const Shape<AprilTagData>& other_AprilTag = ShapeRootTypeConst(other,AprilTagData);
00047   if (getTagID() != other_AprilTag->getTagID()) return false;
00048   const float distance = getCentroid().distanceFrom(other_AprilTag->getCentroid());
00049   // disable orientation checking because we're not converting from camera to local/world
00050   const AngSignPi angdiff = 0; // *** getOrientation() - other_AprilTag->getOrientation();
00051   bool result = (distance < 200 && fabs(angdiff) < M_PI/6);
00052   return result;
00053 }
00054 
00055 bool AprilTagData::updateParams(const ShapeRoot& other, bool force) {
00056   // std::cout << "Merging AprilTags " << getId() << " and " << other->getId() << std::endl;
00057   center = (center + other->getCentroid()) / 2;
00058   return true;
00059 }
00060 
00061 void AprilTagData::printParams() const {
00062   std::cout << "Type = " << getTypeName() << "  ID=" << getId() << "  ParentID=" << getParentId() << std::endl;
00063 }
00064 
00065 void AprilTagData::applyTransform(const fmat::Transform& Tmat, const ReferenceFrameType_t newref) {
00066   center.applyTransform(Tmat,newref);
00067   bl.applyTransform(Tmat,newref);
00068   br.applyTransform(Tmat,newref);
00069   float orient = float((br-bl).atanYX()) - M_PI/2;
00070   q = fmat::Quaternion::aboutZ(orient);
00071 }
00072 
00073 fmat::Quaternion AprilTagData::getQuaternion() const { return q; }
00074 
00075 void AprilTagData::projectToGround(const fmat::Transform& camToBase,
00076                                    const PlaneEquation& groundplane) {
00077   // Transform into local coordinates using known distance from the
00078   // camera, which was computed by the MapBuilder based on known height
00079   // of the marker and placed in center.coordZ().
00080   const float xres = VRmixin::camSkS.getWidth();
00081   const float yres = VRmixin::camSkS.getHeight();
00082   const float maxres = std::max(xres,yres);
00083   const float normX = float(2*center.coordX() - xres) / maxres;
00084   const float normY = float(2*center.coordY() - yres) / maxres;
00085   const float distance = center.coordZ();
00086   fmat::Column<3> camera_vector;
00087   config->vision.computeRay(normX, normY,
00088           camera_vector[0],camera_vector[1],camera_vector[2]);
00089   // normalize and multiply by distance from camera to get actual point in space
00090   fmat::Column<3> camera_point = camera_vector * (distance / camera_vector.norm());
00091   // transform to base (ground) frame
00092   center.coords = camera_point;
00093   center.applyTransform(camToBase, egocentric);
00094   // cout << " camera_point=" << camera_point << "   new center=" << center << "  camToBase=" << camToBase << endl;
00095 
00096   coordinate_t markerHeight = MapBuilderRequest::defaultMarkerHeight;
00097   MarkerData::calculateCameraDistance(bl, markerHeight);
00098   MarkerData::calculateCameraDistance(br, markerHeight);
00099 
00100 
00101   const float normX0 = (2*bl.coordX() - xres) / maxres;
00102   const float normY0 = (2*bl.coordY() - yres) / maxres;
00103   config->vision.computeRay(normX0, normY0,
00104           camera_vector[0],camera_vector[1],camera_vector[2]);
00105   camera_point = camera_vector * (bl.coordZ() / camera_vector.norm());
00106   bl.coords = camera_point;
00107   bl.applyTransform(camToBase, egocentric);
00108 
00109   const float normX1 = (2*br.coordX() - xres) / maxres;
00110   const float normY1 = (2*br.coordY() - yres) / maxres;
00111   config->vision.computeRay(normX1, normY1,
00112           camera_vector[0],camera_vector[1],camera_vector[2]);
00113   camera_point = camera_vector * (br.coordZ() / camera_vector.norm());
00114   br.coords = camera_point;
00115   br.applyTransform(camToBase, egocentric);
00116 
00117   AngTwoPi orient = AngTwoPi(float((br-bl).atanYX()) - M_PI/2);
00118   q = fmat::Quaternion::aboutZ(orient);
00119   //std::cout << "*** Tag " << getTagID() << " bl=" << bl << " br=" << br
00120   //          << " orient = " << float(orient)*180/M_PI << std::endl;
00121   //fmat::Column<3> yprval = q.ypr();
00122   //std::cout << "   yaw=" << yprval[0] << " pitch=" << yprval[1] << " roll=" << yprval[2] << std::endl;
00123 }
00124 
00125 Sketch<bool>* AprilTagData::render() const {
00126   SketchSpace &SkS = space->getDualSpace();
00127   Sketch<bool> result(SkS, "render("+getName()+")");
00128   result = 0;   // *** incomplete rendering ***
00129   return new Sketch<bool>(result);
00130 }
00131 
00132 std::vector<Shape<AprilTagData> > AprilTagData::extractAprilTags(const Sketch<uchar> &rawY, const AprilTags::TagFamily &tagFamily) {
00133   AprilTags::TagDetector detector(tagFamily);
00134   std::vector<AprilTags::TagDetection> tags = detector.extractTags(rawY);
00135   std::vector<Shape<AprilTagData> > result;
00136   for ( std::vector<AprilTags::TagDetection>::const_iterator it = tags.begin();
00137         it != tags.end(); it++ ) {
00138     NEW_SHAPE(apriltag, AprilTagData, new AprilTagData(rawY->getSpace().getDualSpace(), *it));
00139     result.push_back(apriltag);
00140   }
00141   return result;
00142 }
00143 
00144 Shape<AprilTagData> AprilTagData::findTag(const std::vector<ShapeRoot> &shapevec, int tag) {
00145   for ( std::vector<ShapeRoot>::const_iterator it = shapevec.begin();
00146         it != shapevec.end(); it++ )
00147     if ( (*it)->isType(aprilTagDataType) ) {
00148       const Shape<AprilTagData> &t = ShapeRootTypeConst(*it,AprilTagData);
00149       if ( t->getTagID() == tag )
00150         return t;
00151     }
00152   return Shape<AprilTagData>();
00153 }
00154   
00155 bool AprilTagData::TagIDLessThan::operator() (const Shape<AprilTagData> &tag1, const Shape<AprilTagData> &tag2) const {
00156   return (tag1->getTagID() < tag2->getTagID());
00157 }
00158 
00159 Point AprilTagData::getBottomLeftImagePoint() const {
00160   float centerX = tagDetection.cxy.first;
00161   float centerY = tagDetection.cxy.second;
00162   for ( int i = 0; i < 4; i++ )
00163     if ( tagDetection.p[i].first < centerX )
00164       if ( tagDetection.p[i].second > centerY )
00165         return Point(tagDetection.p[i].first, tagDetection.p[i].second);
00166   return Point(); // should never get here
00167 }
00168 
00169 Point AprilTagData::getBottomRightImagePoint() const {
00170   float centerX = tagDetection.cxy.first;
00171   float centerY = tagDetection.cxy.second;
00172   for ( int i = 0; i < 4; i++ )
00173     if ( tagDetection.p[i].first > centerX )
00174       if ( tagDetection.p[i].second > centerY )
00175         return Point(tagDetection.p[i].first, tagDetection.p[i].second);
00176   return Point(); // should never get here
00177 }
00178 
00179 DATASTUFF_CC(AprilTagData);
00180 
00181 } // namespace

DualCoding 5.1CVS
Generated Mon May 9 04:56:25 2016 by Doxygen 1.6.3