All Classes Namespaces Files Functions Variables Enumerations Enumerator
programs/MultiUrgViewer/UrgStateWidget.cpp
Go to the documentation of this file.
00001 
00010 #include "UrgStateWidget.h"
00011 #include "MultiUrgViewerWidget.h"
00012 #include "SerialConnectionWidget.h"
00013 #include "DropRateWidget.h"
00014 #include "DrawWidget.h"
00015 #include "UrgDevice.h"
00016 #include "UrgUtils.h"
00017 #include "MovingAverage.h"
00018 #include "ticks.h"
00019 #include <QTimer>
00020 
00021 using namespace qrk;
00022 using namespace std;
00023 
00024 
00025 namespace
00026 {
00027   enum {
00028     AverageTimes = 40,
00029   };
00030 }
00031 
00032 
00033 struct UrgStateWidget::pImpl
00034 {
00035   MultiUrgViewerWidget* parent_;
00036   UrgStateWidget* widget_;
00037   SerialConnectionWidget connection_widget_;
00038   DropRateWidget drop_rate_widget_;
00039   DrawWidget* draw_widget_;
00040 
00041   UrgDevice urg_;
00042   string device_;
00043   long serial_id_;
00044   QTimer capture_timer_;
00045   int scan_msec_;
00046   long prev_timestamp_;
00047 
00048   MovingAverage<int> capture_times_;
00049 
00050 
00051   pImpl(MultiUrgViewerWidget* parent, UrgStateWidget* widget)
00052     : parent_(parent), widget_(widget), draw_widget_(NULL),
00053       serial_id_(0), prev_timestamp_(0), capture_times_(AverageTimes)
00054   {
00055     capture_times_.setAverageValue(100);
00056   }
00057 
00058 
00059   void initializeForm(void)
00060   {
00061     // Widget の配置
00062     widget_->connection_layout_->addWidget(&connection_widget_);
00063     widget_->drop_rate_layout_->addWidget(&drop_rate_widget_);
00064     widget_->connection_dummy_label_->hide();
00065     widget_->drop_rate_dummy_label_->hide();
00066 
00067     // イベントの接続
00068     connect(&connection_widget_, SIGNAL(rescanRequest()),
00069             parent_, SLOT(rescanDevices()));
00070     connect(&connection_widget_,
00071             SIGNAL(connectRequest(bool, const std::string&)),
00072             widget_, SLOT(connectDevice(bool, const std::string&)));
00073     connect(widget_, SIGNAL(deleteUrgState(UrgStateWidget*)),
00074             parent_, SLOT(deleteUrgState(UrgStateWidget*)));
00075 
00076     connect(&capture_timer_, SIGNAL(timeout()),
00077             widget_, SLOT(captureHandler()));
00078 
00079     connect(widget_->view_button_, SIGNAL(clicked()),
00080             widget_, SLOT(setViewer()));
00081 
00082     setEnabled(false);
00083   }
00084 
00085 
00086   void setEnabled(bool enable)
00087   {
00088     widget_->view_button_->setEnabled(enable);
00089     drop_rate_widget_.setEnabled(enable);
00090   }
00091 
00092 
00093   void connectDevice(const string& device)
00094   {
00095     // 接続時
00096     bool ret = urg_.connect(device.c_str());
00097     connection_widget_.setConnected(ret);
00098     if (! ret) {
00099       return;
00100     }
00101 
00102     device_ = device;
00103     parent_->addUrgState();
00104     parent_->rescanDevices();
00105 
00106     // シリアル ID の登録
00107     serial_id_ = urgSerialId<UrgDevice>(&urg_);
00108     QString title = serialId();
00109 
00110     widget_->groupbox_->setTitle(title);
00111     setEnabled(true);
00112 
00113     urg_.setCaptureMode(AutoCapture);
00114     prev_timestamp_ = ticks();
00115     urg_.setTimestamp(prev_timestamp_);
00116     scan_msec_ = urg_.scanMsec();
00117 
00118     // データの取得開始
00119     capture_timer_.setInterval(scan_msec_ / 2);
00120     capture_timer_.start();
00121   }
00122 
00123 
00124   QString serialId(void)
00125   {
00126     return QString("Serial ID : %1").arg(serial_id_);
00127   }
00128 
00129 
00130   void captureHandler(void)
00131   {
00132     vector<long> data;
00133     long timestamp = 0;
00134     int n = urg_.capture(data, &timestamp);
00135     if (n > 0) {
00136       int drop_times =
00137         static_cast<int>((3.0 + timestamp - prev_timestamp_) / scan_msec_) - 1;
00138 
00139       capture_times_.push_back(100);
00140       for (int i = 0; i < drop_times; ++i) {
00141         capture_times_.push_back(0);
00142       }
00143       prev_timestamp_ = timestamp;
00144 
00145       int average = capture_times_.average();
00146       drop_rate_widget_.setDropRate(average);
00147 
00148       // 描画データの表示
00149       if (draw_widget_) {
00150         draw_widget_->setUrgData(data, &urg_, timestamp, widget_);
00151       }
00152     }
00153   }
00154 };
00155 
00156 
00157 UrgStateWidget::UrgStateWidget(MultiUrgViewerWidget* parent)
00158   : QWidget(parent), pimpl(new pImpl(parent, this))
00159 {
00160   setupUi(this);
00161   pimpl->initializeForm();
00162 }
00163 
00164 
00165 UrgStateWidget::~UrgStateWidget(void)
00166 {
00167 }
00168 
00169 
00170 void UrgStateWidget::connectDevice(bool connection, const string& device)
00171 {
00172   if (connection) {
00173     // 接続時
00174     pimpl->connectDevice(device);
00175   } else {
00176     // 切断時
00177     emit deleteUrgState(this);
00178   }
00179 }
00180 
00181 
00182 void UrgStateWidget::captureHandler(void)
00183 {
00184   pimpl->captureHandler();
00185 }
00186 
00187 
00188 void UrgStateWidget::setViewer(void)
00189 {
00190   DrawWidget* draw_widget = pimpl->parent_->drawWidget();
00191   pimpl->draw_widget_ = draw_widget;
00192   draw_widget->show();
00193   draw_widget->setTitle(pimpl->serialId(), this);
00194 }
00195 
00196 
00197 void UrgStateWidget::setDevices(const vector<string>& devices)
00198 {
00199   pimpl->connection_widget_.setDevices(devices);
00200 }
00201 
00202 
00203 string UrgStateWidget::device(void) const
00204 {
00205   return pimpl->device_;
00206 }
00207 
00208 
00209 bool UrgStateWidget::isConnected(void) const
00210 {
00211   return pimpl->urg_.isConnected();
00212 }