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 #include "rosout_panel.h"
00036 #include "rosout_setup_dialog.h"
00037 #include "rosout_list_control.h"
00038
00039 #include <wx/wx.h>
00040 #include <wx/artprov.h>
00041
00042 #include <ros/ros.h>
00043 #include <ros/package.h>
00044
00045 #include <sstream>
00046 #include <algorithm>
00047
00048 #include <boost/bind.hpp>
00049
00050 #include "rosout_text_filter.h"
00051 #include "rosout_text_filter_control.h"
00052 #include "rosout_severity_filter.h"
00053 #include "rosout_severity_filter_control.h"
00054
00055 namespace rxtools
00056 {
00057
00058 RosoutPanel::RosoutPanel(wxWindow* parent, int id, wxPoint pos, wxSize size, int style)
00059 : RosoutPanelBase(parent, id, pos, size, style)
00060 , enabled_(false)
00061 , message_id_counter_(0)
00062 , max_messages_(20000)
00063 , needs_refilter_(false)
00064 , refilter_timer_(0.0f)
00065 , pause_(false)
00066 , logger_level_frame_(0)
00067 , connected_(true)
00068 , shutdown_thread_(false)
00069 , RECONNECTED_TO_MASTER_EVENT_(wxNewEventType())
00070 , DISCONNECTED_FROM_MASTER_EVENT_(wxNewEventType())
00071 {
00072 wxInitAllImageHandlers();
00073
00074 nh_.setCallbackQueue(&callback_queue_);
00075
00076 Connect(RECONNECTED_TO_MASTER_EVENT_, (wxObjectEventFunction)&RosoutPanel::onMasterReconnected, 0, this);
00077 Connect(DISCONNECTED_FROM_MASTER_EVENT_, (wxObjectEventFunction)&RosoutPanel::onMasterDisconnected, 0, this);
00078 check_master_thread_ = new boost::thread(boost::bind(&RosoutPanel::checkForMaster, this));
00079
00080 process_timer_ = new wxTimer(this);
00081 process_timer_->Start(250);
00082
00083 Connect(process_timer_->GetId(), wxEVT_TIMER, wxTimerEventHandler(RosoutPanel::onProcessTimer), NULL, this);
00084
00085 table_->setModel(this);
00086
00087 setTopic("/rosout_agg");
00088 setEnabled(true);
00089
00090 std::string icon_path = ros::package::getPath("rxtools") + "/icons/";
00091 delete_filter_bitmap_ = wxBitmap(wxString::FromAscii((icon_path + "delete-filter-16.png").c_str()), wxBITMAP_TYPE_PNG);
00092
00093 wxBitmap add_bitmap(wxString::FromAscii((icon_path + "add-16.png").c_str()), wxBITMAP_TYPE_PNG);
00094 add_filter_button_->SetBitmapLabel(add_bitmap);
00095
00096 add_filter_button_->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RosoutPanel::onAddFilterPressed), NULL, this);
00097
00098 {
00099 RosoutSeverityFilterPtr filter(new RosoutSeverityFilter);
00100 RosoutSeverityFilterControl* control = new RosoutSeverityFilterControl(this, filter);
00101 severity_filter_ = filter;
00102 severity_sizer_->Add(control, 0, wxEXPAND);
00103 severity_filter_->getChangedSignal().connect(boost::bind(&RosoutPanel::onFilterChanged, this, _1));
00104 }
00105
00106 createTextFilter();
00107
00108 filters_window_->SetMinSize(wxSize(-1, filters_[0].panel->GetSize().GetHeight() + add_filter_button_->GetSize().GetHeight() + 5));
00109 }
00110
00111 RosoutPanel::~RosoutPanel()
00112 {
00113 shutdown_thread_ = true;
00114 check_master_thread_->join();
00115 delete check_master_thread_;
00116
00117 unsubscribe();
00118
00119 Disconnect(process_timer_->GetId(), wxEVT_TIMER, wxTimerEventHandler(RosoutPanel::onProcessTimer), NULL, this);
00120
00121 delete process_timer_;
00122
00123 clear();
00124 }
00125
00126 void RosoutPanel::clear()
00127 {
00128 table_->SetItemCount(0);
00129 messages_.clear();
00130 ordered_messages_.clear();
00131 }
00132
00133 void RosoutPanel::setEnabled(bool enabled)
00134 {
00135 if (enabled_ == enabled)
00136 {
00137 return;
00138 }
00139
00140 enabled_ = enabled;
00141 if (enabled)
00142 {
00143 subscribe();
00144 }
00145 else
00146 {
00147 unsubscribe();
00148 }
00149 }
00150
00151 void RosoutPanel::subscribe()
00152 {
00153 if (!enabled_ || topic_.empty())
00154 {
00155 return;
00156 }
00157
00158 sub_ = nh_.subscribe(topic_, 0, &RosoutPanel::incomingMessage, this);
00159 }
00160
00161 void RosoutPanel::unsubscribe()
00162 {
00163 sub_.shutdown();
00164 }
00165
00166 void RosoutPanel::setTopic(const std::string& topic)
00167 {
00168 if (topic == topic_)
00169 {
00170 return;
00171 }
00172
00173 unsubscribe();
00174
00175 topic_ = topic;
00176
00177 subscribe();
00178 }
00179
00180 void RosoutPanel::setMessages(const M_IdToMessage& messages)
00181 {
00182 messages_ = messages;
00183
00184 if (messages.empty())
00185 {
00186 message_id_counter_ = 0;
00187 }
00188 else
00189 {
00190 message_id_counter_ = messages.rbegin()->first;
00191 }
00192
00193 refilter();
00194 }
00195
00196 RosoutFrame* RosoutPanel::createNewFrame()
00197 {
00198 RosoutFrame* frame = new RosoutFrame(0);
00199 frame->rosout_panel_->setMessages(messages_);
00200 frame->Show();
00201 frame->Raise();
00202
00203 return frame;
00204 }
00205
00206 void RosoutPanel::onNewWindow(wxCommandEvent& event)
00207 {
00208 createNewFrame();
00209 }
00210
00211 void RosoutPanel::onLoggerLevelsClose(wxCloseEvent& event)
00212 {
00213 logger_level_frame_->Show(false);
00214 event.Veto();
00215 }
00216
00217 void RosoutPanel::onLoggerLevels(wxCommandEvent& event)
00218 {
00219 if (!logger_level_frame_)
00220 {
00221 logger_level_frame_ = new LoggerLevelFrame(this);
00222 logger_level_frame_->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(RosoutPanel::onLoggerLevelsClose), NULL, this);
00223 }
00224
00225 logger_level_frame_->Show();
00226 logger_level_frame_->Raise();
00227 }
00228
00229 bool filterEnabledCheckboxEqual(wxWindowID id, const RosoutPanel::FilterInfo& info)
00230 {
00231 return info.enabled_cb && info.enabled_cb->GetId() == id;
00232 }
00233
00234 void RosoutPanel::onFilterEnableChecked(wxCommandEvent& event)
00235 {
00236 V_FilterInfo::iterator it = std::find_if(filters_.begin(), filters_.end(), boost::bind(filterEnabledCheckboxEqual, event.GetId(), _1));
00237 if (it != filters_.end())
00238 {
00239 FilterInfo& info = *it;
00240 info.filter->setEnabled(event.IsChecked());
00241 refilter();
00242 }
00243 }
00244
00245 bool filterDeleteButtonEqual(wxWindowID id, const RosoutPanel::FilterInfo& info)
00246 {
00247 return info.delete_button && info.delete_button->GetId() == id;
00248 }
00249
00250 void RosoutPanel::onFilterDelete(wxCommandEvent& event)
00251 {
00252 V_FilterInfo::iterator it = std::find_if(filters_.begin(), filters_.end(), boost::bind(filterDeleteButtonEqual, event.GetId(), _1));
00253 if (it != filters_.end())
00254 {
00255 FilterInfo& info = *it;
00256 removeFilter(info.filter);
00257 }
00258 }
00259
00260 bool filterUpButtonEqual(wxWindowID id, const RosoutPanel::FilterInfo& info)
00261 {
00262 return info.up_button && info.up_button->GetId() == id;
00263 }
00264
00265 void RosoutPanel::onFilterMoveUp(wxCommandEvent& event)
00266 {
00267 V_FilterInfo::iterator it = std::find_if(filters_.begin(), filters_.end(), boost::bind(filterUpButtonEqual, event.GetId(), _1));
00268 if (it != filters_.end() && it != filters_.begin())
00269 {
00270 FilterInfo& info = *it;
00271
00272 filters_sizer_->Detach(info.panel);
00273 size_t new_index = it - filters_.begin() - 1;
00274 filters_sizer_->Insert(new_index, info.panel, 0, wxEXPAND|wxBOTTOM, 1);
00275 filters_sizer_->Layout();
00276 std::swap(*it, *(it - 1));
00277
00278 resizeFiltersPane();
00279 updateFilterBackgrounds();
00280 }
00281 }
00282
00283 bool filterDownButtonEqual(wxWindowID id, const RosoutPanel::FilterInfo& info)
00284 {
00285 return info.down_button && info.down_button->GetId() == id;
00286 }
00287
00288 void RosoutPanel::onFilterMoveDown(wxCommandEvent& event)
00289 {
00290 V_FilterInfo::iterator it = std::find_if(filters_.begin(), filters_.end(), boost::bind(filterDownButtonEqual, event.GetId(), _1));
00291 if (it != filters_.end() && it != filters_.end() - 1)
00292 {
00293 FilterInfo& info = *it;
00294
00295 filters_sizer_->Detach(info.panel);
00296 size_t new_index = it - filters_.begin() + 1;
00297 filters_sizer_->Insert(new_index, info.panel, 0, wxEXPAND|wxBOTTOM, 1);
00298 filters_sizer_->Layout();
00299 std::swap(*it, *(it + 1));
00300
00301 resizeFiltersPane();
00302 updateFilterBackgrounds();
00303 }
00304 }
00305
00306 void RosoutPanel::updateFilterBackgrounds()
00307 {
00308 for (size_t i = 0; i < filters_.size(); ++i)
00309 {
00310 FilterInfo& info = filters_[i];
00311 if (i % 2 == 0)
00312 {
00313 info.panel->SetBackgroundColour(*wxLIGHT_GREY);
00314 info.control->SetBackgroundColour(*wxLIGHT_GREY);
00315 }
00316 else
00317 {
00318 info.panel->SetBackgroundColour(wxNullColour);
00319 info.control->SetBackgroundColour(wxNullColour);
00320 }
00321 }
00322 }
00323
00324 void RosoutPanel::addFilter(const RosoutFilterPtr& filter, wxWindow* control)
00325 {
00326 table_->preItemChanges();
00327
00328 FilterInfo info;
00329 info.filter = filter;
00330 info.control = control;
00331
00332 info.panel = new wxPanel(filters_window_, wxID_ANY);
00333 filters_sizer_->Add(info.panel, 0, wxEXPAND|wxBOTTOM, 1);
00334 info.panel->SetPosition(wxPoint(0, info.panel->GetSize().GetHeight() * filters_.size()));
00335
00336 if (filters_.size() % 2 == 0)
00337 {
00338 info.panel->SetBackgroundColour(*wxLIGHT_GREY);
00339 info.control->SetBackgroundColour(*wxLIGHT_GREY);
00340 }
00341 else
00342 {
00343 info.panel->SetBackgroundColour(wxNullColour);
00344 info.control->SetBackgroundColour(wxNullColour);
00345 }
00346
00347 control->Reparent(info.panel);
00348
00349 info.sizer = new wxBoxSizer(wxHORIZONTAL);
00350 info.panel->SetSizer(info.sizer);
00351
00352
00353 #if 01
00354
00355 {
00356 info.enabled_cb = new wxCheckBox(info.panel, wxID_ANY, wxT("Enabled"));
00357 info.enabled_cb->SetValue(filter->isEnabled());
00358 info.sizer->Add(info.enabled_cb, 0, wxALIGN_CENTER_VERTICAL);
00359 info.enabled_cb->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(RosoutPanel::onFilterEnableChecked), NULL, this);
00360 }
00361 #endif
00362
00363 info.sizer->Add(control, 1, wxALIGN_CENTER_VERTICAL);
00364
00365 info.delete_button = 0;
00366
00367 {
00368 info.delete_button = new wxBitmapButton(info.panel, wxID_ANY, delete_filter_bitmap_);
00369 info.sizer->Add(info.delete_button, 0, wxALIGN_CENTER_VERTICAL);
00370 info.delete_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RosoutPanel::onFilterDelete), NULL, this);
00371
00372 info.down_button = new wxBitmapButton(info.panel, wxID_ANY, wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_OTHER, wxSize(16, 16)));
00373 info.sizer->Add(info.down_button, 0, wxALIGN_CENTER_VERTICAL);
00374 info.down_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RosoutPanel::onFilterMoveDown), NULL, this);
00375
00376 info.up_button = new wxBitmapButton(info.panel, wxID_ANY, wxArtProvider::GetBitmap(wxART_GO_UP, wxART_OTHER, wxSize(16, 16)));
00377 info.sizer->Add(info.up_button, 0, wxALIGN_CENTER_VERTICAL);
00378 info.up_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RosoutPanel::onFilterMoveUp), NULL, this);
00379 }
00380
00381 filters_.push_back(info);
00382
00383 resizeFiltersPane();
00384
00385 filters_window_->Scroll(-1, 100000);
00386
00387 filter->getChangedSignal().connect(boost::bind(&RosoutPanel::onFilterChanged, this, _1));
00388
00389 needs_refilter_ = true;
00390
00391 table_->postItemChanges();
00392 }
00393
00394 void RosoutPanel::resizeFiltersPane()
00395 {
00396 filters_window_->Layout();
00397
00398 wxSize sizer_size = filters_window_->GetSizer()->GetMinSize();
00399 if (sizer_size.GetHeight() > 150)
00400 {
00401 filters_window_->SetMinSize(wxSize(-1, 150));
00402 filters_window_->GetSizer()->FitInside(filters_window_);
00403 }
00404 else
00405 {
00406 filters_window_->SetMinSize(wxSize(-1, sizer_size.GetHeight()));
00407 }
00408
00409 Layout();
00410 Refresh();
00411 }
00412
00413 bool filterEquals(const RosoutFilterPtr& filter, const RosoutPanel::FilterInfo& info)
00414 {
00415 return info.filter == filter;
00416 }
00417
00418 void RosoutPanel::removeFilter(const RosoutFilterPtr& filter)
00419 {
00420 V_FilterInfo::iterator it = std::find_if(filters_.begin(), filters_.end(), boost::bind(filterEquals, filter, _1));
00421 if (it != filters_.end())
00422 {
00423 FilterInfo& info = *it;
00424 info.panel->Destroy();
00425 filters_.erase(it);
00426
00427 resizeFiltersPane();
00428 updateFilterBackgrounds();
00429
00430 refilter();
00431 }
00432 }
00433
00434 void RosoutPanel::clearFilters()
00435 {
00436 while (!filters_.empty())
00437 {
00438 removeFilter(filters_.front().filter);
00439 }
00440 }
00441
00442 void RosoutPanel::onFilterChanged(const RosoutFilter*)
00443 {
00444 needs_refilter_ = true;
00445 }
00446
00447 template<class T>
00448 void printStuff(const std::string& name, T* win)
00449 {
00450 wxPoint point = win->GetPosition();
00451 wxSize size = win->GetSize();
00452 ROS_INFO("%s: x: %d, y: %d, w: %d, h: %d", name.c_str(), point.x, point.y, size.GetWidth(), size.GetHeight());
00453 }
00454
00455 #define PRINT_STUFF(description) \
00456 ROS_INFO(description); \
00457 printStuff(" filters_sizer_", filters_sizer_); \
00458 printStuff(" filters_window_->GetSizer()", filters_window_->GetSizer()); \
00459 printStuff(" filters_window_", filters_window_); \
00460 for (size_t i = 0; i < filters_.size(); ++i) \
00461 { \
00462 { \
00463 std::stringstream ss; \
00464 ss << " panel " << i; \
00465 printStuff(ss.str(), filters_[i].panel); \
00466 } \
00467 { \
00468 std::stringstream ss; \
00469 ss << " sizer " << i; \
00470 printStuff(ss.str(), filters_[i].sizer); \
00471 } \
00472 }
00473
00474 void RosoutPanel::onProcessTimer(wxTimerEvent& evt)
00475 {
00476 if (connected_)
00477 {
00478 callback_queue_.callAvailable(ros::WallDuration());
00479 }
00480
00481 processMessages();
00482
00483 refilter_timer_ += 0.25f;
00484 if (needs_refilter_ && refilter_timer_ > 0.5f)
00485 {
00486 refilter_timer_ = 0.0f;
00487 needs_refilter_ = false;
00488 refilter();
00489 }
00490
00491
00492 }
00493
00494 RosoutTextFilterPtr RosoutPanel::createTextFilter()
00495 {
00496 RosoutTextFilterPtr filter(new RosoutTextFilter);
00497 RosoutTextFilterControl* control = new RosoutTextFilterControl(filters_window_, filter);
00498 addFilter(filter, control);
00499
00500 return filter;
00501 }
00502
00503 void RosoutPanel::onAddFilterPressed(wxCommandEvent& event)
00504 {
00505 createTextFilter();
00506 }
00507
00508 void RosoutPanel::onClear(wxCommandEvent& event)
00509 {
00510 clear();
00511 }
00512
00513 void RosoutPanel::addMessageToTable(const rosgraph_msgs::Log::ConstPtr& message, uint32_t id)
00514 {
00515 ordered_messages_.push_back(id);
00516 }
00517
00518 rosgraph_msgs::LogConstPtr RosoutPanel::getMessageByIndex(uint32_t index) const
00519 {
00520 if (index >= ordered_messages_.size())
00521 {
00522 return rosgraph_msgs::LogConstPtr();
00523 }
00524
00525 M_IdToMessage::const_iterator it = messages_.find(ordered_messages_[index]);
00526 ROS_ASSERT(it != messages_.end());
00527
00528 return it->second;
00529 }
00530
00531 bool RosoutPanel::filter(uint32_t id) const
00532 {
00533
00534 if (filters_.empty())
00535 {
00536 return true;
00537 }
00538
00539 M_IdToMessage::const_iterator it = messages_.find(id);
00540 ROS_ASSERT(it != messages_.end());
00541
00542 const rosgraph_msgs::LogConstPtr& message = it->second;
00543
00544
00545 if (!severity_filter_->filter(message))
00546 {
00547 return false;
00548 }
00549
00550 {
00551 V_FilterInfo::const_iterator it = filters_.begin();
00552 V_FilterInfo::const_iterator end = filters_.end();
00553 for (; it != end; ++it)
00554 {
00555 const FilterInfo& info = *it;
00556 const RosoutFilterPtr& filter = info.filter;
00557 if (filter->isEnabled() && filter->isValid())
00558 {
00559 if (!filter->filter(message))
00560 {
00561 return false;
00562 }
00563 }
00564 }
00565 }
00566
00567 return true;
00568 }
00569
00570 void RosoutPanel::validateOrderedMessages()
00571 {
00572 #if VALIDATE_FILTERING
00573 typedef std::set<uint32_t> S_u32;
00574 S_u32 s;
00575 V_u32::iterator it = ordered_messages_.begin();
00576 V_u32::iterator end = ordered_messages_.end();
00577 for (; it != end; ++it)
00578 {
00579 uint32_t id = *it;
00580 if (!s.insert(id).second)
00581 {
00582 ROS_BREAK();
00583 }
00584 }
00585 #endif
00586 }
00587
00588 void RosoutPanel::refilter()
00589 {
00590 table_->preItemChanges();
00591
00592 ordered_messages_.clear();
00593 M_IdToMessage::iterator it = messages_.begin();
00594 M_IdToMessage::iterator end = messages_.end();
00595 for (; it != end; ++it)
00596 {
00597 uint32_t id = it->first;
00598 rosgraph_msgs::Log::ConstPtr& message = it->second;
00599
00600 if (filter(id))
00601 {
00602 addMessageToTable(message, id);
00603 }
00604 }
00605
00606 validateOrderedMessages();
00607
00608 table_->SetItemCount(ordered_messages_.size());
00609
00610 table_->postItemChanges();
00611 }
00612
00613 void RosoutPanel::popMessage()
00614 {
00615 M_IdToMessage::iterator it = messages_.begin();
00616 if (!ordered_messages_.empty() && ordered_messages_.front() == it->first)
00617 {
00618
00619 ordered_messages_.erase(ordered_messages_.begin());
00620 table_->SetItemCount(ordered_messages_.size());
00621
00622
00623 const S_int32& selection = table_->getSelection();
00624 S_int32 new_selection;
00625
00626 S_int32::const_iterator it = selection.begin();
00627 S_int32::const_iterator end = selection.end();
00628 for (; it != end; ++it)
00629 {
00630 int32_t new_index = *it - 1;
00631 if (new_index >= 0)
00632 {
00633 new_selection.insert(new_index);
00634 }
00635 }
00636
00637 table_->setSelection(new_selection);
00638 }
00639
00640 messages_.erase(it);
00641 }
00642
00643 void RosoutPanel::processMessage(const rosgraph_msgs::Log::ConstPtr& message)
00644 {
00645 uint32_t id = message_id_counter_++;
00646
00647 messages_.insert(std::make_pair(id, message));
00648
00649 if (filter(id))
00650 {
00651 addMessageToTable(message, id);
00652 }
00653
00654 validateOrderedMessages();
00655
00656 if (messages_.size() > max_messages_)
00657 {
00658 popMessage();
00659 }
00660 }
00661
00662 void RosoutPanel::processMessages()
00663 {
00664 if (message_queue_.empty())
00665 {
00666 return;
00667 }
00668
00669 table_->preItemChanges();
00670
00671 V_Log::iterator it = message_queue_.begin();
00672 V_Log::iterator end = message_queue_.end();
00673 for (; it != end; ++it)
00674 {
00675 rosgraph_msgs::Log::ConstPtr& message = *it;
00676
00677 processMessage(message);
00678 }
00679
00680 message_queue_.clear();
00681
00682 table_->SetItemCount(ordered_messages_.size());
00683
00684 table_->postItemChanges();
00685 }
00686
00687 void RosoutPanel::incomingMessage(const rosgraph_msgs::Log::ConstPtr& msg)
00688 {
00689 if (!pause_)
00690 {
00691 message_queue_.push_back(msg);
00692 }
00693 }
00694
00695 void RosoutPanel::onPause(wxCommandEvent& evt)
00696 {
00697 pause_ = evt.IsChecked();
00698 }
00699
00700 void RosoutPanel::onSetup(wxCommandEvent& evt)
00701 {
00702 RosoutSetupDialog dialog(this, topic_, max_messages_);
00703
00704 if (dialog.ShowModal() == wxOK)
00705 {
00706 setTopic(dialog.getTopic());
00707 setBufferSize(dialog.getBufferSize());
00708 }
00709 }
00710
00711 void RosoutPanel::setBufferSize(uint32_t size)
00712 {
00713 max_messages_ = size;
00714 while (messages_.size() >= max_messages_)
00715 {
00716 popMessage();
00717 }
00718 }
00719
00720 RosoutMessageSummary RosoutPanel::getMessageSummary(double duration) const
00721 {
00722 RosoutMessageSummary summary;
00723 ros::Time search_end(0);
00724
00725 if (ros::Time::now().toSec() - duration > 0)
00726 {
00727 search_end = ros::Time::now() - ros::Duration(duration);
00728 }
00729
00730 M_IdToMessage::const_reverse_iterator it = messages_.rbegin();
00731 M_IdToMessage::const_reverse_iterator end = messages_.rend();
00732 for (; it != end; ++it)
00733 {
00734 const rosgraph_msgs::Log::ConstPtr& msg = it->second;
00735
00736 if (msg->header.stamp < search_end)
00737 {
00738 break;
00739 }
00740
00741 switch (msg->level)
00742 {
00743 case rosgraph_msgs::Log::DEBUG:
00744 ++summary.debug;
00745 break;
00746 case rosgraph_msgs::Log::INFO:
00747 ++summary.info;
00748 break;
00749 case rosgraph_msgs::Log::WARN:
00750 ++summary.warn;
00751 break;
00752 case rosgraph_msgs::Log::ERROR:
00753 ++summary.error;
00754 break;
00755 case rosgraph_msgs::Log::FATAL:
00756 ++summary.fatal;
00757 break;
00758 }
00759 }
00760
00761 return summary;
00762 }
00763
00764 void RosoutPanel::checkForMaster()
00765 {
00766 while (!shutdown_thread_)
00767 {
00768 if (ros::master::check())
00769 {
00770 if (!connected_)
00771 {
00772 connected_ = true;
00773 ROS_INFO("Reconnected to ROS master");
00774 wxCommandEvent event(RECONNECTED_TO_MASTER_EVENT_);
00775 wxPostEvent(this, event);
00776 }
00777 }
00778 else if (connected_)
00779 {
00780 connected_ = false;
00781 ROS_INFO("Disconnected from ROS master");
00782 wxCommandEvent event(DISCONNECTED_FROM_MASTER_EVENT_);
00783 wxPostEvent(this, event);
00784 }
00785 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
00786 }
00787 }
00788
00789 void RosoutPanel::onMasterReconnected(wxEvent& event)
00790 {
00791 Enable(1);
00792 nh_.setCallbackQueue(&callback_queue_);
00793 subscribe();
00794 }
00795
00796 void RosoutPanel::onMasterDisconnected(wxEvent& event)
00797 {
00798 Enable(0);
00799 nh_.shutdown();
00800 }
00801
00802 }