#include <gadget/Filter/Position/PositionCalibrationFilter.h>
Inheritance diagram for gadget::PositionCalibrationFilter:


Public Member Functions | |
| PositionCalibrationFilter () | |
| Default Ctor. | |
| ~PositionCalibrationFilter () | |
| bool | config (jccl::ConfigElementPtr e) |
| Configuration for the filter. | |
| void | apply (std::vector< PositionData > &posSample) |
| Applies the position filter to the given sample in place. | |
Static Public Member Functions | |
| static std::string | getElementType () |
| Returns the string rep of the element type used to config this device. | |
Definition at line 56 of file PositionCalibrationFilter.h.
| gadget::PositionCalibrationFilter::PositionCalibrationFilter | ( | ) | [inline] |
| gadget::PositionCalibrationFilter::~PositionCalibrationFilter | ( | ) |
Definition at line 58 of file PositionCalibrationFilter.cpp.
00059 { 00060 for (size_t i = 0; i < mTable.size(); ++i) 00061 { 00062 delete[] mWMatrix[i]; 00063 } 00064 delete[] mWMatrix; 00065 }
| bool gadget::PositionCalibrationFilter::config | ( | jccl::ConfigElementPtr | e | ) | [virtual] |
Configuration for the filter.
Implements gadget::PositionFilter.
Definition at line 74 of file PositionCalibrationFilter.cpp.
References getElementType().
00075 { 00076 vprASSERT(e->getID() == PositionCalibrationFilter::getElementType()); 00077 vprDEBUG_OutputGuard(vprDBG_ALL, vprDBG_VERB_LVL, 00078 std::string("PositionCalibrationFilter::config: ") + 00079 e->getFullName() + std::string(":") + e->getID() + 00080 std::string("\n"), 00081 std::string("PositionCalibrationFilter::config: done.\n") ); 00082 std::string file_name = e->getProperty<std::string>("calibration_file",0); 00083 mFileName = jccl::ParseUtil::expandFileName(file_name, std::string("") ); 00084 00085 // Parse the calibration file. 00086 vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL) 00087 << "[PositionCalibrationFilter::config] Parsing " << mFileName << "\n" 00088 << vprDEBUG_FLUSH; 00089 00090 cppdom::ContextPtr context( new cppdom::Context() ); 00091 cppdom::DocumentPtr document( new cppdom::Document(context) ); 00092 00093 try 00094 { 00095 document->loadFile(mFileName); 00096 } 00097 catch (cppdom::Error e) 00098 { 00099 vprDEBUG(vprDBG_ERROR, vprDBG_CONFIG_LVL) 00100 << "[PositionCalibrationFilter::config] Unable to load calibration " 00101 << "file " << mFileName << ". " << e.getString() << " at " 00102 << e.getInfo() << vprDEBUG_FLUSH; 00103 return false; 00104 } 00105 00106 cppdom::NodePtr root = document->getChild("CalibrationTable"); 00107 if (NULL == root.get()) 00108 { 00109 vprDEBUG(vprDBG_ERROR, vprDBG_CONFIG_LVL) 00110 << "[PositionCalibrationFilter::config] Bad calibration file " 00111 << mFileName << "; could not retrieve the root node " 00112 << "'CalibrationTable'. " << vprDEBUG_FLUSH; 00113 return false; 00114 } 00115 00116 cppdom::NodeList offset_list; 00117 offset_list = root->getChildren("Offset"); 00118 cppdom::NodeListIterator itr; 00119 00120 for (itr = offset_list.begin(); itr != offset_list.end(); ++itr) 00121 { 00122 gmtl::Vec3d real_position; 00123 gmtl::Vec3d dev_position; 00124 00125 if ( (*itr)->hasAttribute("X") && 00126 (*itr)->hasAttribute("Y") && 00127 (*itr)->hasAttribute("Z") ) 00128 { 00129 real_position.set( (*itr)->getAttribute("X").getValue<double>(), 00130 (*itr)->getAttribute("Y").getValue<double>(), 00131 (*itr)->getAttribute("Z").getValue<double>() ); 00132 std::istringstream offset_stream((*itr)->getCdata()); 00133 //XXX: Error checking on the Cdata needs to be more robust. 00134 offset_stream >> dev_position[gmtl::Xelt]; 00135 offset_stream >> dev_position[gmtl::Yelt]; 00136 offset_stream >> dev_position[gmtl::Zelt]; 00137 00138 vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL) 00139 << "[PositionCalibrationFilter::config()] Added " 00140 << real_position << " --> " << dev_position << " " 00141 << "to the table.\n" 00142 << vprDEBUG_FLUSH; 00143 00144 mTable.push_back( std::make_pair(real_position, dev_position) ); 00145 } 00146 else 00147 { 00148 vprDEBUG(vprDBG_ERROR, vprDBG_CONFIG_LVL) 00149 << "[PositionCalibrationFilter::config()] Malformed Offset " 00150 << "Element. The element does not contain X, Y, and Z " 00151 << "attributes that represent a position; skipping.\n" 00152 << vprDEBUG_FLUSH; 00153 } 00154 } 00155 00156 // Now that we have the offsets, loop through the alpha elements to 00157 // obtain the coefficients. 00158 mAlphaVec.reserve(mTable.size()); 00159 cppdom::NodeList alpha_list = root->getChildren("Alpha"); 00160 if (alpha_list.empty()) 00161 { 00162 vprDEBUG(vprDBG_ERROR, vprDBG_CONFIG_LVL) 00163 << "[PositionCalibrationFilter::config()] Bad calibration file " 00164 << "'" << mFileName << "'\n" << "This file contains no Alpha " 00165 << " elements; these coefficients are necessary for calibration!\n" 00166 << vprDEBUG_FLUSH; 00167 return false; 00168 } 00169 for (itr = alpha_list.begin(); itr != alpha_list.end(); ++itr) 00170 { 00171 if ( (*itr)->hasAttribute("X") && 00172 (*itr)->hasAttribute("Y") && 00173 (*itr)->hasAttribute("Z") ) 00174 { 00175 gmtl::Vec3d alpha_value( 00176 (*itr)->getAttribute("X").getValue<double>(), 00177 (*itr)->getAttribute("Y").getValue<double>(), 00178 (*itr)->getAttribute("Z").getValue<double>() ); 00179 vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL) 00180 << "[PositionCalibrationFilter::config()] Added " 00181 << alpha_value 00182 << " to the alpha vector.\n" 00183 << vprDEBUG_FLUSH; 00184 mAlphaVec.push_back(alpha_value); 00185 } 00186 else 00187 { 00188 vprDEBUG(vprDBG_ERROR, vprDBG_CONFIG_LVL) 00189 << "[PositionCalibrationFilter::config()] " 00190 << "Malformed Alpha Element; this element does not contain " 00191 << "X="", Y="", Z="" attributes.\n" 00192 << vprDEBUG_FLUSH; 00193 } 00194 } 00195 00196 // Now that we have the calibration table, compute the W Matrix and then 00197 // solve for the Alpha Vector. 00198 00199 vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL) 00200 << "[PositionCalibrationFilter::config()] Calibration table parsed; " 00201 << "preparing W Matrix...\n" << vprDEBUG_FLUSH; 00202 00203 // The "W" Matrix is an NxN matrix where N = mTable.size() 00204 // It is composed of elements computed using the w(p) function: 00205 // w[j](p) = sqrt( length(p - p[j])^2 + R^2 ) 00206 // where 10 <= R^2 <= 1000. 00207 // The matrix looks like: 00208 // ( w[1](p[1]) w[2](p[1]) w[3](p[1]) ... w[N](p[1]) ) 00209 // ( w[1](p[2]) w[2](p[2]) w[3](p[2]) ... w[N](p[2]) ) 00210 // ( w[1](p[3]) w[2](p[3]) w[3](p[3]) ... w[N](p[3]) ) 00211 // ( . ) 00212 // ( . ) 00213 // ( . ) 00214 // ( w[1](p[N]) w[2](p[N]) w[3](p[N]) ... w[N](p[N]) ) 00215 00216 vprDEBUG(vprDBG_ALL, vprDBG_DETAILED_LVL) 00217 << "[PositionCalibrationFilter::config()] The W matrix is " 00218 << mTable.size() << "x" << mTable.size() << ".\n" 00219 << vprDEBUG_FLUSH; 00220 00221 double r_squared(0.4f); 00222 double r(0.63245553203367588f); 00223 mWMatrix = new double*[mTable.size()]; 00224 for (unsigned int i = 0; i < mTable.size(); ++i) 00225 { 00226 mWMatrix[i] = new double[mTable.size()]; 00227 for (unsigned int j = 0; j < mTable.size(); ++j) 00228 { 00229 if (i == j) 00230 { 00231 // Shortcut; the diagonal will always be equal to R. 00232 mWMatrix[i][j] = r; 00233 } 00234 else 00235 { 00236 // XXX: This is a workaround for GMTL CVS Head which supports 00237 // template meta-programming for vectors; unfortunately, 00238 // gmtl::length(v1 - v2) will not compile since the types 00239 // are NOT gmtl::Vec. 00240 gmtl::Vec3d difference = mTable[i].second - mTable[j].second; 00241 //double length = gmtl::length( difference ); 00242 mWMatrix[i][j] = gmtl::Math::sqrt( 00243 gmtl::dot(difference, difference) + 00244 r_squared ); 00245 } 00246 vprDEBUG(vprDBG_ALL, vprDBG_HEX_LVL) 00247 << "[PositionCalibrationFilter::config()] Assigning " 00248 << mWMatrix[i][j] 00249 << " to mWMatrix( " << i << ", " << j << ").\n" 00250 << vprDEBUG_FLUSH; 00251 } 00252 } 00253 00254 return true; 00255 }
| void gadget::PositionCalibrationFilter::apply | ( | std::vector< PositionData > & | posSample | ) | [virtual] |
Applies the position filter to the given sample in place.
| posSample | The sample to modify in place. |
Implements gadget::PositionFilter.
Definition at line 258 of file PositionCalibrationFilter.cpp.
00259 { 00260 vprDEBUG(vprDBG_ALL, vprDBG_DETAILED_LVL) 00261 << "[PositionCalibrationFilter::apply()] Received " << posSample.size() 00262 << " samples.\n" 00263 << vprDEBUG_FLUSH; 00264 std::vector< PositionData >::iterator itr; 00265 for (itr = posSample.begin(); itr != posSample.end(); ++itr) 00266 { 00267 // Prepare the position matrix for Hardy's multi-quadric method. 00268 // 00269 // Right now, we only calibrate the position, not the orientation, so 00270 // first, we need to pull out the translation matrix of posSample. 00271 // We do this using the standard method: 00272 // pull the rotation matrix R out 00273 // of the transformation matrix Tr and multiply R-inverse by Tr, ie, 00274 // inverse(R) * Tr = T 00275 // and since rotation matrices are orthogonal, 00276 // inverse(R) = transpose(R), so... 00277 // transpose(R) * Tr = T 00278 gmtl::Matrix44f rotation(itr->getPosition()); 00279 rotation[0][3] = 0; 00280 rotation[1][3] = 0; 00281 rotation[2][3] = 0; 00282 rotation[3][3] = 1; 00283 00284 gmtl::Matrix44f translation = gmtl::transpose(rotation) * itr->getPosition(); 00285 vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL) 00286 << "[PositionCalibrationFilter::apply()] Received tracked " 00287 << "position\n" << translation << "\n" 00288 << vprDEBUG_FLUSH; 00289 gmtl::Vec3d tracked_pos( translation[0][3], 00290 translation[1][3], 00291 translation[2][3] ); 00292 00293 // Now, we apply the following to the tracked position: 00294 // real_pos = alpha[j] * w[j](tracked_pos) + ... + alpha[N] * 00295 // w[N](tracked_pos) 00296 // where w[j](p) = sqrt( length( p - p[j] )^2 + R^2 ) 00297 // where 10 <= R^2 <= 1000. 00298 gmtl::Vec3d real_pos(0.0f, 0.0f, 0.0f); 00299 double r_squared = 40.0f; 00300 vprDEBUG(vprDBG_ALL, vprDBG_DETAILED_LVL) 00301 << "[PositionCalibrationFilter::apply()] Summing real position...\n" 00302 << vprDEBUG_FLUSH; 00303 for (unsigned int i = 0; i < mTable.size(); ++i) 00304 { 00305 // XXX: This is a workaround for GMTL CVS Head which supports 00306 // template meta-programming for vectors; unfortunately, 00307 // gmtl::length(v1 - v2) will not compile since the types are 00308 // NOT gmtl::Vec. 00309 gmtl::Vec3d difference = tracked_pos - mTable[i].second; 00310 //double length = gmtl::length(difference); 00311 real_pos += mAlphaVec[i] * 00312 gmtl::Math::sqrt( gmtl::dot(difference, difference) + 00313 r_squared ); 00314 vprDEBUG(vprDBG_ALL, vprDBG_DETAILED_LVL) 00315 << "[PositionCalibrationFilter::apply()] real_pos: " 00316 << real_pos << "\n" << vprDEBUG_FLUSH; 00317 } 00318 00319 00320 // Now we clobber the old transformation and replace it with a 00321 // translation to our real position. 00322 gmtl::Matrix44f new_translation; 00323 new_translation[0][3] = static_cast<float>(real_pos[0]); 00324 new_translation[1][3] = static_cast<float>(real_pos[1]); 00325 new_translation[2][3] = static_cast<float>(real_pos[2]); 00326 00327 vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL) 00328 << "[PositionCalibrationFilter::apply()] Replaced " 00329 << tracked_pos << " with \n" 00330 << real_pos << "\n" 00331 << vprDEBUG_FLUSH; 00332 vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL) 00333 << "[PositionCalibrationFilter::apply()] Replaced \n" << translation 00334 << "\nwith " << new_translation 00335 << vprDEBUG_FLUSH; 00336 00337 // Rebuild the position sample (transformation matrix). 00338 itr->setPosition(rotation * new_translation); 00339 } 00340 }
| std::string gadget::PositionCalibrationFilter::getElementType | ( | ) | [static] |
Returns the string rep of the element type used to config this device.
This string is used by the device factory to look up device drivers based up the type of element it is trying to load.
Reimplemented from gadget::PositionFilter.
Definition at line 68 of file PositionCalibrationFilter.cpp.
Referenced by config().
1.5.1