00001 #include "ShapeFuns.h"
00002 #include "AprilTagData.h"
00003 #include "ShapeAprilTag.h"
00004 #include "MarkerData.h"
00005 #include "VRmixin.h"
00006 #include "Crew/MapBuilderRequest.h"
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
00050 const AngSignPi angdiff = 0;
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
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
00078
00079
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
00090 fmat::Column<3> camera_point = camera_vector * (distance / camera_vector.norm());
00091
00092 center.coords = camera_point;
00093 center.applyTransform(camToBase, egocentric);
00094
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
00120
00121
00122
00123 }
00124
00125 Sketch<bool>* AprilTagData::render() const {
00126 SketchSpace &SkS = space->getDualSpace();
00127 Sketch<bool> result(SkS, "render("+getName()+")");
00128 result = 0;
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();
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();
00177 }
00178
00179 DATASTUFF_CC(AprilTagData);
00180
00181 }