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

sonar_viz.cpp

Go to the documentation of this file.
00001 #include <iostream>
00002 #include <fstream>
00003 #include <sstream>
00004 #include <vector>
00005 #include "parsecl.hpp"
00006 #include "jet.hpp"
00007 #include "properties.hpp"
00008 #include "geometry.hpp"
00009 #include "coloring.hpp"
00010 #include "cone_tracing.hpp"
00011 #include "sonar_obs.hpp"
00012 #include <CGAL/IO/Qt_widget.h>
00013 #include <CGAL/IO/Qt_widget_layer.h>
00014 #include <CGAL/IO/Qt_widget_standard_toolbar.h>
00015 #include <CGAL/IO/Qt_widget_get_segment.h>
00016 #include <qapplication.h>
00017 #include <qmainwindow.h>
00018 #include <CGAL/Aff_transformation_2.h>
00019 
00020 using namespace Arak;
00021 
00022 Coloring* coloring;
00023 ArakPrior* prior;
00024 ArakPosteriorSonarObs* process;
00025 
00026 Geometry::Point point;
00027 double maxRange;
00028 double aperture;
00029 bool firstImpactOnly = false;
00030 
00031 std::vector<Arak::SonarImpact> impacts;
00032 std::vector<std::pair<double,double> > likelihood_fn;
00033 
00034 class My_Layer : public CGAL::Qt_widget_layer {
00035   void draw(){
00036     // First draw the map.
00037     coloring->visualize(*widget, false, false, true, false);
00038     // Now draw face impacts.
00039     double no_prev_returns_prob = 1.0;
00040     for (unsigned int i = 0; i < impacts.size(); i++) {
00041       const SonarImpact& impact = impacts[i];
00042       double return_prob = process->returnProb(impact);
00043       double first_return_prob = no_prev_returns_prob * return_prob;
00044       no_prev_returns_prob *= (1.0 - return_prob);
00045       unsigned char index = int(first_return_prob * double(Arak::jet_size));
00046       const CGAL::Color& c = Arak::jet_colors[index];
00047       if (!impact.isCorner()) 
00048   *widget << CGAL::LineWidth(0) << c << CGAL::FillColor(c) 
00049     << Geometry::Triangle(point, impact.pmin, impact.pmax);
00050     }
00051     // Now draw corner impacts.
00052     no_prev_returns_prob = 1.0;
00053     for (unsigned int i = 0; i < impacts.size(); i++) {
00054       const SonarImpact& impact = impacts[i];
00055       double return_prob = process->returnProb(impact);
00056       double first_return_prob = no_prev_returns_prob * return_prob;
00057       no_prev_returns_prob *= (1.0 - return_prob);
00058       unsigned char index = int(first_return_prob * double(Arak::jet_size));
00059       const CGAL::Color& c = Arak::jet_colors[index];
00060       if (impact.isCorner()) 
00061   *widget << CGAL::LineWidth(2) << c 
00062     << Geometry::Segment(point, impact.pmin);
00063     }
00064     // Visualize the likelihood function.
00065     double xmin = widget->x_min();
00066     double xmax = widget->x_max();
00067     double ymin = widget->y_min();
00068     double ymax = widget->y_max();
00069 
00070     typedef CGAL::Aff_transformation_2<Geometry::Kernel> Transformation;
00071     Arak::Geometry::Vector origin(xmin + 0.1 * (xmax - xmin),
00072           ymin + 0.1 * (ymax - ymin));
00073     Transformation trans(CGAL::TRANSLATION, origin);
00074     
00075 
00076     Transformation scale(CGAL::SCALING, (xmax - xmin) / (1.2 * maxRange));
00077     Transformation composed = trans * scale;
00078     *widget << CGAL::RED 
00079       << Geometry::Segment(CGAL::ORIGIN, Geometry::Point(maxRange, 0)).transform(composed)
00080       << Geometry::Segment(CGAL::ORIGIN, Geometry::Point(0, 1.0)).transform(composed);
00081     Geometry::Point prev = CGAL::ORIGIN;
00082     for (unsigned int i = 0; i < likelihood_fn.size(); i++) {
00083       double range = likelihood_fn[i].first;
00084       double likelihood = likelihood_fn[i].second;
00085       Geometry::Point next = Geometry::Point(range, likelihood);
00086       if (prev != CGAL::ORIGIN) 
00087   *widget << Geometry::Segment(prev, next).transform(composed);
00088       prev = next;
00089     }
00090     
00091   }
00092 };
00093 
00094 class My_Window : public QMainWindow {
00095   Q_OBJECT
00096 public:
00097   My_Window(int x, int y){
00098     widget = new CGAL::Qt_widget(this, "CGAL Qt_widget");
00099     setCentralWidget(widget);
00100     resize(x,y);
00101     widget->attach(&get_segment);
00102     widget->attach(&v);
00103     connect(widget, SIGNAL(new_cgal_object(CGAL::Object)), 
00104             this, SLOT(get_new_object(CGAL::Object)));
00105     std_toolbar = new CGAL::Qt_widget_standard_toolbar(widget, this,
00106                    "Standard Toolbar");
00107     Geometry::Rectangle bd = coloring->boundary();
00108     widget->set_window(CGAL::to_double(bd.xmin()), 
00109            CGAL::to_double(bd.xmax()), 
00110            CGAL::to_double(bd.ymin()), 
00111            CGAL::to_double(bd.ymax()));
00112   };
00113 private:  //members
00114   CGAL::Qt_widget_get_segment<Geometry::Kernel> get_segment;
00115   My_Layer v;
00116   CGAL::Qt_widget *widget;
00117   CGAL::Qt_widget_standard_toolbar *std_toolbar;
00118 private slots:
00119   void get_new_object(CGAL::Object obj) {
00120     Geometry::Segment seg;
00121     if (CGAL::assign(seg, obj)) { 
00122       point = seg.source();
00123       Geometry::Vector vec = seg.to_vector();
00124       double angle = atan2(CGAL::to_double(vec.y()), 
00125          CGAL::to_double(vec.x()));
00126       double angle_min = angle - aperture / 2.0;
00127       double angle_max = angle + aperture / 2.0;
00128       if (firstImpactOnly) {
00129   SonarImpact impact;
00130   impacts.clear();
00131   if (Arak::computeFirstSonarImpact(*coloring, point, 
00132             Geometry::Direction(cos(angle_min), 
00133                     sin(angle_min)), 
00134             Geometry::Direction(cos(angle_max), 
00135                     sin(angle_max)), 
00136             Geometry::Kernel::FT(maxRange), 
00137             impact)) 
00138     impacts.push_back(impact);
00139       } else {
00140   Arak::computeSonarImpacts(*coloring, point, 
00141           Geometry::Direction(cos(angle_min), 
00142                   sin(angle_min)), 
00143           Geometry::Direction(cos(angle_max), 
00144                   sin(angle_max)), 
00145           Geometry::Kernel::FT(maxRange), 
00146           impacts);
00147       }
00148       likelihood_fn.clear();
00149       for (double range = 0.0; range < maxRange; range += 0.01) {
00150   double likelihood = 
00151     process->likelihood(range, impacts.begin(), impacts.end());
00152   likelihood_fn.push_back(std::pair<double,double>(range, likelihood));
00153       }
00154       likelihood_fn.push_back(std::pair<double,double>(maxRange, 
00155                    process->likelihood(maxRange, impacts.begin(), impacts.end())));
00156       widget->redraw();
00157     }
00158   }
00159 }; //endclass
00160 
00161 #include <sonar_viz.moc> // MOC source file: sonar_viz.cpp
00162 
00163 int sonar_viz(int argc, char **argv,
00164         const Arak::Util::PropertyMap& props) {
00165   // Allocate the coloring.
00166   coloring = new Arak::Coloring(props);
00167   // Read the coloring from standard input.
00168   std::cin >> *coloring;
00169   if (!std::cin.good()) {
00170     std::cerr << "Error reading coloring from standard input." << std::endl;
00171     return 1;
00172   }
00173   // Form the sonar observation posterior.
00174   prior = new ArakPrior(*coloring, props);
00175   process = new ArakPosteriorSonarObs(*prior, props);
00176 
00177   QApplication app(argc, argv);
00178   My_Window *w = new My_Window(600, 600);
00179   app.setMainWidget(w);
00180   w->show();
00181   int result = app.exec();
00182   delete process;
00183   delete prior;
00184   delete coloring;
00185   return result;
00186 }
00187 
00192 int main(int argc, char** argv) {
00193   using namespace Arak::Util;
00194   // Parse the command line.
00195   CommandLine cl;
00196   CommandLine::MultiParameter<std::string>
00197     propFiles("-p", "--prop-file", "specifies a property file");
00198   cl.add(propFiles);
00199   CommandLine::MultiParameter<std::string>
00200     propDefs("-D", "--define-prop", "defines a property value");
00201   cl.add(propDefs);
00202   CommandLine::Option
00203     firstOpt("-f", "--first-only", "use first sonar impact only");
00204   cl.add(firstOpt);
00205 
00206   if (!cl.parse(argc, argv, std::cerr)) {
00207     cl.printUsage(std::cerr);
00208     exit(1);
00209   }
00210   firstImpactOnly = firstOpt.supplied();
00211 
00212   Arak::Util::PropertyMap properties;
00213 
00214   // Parse the properties files.
00215   const std::vector<std::string>& propFilePaths = propFiles.values();
00216   for (std::vector<std::string>::const_iterator it = propFilePaths.begin();
00217        it != propFilePaths.end(); it++) {
00218     std::string path = *it;
00219     std::ifstream in(path.data());
00220     in >> properties;
00221   }
00222   // Parse the overriding property definitions.
00223   const std::vector<std::string>& propDefinitions = propDefs.values();
00224   for (std::vector<std::string>::const_iterator it = propDefinitions.begin();
00225        it != propDefinitions.end(); it++) {
00226     std::string def = *it;
00227     std::istringstream in(def);
00228     in >> properties;
00229   }
00230 
00231   std::cout << "Properties:" << std::endl << properties << std::endl;
00232 
00233   assert(parse(getp(properties, "arak.sonar_obs.max_range"), maxRange));
00234   assert(parse(getp(properties, "arak.sonar_obs.aperture"), aperture));
00235 
00236   // Invoke the program.
00237   return sonar_viz(argc, argv, properties);
00238 }

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