Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

range_obs.cpp

Go to the documentation of this file.
00001 #include <set>
00002 #include <fstream>
00003 #include <CGAL/IO/Qt_widget.h>
00004 #include "range_obs.hpp"
00005 #include "jet.hpp"
00006 
00007 using namespace Arak;
00008 using namespace Arak::Geometry;
00009 
00010 #define REGISTER_QUERY_POINTS
00011 
00012 ArakPosteriorRangeObs::ArakPosteriorRangeObs(const ArakProcess& prior,
00013                const Arak::Util::PropertyMap& props)
00014   : ArakProcess(prior.getColoring()), prior(prior), updateId(0), lp(0.0) {
00015   using namespace Arak::Util;
00016   assert(parse(getp(props, "arak.range_obs.max_range"), maxRange));
00017   assert(parse(getp(props, "arak.range_obs.range_var"), rangeVar));
00018   assert(parse(getp(props, "arak.range_obs.prob_outlier"), pOutlier));
00019   assert(parse(getp(props, "arak.range_obs.prob_max_range_false_pos"), 
00020          pMaxFalsePos));
00021   assert(parse(getp(props, "arak.range_obs.prob_max_range_false_neg"), 
00022          pMaxFalseNeg));
00023   const std::string& datafile_path = 
00024     getp(props, "arak.range_obs.data_file");
00025   std::ifstream in(datafile_path.data());
00026   assert(in.good());
00027   int n;
00028   in >> n;
00029 #ifdef REGISTER_QUERY_POINTS
00030   std::vector<Geometry::Point> sources;
00031   sources.reserve(n);
00032 #endif
00033   obs.reserve(n);
00034   const Geometry::Rectangle& bd = prior.getColoring().boundary();
00035   for (int i = 0; i < n; i++) {
00036     Geometry::Point p, q;
00037     in >> p >> q;
00038     /*
00039     // Ignore observations that are not contained in the coloring's
00040     // boundary. (This isn't correct, but oh well.)
00041     if (prior.getColoring().outside(p) || 
00042   prior.getColoring().outside(q)) 
00043       continue;
00044     */
00045     RangeObs* o = new RangeObs(p, q, maxRange);
00046 #ifdef REGISTER_QUERY_POINTS
00047     sources.push_back(p);
00048 #endif
00049     obs.push_back(o);
00050   }
00051   assert(!in.bad());
00052   // Build the index.
00053   int rows, cols;
00054   if (hasp(props, "arak.range_obs.rows") &&
00055       hasp(props, "arak.range_obs.cols")) {
00056     assert(parse(getp(props, "arak.range_obs.rows"), rows));
00057     assert(parse(getp(props, "arak.range_obs.cols"), cols));
00058   } else {
00059     // Choose the size of the grid based upon the number of
00060     // measurements and the dimensions of the boundary.
00061     const double obsPerCell = 3.0;
00062     const double numCells = double(obs.size()) / obsPerCell;
00063     const double ar = 
00064       CGAL::to_double((c.boundary().xmax() - c.boundary().xmin()) /
00065           (c.boundary().ymax() - c.boundary().ymin()));
00066     rows = int(sqrt(numCells / ar));
00067     cols = int(numCells) / rows;
00068     // std::cerr << "Using " << rows << "x" << cols << " grid." << std::endl;
00069   }
00070   obsIndex = new RangeObsIndex(bd, rows, cols);
00071   // Initialize the likelihood.
00072   for (std::vector<RangeObs*>::iterator it = obs.begin(); 
00073        it != obs.end(); it++)
00074     lp += updateObsLP(*(*it), true);
00075   // Register with the coloring for updates.
00076   c.addListener(*this);
00077 #ifdef REGISTER_QUERY_POINTS
00078   QueryPointIndex index(sources, obs);
00079   c.addQueryPoints(index);
00080 #endif
00081 }
00082 
00083 ArakPosteriorRangeObs::RangeObs::RangeObs(const Geometry::Point& source, 
00084             const Geometry::Point& target, 
00085             const double maxRange) {
00086   this->source = source;
00087   this->target = target;
00088   const Geometry::Vector v = target - source;
00089   range = sqrt(CGAL::to_double(v.squared_length()));
00090   max = source + v * (maxRange / range);
00091   isMaxRange = (range > maxRange - 1e-2);
00092   curContact = source;
00093   curRange = 0.0;
00094   lp = 0.0;
00095   updateId = 0;
00096 }
00097 
00098 bool ArakPosteriorRangeObs::retraceObs(RangeObs& o, bool init) const {
00099   Coloring::IntEdgeHandle e;
00100   Geometry::Kernel::FT sd;
00101   Geometry::Point oldContact = o.curContact;
00102   if (c.trace(o.source, o.max, e, o.curContact, sd)) {
00103     o.curRange = sqrt(CGAL::to_double(sd));
00104   } else {
00105     o.curContact = o.max;
00106     o.curRange = maxRange;
00107   }
00108   if (oldContact != o.curContact) {
00109     // Remove the observation's old entries in the index.
00110     for (RangeObs::CellEntryList::iterator it = o.entries.begin();
00111    it != o.entries.end(); it++)
00112       it->remove();
00113     o.unused.splice(o.unused.begin(), o.entries, 
00114         o.entries.begin(), o.entries.end());
00115     // Use a line cell iterator to find all cells the line currently
00116     // intersects.
00117     typedef RangeObsIndex::LineCellIterator Iterator;
00118     Iterator it, end;
00119     if (obsIndex->boundary().has_on_unbounded_side(o.curContact))
00120       it = Iterator(*obsIndex, o.source, o.curContact, Iterator::RAY());
00121     else
00122       it = Iterator(*obsIndex, o.source, o.curContact, Iterator::SEGMENT());
00123     while (it != end) {
00124       /*
00125       assert(std::find(it->getItemList().begin(), 
00126            it->getItemList().end(), 
00127            RangeObsHandle(o)) == it->getItemList().end());
00128       */
00129       RangeObsIndex::Cell::Entry entry = it->add(RangeObsHandle(o));
00130       // Add the entry to this observation's list, using an unused
00131       // list entry if possible.
00132       if (o.unused.empty())
00133   o.entries.push_front(entry);
00134       else {
00135   RangeObs::CellEntryList::iterator jt = o.unused.begin();
00136   *jt = entry;
00137   o.entries.splice(o.entries.begin(), o.unused, jt);
00138       }
00139       ++it;
00140     }
00141     return true;
00142   } else
00143     return false;
00144 }
00145 
00146 double ArakPosteriorRangeObs::updateObsLP(RangeObs& o, bool init) const {
00147   // Update the sequence number.
00148   o.updateId = updateId;
00149   // Retrace the observation.
00150   if (!retraceObs(o, init)) return 0.0;
00151   // Record the old log probability.
00152   const double oldLP = o.lp;
00153   // First check that the source is not colored black.
00154 #ifdef REGISTER_QUERY_POINTS
00155   Color sourceColor = o.sourceColor;
00156 #else
00157   Color sourceColor = c.color(o.source);
00158 #endif
00159   if (sourceColor == BLACK) {
00160     o.lp = -1e10; // ln(1e-100);
00161   } else {
00162     if (o.curRange < maxRange) {
00163       // The correct observation is o.curRange.
00164       if (o.isMaxRange)
00165   // The probability of reflection.
00166   o.lp = ln(pMaxFalsePos);
00167       else {
00168   // Noisy measurement.
00169   double gl = exp(-pow(o.range - o.curRange, 2) / (2.0 * rangeVar)) /
00170     sqrt(rangeVar * 2.0 * M_PI);
00171   o.lp = ln((1.0 - pMaxFalsePos) * 
00172        ((pOutlier / maxRange) + (1.0 - pOutlier) * gl));
00173       }
00174       
00175     } else {
00176       // The correct observation is maxRange.
00177       if (o.isMaxRange)
00178   // The probability of getting a correct maxRange reading.
00179   o.lp = ln(1.0 - pMaxFalseNeg);
00180       else 
00181   // The probability of failing to get a maxRange reading.
00182   o.lp = ln(pMaxFalseNeg) - ln(maxRange);
00183     }
00184   }
00185   return o.lp - oldLP;
00186 }
00187 
00188 double ArakPosteriorRangeObs::logMeasure() const {
00189   return prior.logMeasure();
00190 }
00191 
00192 double ArakPosteriorRangeObs::potential() const {
00193   return prior.potential() - lp;
00194 }
00195 
00196 ArakPosteriorRangeObs::~ArakPosteriorRangeObs() { 
00197   for (std::vector<RangeObs*>::iterator it = obs.begin(); 
00198        it != obs.end(); it++)
00199     delete *it;
00200   delete obsIndex;
00201 }
00202 
00203 void ArakPosteriorRangeObs::visualize(CGAL::Qt_widget& widget) const {
00204   /*
00205   // Visualize the density of the index.
00206   const int maxSize = 100;
00207   for (int i = 0; i < obsIndex->numRows(); i++) 
00208     for (int j = 0; j < obsIndex->numCols(); j++) {
00209       const RangeObsIndex::Cell& cell = obsIndex->getCell(i, j);
00210       int size = cell.getItemList().size();
00211       // std::cerr << size << std::endl;
00212       unsigned char intensity = 
00213   int(std::min(double(size) / double(maxSize), 1.0) * 255.0);
00214       CGAL::Color fill(intensity, intensity, intensity);
00215       widget << fill << CGAL::FillColor(fill) << cell;
00216     }
00217   */
00218   // widget << CGAL::RED;
00219   for (std::vector<RangeObs*>::const_iterator it = obs.begin(); 
00220        it != obs.end(); it++) {
00221     const RangeObs* o = *it;
00222     const double max_likelihood = 5.0; // likelihoods can be greater than 1
00223     double normalized = std::min(exp(o->lp), max_likelihood) / max_likelihood;
00224     int n = int(double(jet_size - 1) * normalized);
00225     const CGAL::Color& color = jet_colors[n];
00226     /*
00227     if (c.color(o->source) == BLACK)
00228       widget << CGAL::YELLOW << Segment(o->source, o->target); 
00229     else {
00230       widget << CGAL::GREEN << Segment(o->source, o->target);
00231       widget << CGAL::RED << Segment(o->target, o->curContact);
00232     }
00233     */
00234     widget << color << Segment(o->source, o->target);
00235   }
00236 }
00237 
00238 void ArakPosteriorRangeObs::update(const Geometry::Point& a,
00239            const Geometry::Point& b,
00240            const Geometry::Point& c) {
00241   // Compute a set of observations that contains all observations
00242   // sensitive to the coloring in the supplied triangle.
00243   Geometry::Triangle t(a, b, c);
00244   RangeObsIndex::TriangleCellIterator it(*obsIndex, t), end;
00245   do {
00246     RangeObsIndex::Cell::ItemList& obsList = it->getItemList();
00247     typedef RangeObsIndex::Cell::ItemList::iterator Iterator;
00248     Iterator jt = obsList.begin();
00249     bool done = (jt == obsList.end());
00250     while (!done) {
00251       RangeObsHandle o = *jt;
00252       done = (++jt == obsList.end());
00253       if (o->updateId != updateId)
00254   lp += updateObsLP(*o);
00255     }
00256   } while (++it != end);
00257 }
00258 
00259 void ArakPosteriorRangeObs::recolored(const Geometry::Point& a,
00260               const Geometry::Point& b,
00261               const Geometry::Point& c) {
00262   updateId++;
00263   update(a, b, c);
00264 }
00265 
00266 void ArakPosteriorRangeObs::recolored(const Geometry::Point& a,
00267               const Geometry::Point& b,
00268               const Geometry::Point& c,
00269               const Geometry::Point& d) {
00270   updateId++;
00271   update(a, b, c);
00272   update(a, d, c);
00273 }
00274 

Generated on Wed May 25 14:39:18 2005 for Arak by doxygen 1.3.6