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
00037 coloring->visualize(*widget, false, false, true, false);
00038
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
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
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:
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 };
00160
00161 #include <sonar_viz.moc>
00162
00163 int sonar_viz(int argc, char **argv,
00164 const Arak::Util::PropertyMap& props) {
00165
00166 coloring = new Arak::Coloring(props);
00167
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
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
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
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
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
00237 return sonar_viz(argc, argv, properties);
00238 }