00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "Robots/LoBot/control/LoRenderResults.H"
00046 #include "Robots/LoBot/ui/LoMainWindow.H"
00047
00048 #include "Robots/LoBot/LoApp.H"
00049 #include "Robots/LoBot/slam/LoMap.H"
00050 #include "Robots/LoBot/slam/LoOccGrid.H"
00051 #include "Robots/LoBot/slam/LoSlamParams.H"
00052
00053 #include "Robots/LoBot/config/LoConfigHelpers.H"
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 #define YY_EXTRA_TYPE lobot::Experiment*
00066 #include "Robots/LoBot/metlog/LoExperiment.H"
00067 #include "Robots/LoBot/metlog/LoMetlogParser.H"
00068
00069 #include "Robots/LoBot/thread/LoPause.H"
00070
00071 #include "Robots/LoBot/misc/LoExcept.H"
00072 #include "Robots/LoBot/misc/LoRegistry.H"
00073 #include "Robots/LoBot/misc/LoTypes.H"
00074 #include "Robots/LoBot/misc/singleton.hh"
00075
00076 #include "Robots/LoBot/util/LoGL.H"
00077 #include "Robots/LoBot/util/LoFile.H"
00078 #include "Robots/LoBot/util/LoMath.H"
00079 #include "Robots/LoBot/util/triple.hh"
00080
00081
00082 #include "Util/log.H"
00083
00084
00085 #ifdef INVT_HAVE_LIBGLU
00086 #include <GL/glu.h>
00087 #endif
00088
00089 #ifdef INVT_HAVE_LIBGL
00090 #include <GL/gl.h>
00091 #endif
00092
00093
00094 #include <boost/algorithm/string.hpp>
00095
00096
00097 #include <fstream>
00098 #include <sstream>
00099 #include <string>
00100
00101
00102 #include <stdio.h>
00103
00104
00105
00106 namespace lobot {
00107
00108
00109
00110 namespace {
00111
00112
00113 template<typename T>
00114 inline T conf(const std::string& key, const T& default_value)
00115 {
00116 return get_conf<T>(LOBE_RENDER_RESULTS, key, default_value) ;
00117 }
00118
00119
00120 template<typename T>
00121 inline triple<T, T, T>
00122 conf(const std::string& key, const triple<T, T, T>& default_value)
00123 {
00124 return get_conf<T>(LOBE_RENDER_RESULTS, key, default_value) ;
00125 }
00126
00127
00128
00129 class RenderResultsParams : public singleton<RenderResultsParams> {
00130
00131
00132
00133
00134
00135
00136
00137 std::string m_results_dir ;
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 std::string m_results_file_name ;
00176
00177
00178
00179
00180
00181 std::string m_ss_fmt ;
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 bool m_bump, m_stop, m_extr, m_lgmd ;
00195
00196
00197
00198 GLColor m_bump_color, m_stop_color, m_extr_color, m_lgmd_color ;
00199
00200
00201
00202
00203
00204 bool m_slideshow ;
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 bool m_pause_on_dataset ;
00217
00218
00219
00220
00221
00222
00223
00224
00225 int m_update_delay ;
00226
00227
00228 RenderResultsParams() ;
00229 friend class singleton<RenderResultsParams> ;
00230
00231
00232 typedef const std::string& str ;
00233 typedef const GLColor& Color ;
00234
00235 public:
00236
00237
00238 static str results_file_name() {return instance().m_results_file_name ;}
00239 static str results_dir(){return instance().m_results_dir;}
00240 static str ss_fmt() {return instance().m_ss_fmt ;}
00241 static Color stop_color() {return instance().m_stop_color ;}
00242 static Color extr_color() {return instance().m_extr_color ;}
00243 static Color lgmd_color() {return instance().m_lgmd_color ;}
00244 static Color bump_color() {return instance().m_bump_color ;}
00245 static bool render_stop() {return instance().m_stop ;}
00246 static bool render_extr() {return instance().m_extr ;}
00247 static bool render_lgmd() {return instance().m_lgmd ;}
00248 static bool render_bump() {return instance().m_bump ;}
00249 static bool slideshow() {return instance().m_slideshow ;}
00250 static bool pause_on_dataset() {return instance().m_pause_on_dataset ;}
00251 static int update_delay() {return instance().m_update_delay ;}
00252
00253 } ;
00254
00255
00256 RenderResultsParams::RenderResultsParams()
00257 : m_results_dir(conf<std::string>("results_dir", "")),
00258 m_results_file_name(conf<std::string>("results_file_name",
00259 "/(metlog-[[:digit:]]{8}-[[:digit:]]{6}|result)$")),
00260 m_ss_fmt(std::string(".") +
00261 ui_conf<std::string>("screen_capture_fmt", "png")),
00262 m_bump(conf("render_bump_points", true)),
00263 m_stop(conf("render_stop_points", true)),
00264 m_extr(conf("render_lrf_extrication_points", true)),
00265 m_lgmd(conf("render_lgmd_extrication_points", true)),
00266 m_bump_color(conf<int>("bump_points_color",
00267 make_triple(255, 0, 0))),
00268 m_stop_color(conf<int>("stop_points_color",
00269 make_triple(255, 165, 0))),
00270 m_extr_color(conf<int>("lrf_extrication_points_color",
00271 make_triple(0, 0, 255))),
00272 m_lgmd_color(conf<int>("lgmd_extrication_points_color",
00273 make_triple(105, 139, 105))),
00274 m_slideshow(conf("slideshow", false)),
00275 m_pause_on_dataset(conf("pause_on_dataset", false)),
00276 m_update_delay(clamp(conf("update_delay", 2500), 500, 60000))
00277 {
00278 boost::trim(m_results_file_name) ;
00279 }
00280
00281
00282 typedef RenderResultsParams Params ;
00283
00284 }
00285
00286
00287
00288 RenderResults::RenderResults()
00289 : base(Params::update_delay(), LOBE_RENDER_RESULTS),
00290 m_traj(300), m_stop(75), m_extr(25), m_lgmd(50), m_bump(5),
00291 m_results_file_being_visualized(false)
00292 {
00293 start(LOBE_RENDER_RESULTS) ;
00294 }
00295
00296 void RenderResults::pre_run()
00297 {
00298 Map* map = App::map() ;
00299 if (! map)
00300 throw behavior_error(MAPPING_DISABLED) ;
00301
00302 const std::string map_file = SlamParams::map_file() ;
00303 if (map_file.empty())
00304 throw behavior_error(MAPPING_DISABLED) ;
00305 map->update(OccGrid(map_file)) ;
00306 map->add_hook(RenderHook(render_results,
00307 reinterpret_cast<unsigned long>(this))) ;
00308
00309 std::string goal_conf = get_conf<std::string>(LOBE_GOAL, "goals", "") ;
00310 if (goal_conf.empty())
00311 throw behavior_error(NO_GOALS) ;
00312 std::istringstream goal(goal_conf) ;
00313 goal >> m_goal ;
00314
00315 const std::string& results_dir = Params::results_dir() ;
00316 const std::string& results_file_name = Params::results_file_name() ;
00317 if (results_dir.empty() || results_file_name.empty())
00318 throw behavior_error(BAD_RESULTS_SPECS) ;
00319 m_results_files = find_file(results_dir, results_file_name) ;
00320 m_results = m_results_files.end() - 1 ;
00321 next() ;
00322 }
00323
00324 void RenderResults::load(const std::string& file_name)
00325 {
00326 m_results_file_being_visualized = false ;
00327 clear_point_lists() ;
00328 load_metlog(file_name) ;
00329 if (m_traj.empty()) {
00330 clear_point_lists() ;
00331 load_results(file_name) ;
00332 m_results_file_being_visualized = true ;
00333 }
00334
00335 const char* s = file_name.c_str() ;
00336 if (m_traj.empty())
00337 LERROR("%s: not a metlog nor a results file!", s) ;
00338 else
00339 LERROR("loaded %s", s) ;
00340 }
00341
00342 void RenderResults::load_metlog(const std::string& file_name)
00343 {
00344 FILE* file = fopen(file_name.c_str(), "r") ;
00345 if (! file)
00346 return ;
00347
00348 Experiment* experiment = Experiment::create(file_name) ;
00349
00350 yyscan_t parser ;
00351 lomet_parser_lex_init(&parser) ;
00352 lomet_parser_set_extra(experiment, parser) ;
00353 lomet_parser_set_in(file, parser) ;
00354 lomet_parser_lex(parser) ;
00355 lomet_parser_lex_destroy(parser) ;
00356 fclose(file) ;
00357
00358 m_traj = experiment->point_list(TRAJECTORY) ;
00359 m_stop = experiment->point_list(EMERGENCY_STOP) ;
00360 m_extr = experiment->point_list(EXTRICATE) ;
00361 m_lgmd = experiment->point_list(LGMD_EXTRICATE) ;
00362 m_bump = experiment->point_list(BUMP) ;
00363
00364 delete experiment ;
00365 }
00366
00367 void RenderResults::load_results(const std::string& file_name)
00368 {
00369 std::ifstream file(file_name.c_str()) ;
00370 for(;;)
00371 {
00372 std::string line ;
00373 std::getline(file, line) ;
00374 if (! file)
00375 break ;
00376
00377 std::istringstream point_spec(line) ;
00378 std::string point_type ; int x, y ;
00379 point_spec >> point_type >> x >> y ;
00380 if (point_type == "trajectory")
00381 m_traj.add(x, y) ;
00382 else if (point_type == "emergency_stop")
00383 m_stop.add(x, y) ;
00384 else if (point_type == "extricate")
00385 m_extr.add(x, y) ;
00386 else if (point_type == "lgmd_extricate")
00387 m_lgmd.add(x, y) ;
00388 else if (point_type == "bump")
00389 m_bump.add(x, y) ;
00390 }
00391 }
00392
00393
00394
00395 void RenderResults::action()
00396 {
00397 if (Params::slideshow()) {
00398 next() ;
00399 if (Params::pause_on_dataset() && m_results_file_being_visualized)
00400 Pause::toggle() ;
00401 }
00402 }
00403
00404 void RenderResults::keypress(unsigned char key)
00405 {
00406 switch (key)
00407 {
00408 case 'n':
00409 case 'N':
00410 case 'f':
00411 case 'F':
00412 case '+':
00413 case ' ':
00414 next() ;
00415 break ;
00416 case 'b':
00417 case 'B':
00418 case '-':
00419 prev() ;
00420 break ;
00421 case 's':
00422 case 'S':
00423 {
00424 std::string file_name = curr() + Params::ss_fmt() ;
00425 if (exists(file_name))
00426 LERROR("%s: already exists; will not overwrite",
00427 file_name.c_str()) ;
00428 else
00429 MainWindow::instance().save_screenshot(file_name) ;
00430 }
00431 break ;
00432 }
00433 }
00434
00435 void RenderResults::prev()
00436 {
00437 viz_lock() ;
00438 if (m_results == m_results_files.begin())
00439 m_results = m_results_files.end() ;
00440 --m_results ;
00441 load(*m_results) ;
00442 viz_unlock() ;
00443 }
00444
00445 void RenderResults::next()
00446 {
00447 viz_lock() ;
00448 ++m_results ;
00449 if (m_results == m_results_files.end())
00450 m_results = m_results_files.begin() ;
00451 load(*m_results) ;
00452 viz_unlock() ;
00453 }
00454
00455 std::string RenderResults::curr()
00456 {
00457 viz_lock() ;
00458 std::string results_file_name = *m_results ;
00459 viz_unlock() ;
00460 return results_file_name ;
00461 }
00462
00463
00464
00465 #ifdef INVT_HAVE_LIBGL
00466
00467
00468
00469
00470
00471 static void mpoint_to_vertex(const mPoint& p)
00472 {
00473 glVertex2i(p.second, p.first) ;
00474 }
00475
00476
00477 static void
00478 render_points(const PointList& L, const GLColor& color)
00479 {
00480 glPushAttrib(GL_POINT_BIT | GL_CURRENT_BIT) ;
00481 glPointSize(5) ;
00482 glColor3fv(color.rgb()) ;
00483 glBegin(GL_POINTS) ;
00484 std::for_each(L.begin(), L.end(), mpoint_to_vertex) ;
00485 glEnd() ;
00486 glPopAttrib() ;
00487 }
00488
00489
00490
00491 void RenderResults::render_results(unsigned long client_data)
00492 {
00493 const RenderResults* me = reinterpret_cast<RenderResults*>(client_data) ;
00494
00495
00496
00497
00498 float L, R, B, T ;
00499 SlamParams::map_extents(&L, &R, &B, &T) ;
00500 me->setup_view_volume(T, B, L, R) ;
00501
00502
00503 me->render_goal() ;
00504 me->render_traj() ;
00505 if (Params::render_stop())
00506 render_points(me->m_stop, Params::stop_color()) ;
00507 if (Params::render_extr())
00508 render_points(me->m_extr, Params::extr_color()) ;
00509 if (Params::render_lgmd())
00510 render_points(me->m_lgmd, Params::lgmd_color()) ;
00511 if (Params::render_bump())
00512 render_points(me->m_bump, Params::bump_color()) ;
00513
00514
00515 me->restore_view_volume() ;
00516 }
00517
00518
00519
00520 void RenderResults::render_goal() const
00521 {
00522 glPushAttrib(GL_LINE_BIT) ;
00523 glEnable(GL_LINE_STIPPLE) ;
00524 glLineStipple(1, 0xCCCC) ;
00525 glColor3f(1, 0, 0) ;
00526 glBegin(GL_LINE_LOOP) ;
00527 glVertex2f(m_goal.top, m_goal.left) ;
00528 glVertex2f(m_goal.bottom, m_goal.left) ;
00529 glVertex2f(m_goal.bottom, m_goal.right);
00530 glVertex2f(m_goal.top, m_goal.right);
00531 glEnd() ;
00532 glPopAttrib() ;
00533 }
00534
00535
00536 void RenderResults::render_traj() const
00537 {
00538 glColor3f(0, 0, 0) ;
00539 glBegin(GL_LINE_STRIP) ;
00540 std::for_each(m_traj.begin(), m_traj.end(), mpoint_to_vertex) ;
00541 glEnd() ;
00542 }
00543
00544 #endif
00545
00546
00547
00548 void RenderResults::clear_point_lists()
00549 {
00550 m_traj.clear() ;
00551 m_stop.clear() ;
00552 m_extr.clear() ;
00553 m_lgmd.clear() ;
00554 m_bump.clear() ;
00555 }
00556
00557 RenderResults::~RenderResults(){}
00558
00559
00560
00561 }
00562
00563
00564
00565
00566