Go to the documentation of this file.00001 #include <iostream>
00002
00003 #include "TagFamily.h"
00004
00026 namespace AprilTags {
00027
00028 TagFamily::TagFamily(const TagCodes& tagCodes)
00029 : blackBorder(1), bits(tagCodes.bits), dimension((int)std::sqrt((float)bits)),
00030 minimumHammingDistance(tagCodes.minHammingDistance),
00031 errorRecoveryBits(1), codes() {
00032 if ( bits != dimension*dimension )
00033 cerr << "Error: TagFamily constructor called with bits=" << bits << "; must be a square number!" << endl;
00034 codes = tagCodes.codes;
00035 }
00036
00037 void TagFamily::setErrorRecoveryBits(int b) {
00038 errorRecoveryBits = b;
00039 }
00040
00041 void TagFamily::setErrorRecoveryFraction(float v) {
00042 errorRecoveryBits = (int) (((int) (minimumHammingDistance-1)/2)*v);
00043 }
00044
00045 unsigned long long TagFamily::rotate90(unsigned long long w, int d) {
00046 unsigned long long wr = 0;
00047 const unsigned long long oneLongLong = 1;
00048
00049 for (int r = d-1; r>=0; r--) {
00050 for (int c = 0; c<d; c++) {
00051 int b = r + d*c;
00052 wr = wr<<1;
00053
00054 if ((w & (oneLongLong<<b)) != 0)
00055 wr |= 1;
00056 }
00057 }
00058 return wr;
00059 }
00060
00061 int TagFamily::hammingDistance(unsigned long long a, unsigned long long b) {
00062 return popCount(a^b);
00063 }
00064
00065 unsigned char TagFamily::popCountReal(unsigned long long w) {
00066 unsigned char cnt = 0;
00067 while (w != 0) {
00068 w &= (w-1);
00069 ++cnt;
00070 }
00071 return cnt;
00072 }
00073
00074 int TagFamily::popCount(unsigned long long w) {
00075 int count = 0;
00076 while (w != 0) {
00077 count += popCountTable[(unsigned int) (w & (popCountTableSize-1))];
00078 w >>= popCountTableShift;
00079 }
00080 return count;
00081 }
00082
00083 void TagFamily::decode(TagDetection& det, unsigned long long rCode) const {
00084 int bestId = -1;
00085 int bestHamming = INT_MAX;
00086 int bestRotation = 0;
00087 unsigned long long bestCode = 0;
00088
00089 unsigned long long rCodes[4];
00090 rCodes[0] = rCode;
00091 rCodes[1] = rotate90(rCodes[0], dimension);
00092 rCodes[2] = rotate90(rCodes[1], dimension);
00093 rCodes[3] = rotate90(rCodes[2], dimension);
00094
00095 for (unsigned int id = 0; id < codes.size(); id++) {
00096 for (unsigned int rot = 0; rot < 4; rot++) {
00097 int thisHamming = hammingDistance(rCodes[rot], codes[id]);
00098 if (thisHamming < bestHamming) {
00099 bestHamming = thisHamming;
00100 bestRotation = rot;
00101 bestId = id;
00102 bestCode = codes[id];
00103 }
00104 }
00105 }
00106 det.id = bestId;
00107 det.hammingDistance = bestHamming;
00108 det.rotation = bestRotation;
00109 det.good = (det.hammingDistance <= errorRecoveryBits);
00110 det.obsCode = rCode;
00111 det.code = bestCode;
00112 }
00113
00114 void TagFamily::printHammingDistances() const {
00115 vector<int> hammings(dimension*dimension+1);
00116 for (unsigned i = 0; i < codes.size(); i++) {
00117 unsigned long long r0 = codes[i];
00118 unsigned long long r1 = rotate90(r0, dimension);
00119 unsigned long long r2 = rotate90(r1, dimension);
00120 unsigned long long r3 = rotate90(r2, dimension);
00121 for (unsigned int j = i+1; j < codes.size(); j++) {
00122 int d = min(min(hammingDistance(r0, codes[j]),
00123 hammingDistance(r1, codes[j])),
00124 min(hammingDistance(r2, codes[j]),
00125 hammingDistance(r3, codes[j])));
00126 hammings[d]++;
00127 }
00128 }
00129
00130 for (unsigned int i = 0; i < hammings.size(); i++)
00131 printf("hammings: %u = %d\n", i, hammings[i]);
00132 }
00133
00134 unsigned char TagFamily::popCountTable[TagFamily::popCountTableSize];
00135
00136 TagFamily::TableInitializer TagFamily::initializer;
00137
00138 }