00001
00010 #include <QShortcut>
00011 #include <QTimer>
00012 #include <QSettings>
00013 #include <QFileDialog>
00014 #include <QWheelEvent>
00015 #include <cmath>
00016 #include "UrgScannerWindow.h"
00017 #include "UrgDataDraw.h"
00018 #include "WiiJoystick.h"
00019 #include "FindComPorts.h"
00020 #include "UrgUsbCom.h"
00021 #include "UrgDevice.h"
00022 #include "ConvertStdStringPath.h"
00023
00024 using namespace qrk;
00025 using namespace std;
00026
00027
00028 struct UrgScannerWindow::pImpl
00029 {
00030 WiiJoystick wii_;
00031 UrgDevice urg_;
00032 long* urg_data_;
00033 size_t urg_data_max_;
00034 UrgDataDraw* data_draw_widget_;
00035 QTimer* redraw_timer_;
00036 bool save_ok_;
00037 UrgUsbCom urg_usb_;
00038 FindComPorts urg_finder_;
00039
00040
00041 pImpl(UrgScannerWindow* parent)
00042 : urg_data_(NULL), urg_data_max_(1),
00043 data_draw_widget_(new UrgDataDraw(parent)),
00044 redraw_timer_(new QTimer(parent)), save_ok_(false)
00045 {
00046 urg_finder_.addBaseName("/dev/ttyACM");
00047 urg_finder_.addBaseName("/dev/tty.usbmodem");
00048
00049 urg_finder_.addDriverName("URG Series USB Device Driver");
00050 urg_finder_.addDriverName("URG-X002 USB Device Driver");
00051 }
00052
00053
00054 void loadSettings(UrgScannerWindow* parent)
00055 {
00056 QSettings settings("Hokuyo LTD.", "URG Scanner");
00057
00058 #ifdef WINDOWS_OS
00059
00060 parent->com_combobox_->
00061 setCurrentIndex(settings.value("port_index", 0).toInt());
00062 #endif
00063
00064
00065 bool h_type = settings.value("h_type", false).toBool();
00066 parent->mirror_checkbox_->setChecked(h_type);
00067 data_draw_widget_->setTypeH(h_type);
00068
00069
00070 bool front_only = settings.value("front_only", false).toBool();
00071 parent->front_only_checkbox_->setChecked(front_only);
00072 data_draw_widget_->setFrontOnly(front_only);
00073
00074
00075 bool hs_mode = settings.value("hs_mode", false).toBool();
00076 parent->hs_mode_checkbox_->setChecked(hs_mode);
00077
00078
00079 bool intensity_mode = settings.value("intensity_mode", false).toBool();
00080 parent->intensity_checkbox_->setChecked(intensity_mode);
00081 }
00082
00083
00084 void saveSettings(UrgScannerWindow* parent) {
00085
00086 QSettings settings("Hokuyo LTD.", "URG Scanner");
00087
00088 #ifdef WINDOWS_OS
00089 settings.setValue("port_index",
00090 parent->com_combobox_->currentIndex());
00091 #endif
00092 settings.setValue("h_type", parent->mirror_checkbox_->checkState());
00093 settings.setValue("front_only", parent->front_only_checkbox_->checkState());
00094 settings.setValue("hs_mode", parent->hs_mode_checkbox_->checkState());
00095 settings.setValue("intensity_mode",
00096 parent->intensity_checkbox_->checkState());
00097 }
00098
00099
00100 void initializeForm(UrgScannerWindow* parent)
00101 {
00102 parent->com_combobox_->clear();
00103 vector<string> devices;
00104 urg_finder_.find(devices);
00105 for (vector<string>::iterator it = devices.begin();
00106 it != devices.end(); ++it) {
00107 if (urg_usb_.isUsbCom(it->c_str())) {
00108 *it = *it + " [URG]";
00109 }
00110 parent->com_combobox_->addItem(it->c_str());
00111 }
00112
00113
00114 parent->verticalLayout_tools_->addWidget(data_draw_widget_);
00115
00116
00117 connect(parent->connect_button_, SIGNAL(clicked(bool)),
00118 parent, SLOT(connectHandler(bool)));
00119
00120
00121 connect(redraw_timer_, SIGNAL(timeout()), parent, SLOT(redrawHandler()));
00122
00123
00124 connect(parent->mirror_checkbox_, SIGNAL(clicked(bool)),
00125 data_draw_widget_, SLOT(setTypeH(bool)));
00126 data_draw_widget_->
00127 setTypeH((parent->mirror_checkbox_->checkState() != Qt::Checked)
00128 ? false : true);
00129
00130
00131 connect(parent->front_only_checkbox_, SIGNAL(clicked(bool)),
00132 data_draw_widget_, SLOT(setFrontOnly(bool)));
00133 data_draw_widget_->
00134 setFrontOnly((parent->front_only_checkbox_->checkState() != Qt::Checked)
00135 ? false : true);
00136
00137 parent->hs_mode_checkbox_->hide();
00138
00139
00140
00141 connect(parent->intensity_checkbox_, SIGNAL(clicked(bool)),
00142 parent, SLOT(meHandler(bool)));
00143
00144
00145 connect(parent->magnify_slidebar_, SIGNAL(valueChanged(int)),
00146 data_draw_widget_, SLOT(magnifyChanged(int)));
00147
00148
00149 data_draw_widget_->magnifyChanged(parent->magnify_slidebar_->value());
00150
00151
00152 (void) new QShortcut(Qt::Key_Return, data_draw_widget_, SLOT(resetView()));
00153
00154
00155 connect(parent->load_button_, SIGNAL(clicked()),
00156 parent, SLOT(loadVrml()));
00157 connect(parent->save_button_, SIGNAL(clicked()),
00158 parent, SLOT(saveVrml()));
00159 }
00160
00161 void clearForm(UrgScannerWindow* parent) {
00162 static_cast<void>(parent);
00163
00164
00165
00166
00167
00168 data_draw_widget_->clearCaptureData();
00169 }
00170
00171
00172 void getWiiRotate(Point3d<int>& wii_rotate)
00173 {
00174 if (wii_.isConnected()) {
00175
00176
00177 Point3d<double> acc;
00178 wii_.acceleration(acc);
00179
00180
00181 double length = sqrt((acc.x * acc.x) + (acc.z * acc.z));
00182 double x_rad = atan2(-acc.y, length);
00183 double z_rad = atan2(acc.z, acc.x);
00184
00185 wii_rotate.x = -static_cast<int>(180 * z_rad / M_PI) + 90;
00186 wii_rotate.y = -static_cast<int>(180 * x_rad / M_PI);
00187 wii_rotate.z = 0;
00188
00189 } else {
00190 wii_rotate.x = 0;
00191 }
00192 }
00193 };
00194
00195
00196 UrgScannerWindow::UrgScannerWindow(void) : pimpl(new pImpl(this))
00197 {
00198 setupUi(this);
00199
00200 pimpl->initializeForm(this);
00201 pimpl->clearForm(this);
00202
00203 pimpl->loadSettings(this);
00204
00205
00206 (void) new QShortcut(Qt::CTRL + Qt::Key_Q, this, SLOT(close()));
00207 }
00208
00209
00210 UrgScannerWindow::~UrgScannerWindow(void)
00211 {
00212 pimpl->saveSettings(this);
00213 }
00214
00215
00216 void UrgScannerWindow::connectHandler(bool checked)
00217 {
00218
00219
00220 if (checked) {
00221 if (! pimpl->wii_.connect()) {
00222
00223 fprintf(stderr, "WiiJoystick::connect: %s\n", pimpl->wii_.what());
00224
00225
00226
00227 }
00228 enum { MovingAverageSize = 12 };
00229 pimpl->wii_.setAccelerationAverageSize(MovingAverageSize);
00230
00231
00232 if (com_combobox_->count() == 0) {
00233 return;
00234 }
00235 string device_name = com_combobox_->currentText().toStdString();
00236 string device = device_name.substr(0, device_name.find(' '));
00237
00238 if (! pimpl->urg_.connect(device.c_str(), 115200)) {
00239
00240 fprintf(stderr, "UrgDevice::connect: %s\n", pimpl->urg_.what());
00241 return;
00242 }
00243 pimpl->urg_.setCaptureMode(AutoCapture);
00244
00245
00246 bool me_on = intensity_checkbox_->isChecked() ? true : false;
00247 if (! meHandler(me_on)) {
00248
00249 intensity_checkbox_->setEnabled(false);
00250 }
00251
00252
00253 connect_button_->setText(tr("Disconnect"));
00254
00255 if (! pimpl->urg_data_) {
00256
00257 pimpl->urg_data_max_ = pimpl->urg_.maxScanLines();
00258 pimpl->urg_data_ = new long[pimpl->urg_data_max_];
00259
00260 }
00261
00262
00263 size_t scan_msec = pimpl->urg_.scanMsec();
00264 pimpl->redraw_timer_->start(scan_msec);
00265
00266 } else {
00267
00268 connect_button_->setText(tr("Connect"));
00269 pimpl->redraw_timer_->stop();
00270
00271 if (pimpl->wii_.isConnected()) {
00272 pimpl->wii_.disconnect();
00273 }
00274 pimpl->urg_.disconnect();
00275 intensity_checkbox_->setEnabled(true);
00276
00277 pimpl->clearForm(this);
00278 }
00279 }
00280
00281
00282
00283 void UrgScannerWindow::redrawHandler(void)
00284 {
00285
00286 Point3d<int> wii_rotate;
00287 pimpl->getWiiRotate(wii_rotate);
00288
00289
00290 bool record = pimpl->wii_.isButtonPressed(WiiJoystick::BUTTON_B);
00291 if (record && (! pimpl->save_ok_)) {
00292 pimpl->save_ok_ = true;
00293 save_button_->setEnabled(true);
00294 }
00295
00296
00297 bool no_plot =
00298 pimpl->wii_.isButtonPressed(WiiJoystick::BUTTON_1) ||
00299 pimpl->wii_.isButtonPressed(WiiJoystick::BUTTON_2);
00300
00301
00302 pimpl->data_draw_widget_->redraw(pimpl->urg_, wii_rotate, record, no_plot);
00303 }
00304
00305
00306
00307 bool UrgScannerWindow::meHandler(bool checked)
00308 {
00309 if (! pimpl->urg_.isConnected()) {
00310
00311 return true;
00312 }
00313
00314
00315 pimpl->redraw_timer_->stop();
00316 RangeCaptureMode mode = checked ? IntensityCapture : AutoCapture;
00317 pimpl->urg_.setCaptureMode(mode);
00318 pimpl->data_draw_widget_->setIntensityMode(checked);
00319 pimpl->redraw_timer_->start();
00320
00321 return true;
00322 }
00323
00324
00325 void UrgScannerWindow::loadVrml(void)
00326 {
00327 QString fileName =
00328 QFileDialog::getOpenFileName(this, tr("Open VRML file."), ".",
00329 tr("VRML file (*.wrl)"));
00330
00331 if (! fileName.isEmpty()) {
00332
00333 string std_path = qrk::toStdStringPath(fileName);
00334
00335 pimpl->data_draw_widget_->loadVrml(std_path);
00336 }
00337 }
00338
00339
00340 void UrgScannerWindow::saveVrml(void)
00341 {
00342
00343
00344 QString fileName =
00345 QFileDialog::getSaveFileName(this, tr("Save VRML file."), ".",
00346 tr("VRML file (*.wrl)"));
00347
00348 if (! fileName.isEmpty()) {
00349
00350 string std_path = qrk::toStdStringPath(fileName);
00351
00352 pimpl->data_draw_widget_->saveVrml(std_path);
00353 }
00354 }
00355
00356
00357
00358 void UrgScannerWindow::wheelEvent(QWheelEvent* event)
00359 {
00360 int degrees = event->delta() / 8;
00361 int steps = degrees / 15;
00362
00363 int add_value = ((steps > 0) ? +1 : -1) * magnify_slidebar_->singleStep();
00364 magnify_slidebar_->setValue(magnify_slidebar_->value() + add_value);
00365
00366 event->accept();
00367 }