00001
00010 #include "UrgRecorderWidget.h"
00011 #include "SerialConnectionWidget.h"
00012 #include "EthernetConnectionWidget.h"
00013 #include "RecordConnection.h"
00014 #include "UrgDevice.h"
00015 #include "UrgUsbCom.h"
00016 #include "FindComPorts.h"
00017 #include "DetectOS.h"
00018 #include "TcpipSocket.h"
00019 #include <QTimer>
00020 #include <QDateTime>
00021 #include <QDir>
00022 #include <QTextStream>
00023 #include <QMessageBox>
00024 #include <QShortcut>
00025 #include <QSettings>
00026
00027 using namespace qrk;
00028 using namespace std;
00029
00030 #if defined(MSC)
00031 #define snprintf _snprintf
00032 #endif
00033
00034
00035 namespace
00036 {
00037 const char* Organization = "Hokuyo LTD.";
00038 const char* Application = "URG Recorder";
00039 const char* UrgDefaultAddress = "192.168.0.10";
00040
00041 enum {
00042 UrgDefaultPort = 10940,
00043 DefaultCaptureTimes = 10,
00044 };
00045 }
00046
00047
00048 struct UrgRecorderWidget::pImpl
00049 {
00050 UrgRecorderWidget* widget_;
00051 SerialConnectionWidget serial_connection_widget_;
00052 EthernetConnectionWidget ethernet_connection_widget_;
00053
00054 UrgUsbCom urg_usb_;
00055 FindComPorts urg_finder_;
00056 UrgDevice urg_;
00057 Connection* serial_connection_;
00058 TcpipSocket ethernet_connection_;
00059
00060 QTimer capture_timer_;
00061 QString save_directory_;
00062 size_t capture_max_;
00063 size_t total_times_;
00064 bool is_raw_record_;
00065
00066 bool intensity_mode_;
00067 bool is_using_serial_;
00068
00069
00070 pImpl(UrgRecorderWidget* widget)
00071 : widget_(widget), serial_connection_(NULL),
00072 capture_max_(1), total_times_(0), is_raw_record_(false),
00073 intensity_mode_(false), is_using_serial_(true)
00074 {
00075 urg_finder_.addBaseName("/dev/ttyACM");
00076 urg_finder_.addBaseName("/dev/tty.usbmodem");
00077 urg_finder_.addDriverName("URG Series USB Device Driver");
00078 urg_finder_.addDriverName("URG-X002 USB Device Driver");
00079
00080 ethernet_connection_widget_.setPort(UrgDefaultPort);
00081 }
00082
00083
00084 void initializeForm(void)
00085 {
00086
00087 loadSettings();
00088
00089
00090 widget_->connection_layout_->addWidget(&serial_connection_widget_);
00091 widget_->connection_layout_->addWidget(ðernet_connection_widget_);
00092 widget_->connection_dummy_label_->hide();
00093
00094
00095 connect(&serial_connection_widget_, SIGNAL(rescanRequest()),
00096 widget_, SLOT(rescanPressed()));
00097 connect(&serial_connection_widget_,
00098 SIGNAL(connectRequest(bool, const std::string&)),
00099 widget_, SLOT(connectPressed(bool, const std::string&)));
00100
00101 connect(ðernet_connection_widget_,
00102 SIGNAL(connectRequest(bool, const std::string&,
00103 unsigned short)),
00104 widget_, SLOT(connectPressed(bool, const std::string&,
00105 unsigned short)));
00106
00107 connect(widget_->times_spinbox_, SIGNAL(valueChanged(int)),
00108 widget_, SLOT(timesChanged(int)));
00109
00110 connect(widget_->record_button_, SIGNAL(clicked()),
00111 widget_, SLOT(recordPressed()));
00112 connect(widget_->cancel_button_, SIGNAL(clicked()),
00113 widget_, SLOT(cancelPressed()));
00114
00115 connect(widget_->raw_button_, SIGNAL(toggled(bool)),
00116 widget_, SLOT(rawButtonChanged(bool)));
00117
00118 connect(&capture_timer_, SIGNAL(timeout()),
00119 widget_, SLOT(recordData()));
00120
00121 connect(widget_->change_button_, SIGNAL(clicked()),
00122 widget_, SLOT(changeButtonPressed()));
00123 }
00124
00125
00126 void loadSettings(void)
00127 {
00128 QSettings settings(Organization, Application);
00129 widget_->restoreGeometry(settings.value("geometry").toByteArray());
00130 int capture_times =
00131 settings.value("capture_times", DefaultCaptureTimes).toInt();
00132 widget_->times_spinbox_->setValue(capture_times);
00133 widget_->times_progress_->setMaximum(capture_times);
00134
00135 is_raw_record_ = settings.value("raw_button_checked", false).toBool();
00136 widget_->raw_button_->setChecked(is_raw_record_);
00137 rawButtonChanged(is_raw_record_);
00138
00139 is_using_serial_ = settings.value("serial_connection", true).toBool();
00140 if (is_using_serial_) {
00141 selectSerial();
00142 } else {
00143 selectEthernet();
00144 }
00145
00146 string address =
00147 settings.value("address",
00148 UrgDefaultAddress).toString().toStdString();
00149 ethernet_connection_widget_.setAddress(address);
00150 unsigned short port = settings.value("port", UrgDefaultPort).toInt();
00151 ethernet_connection_widget_.setPort(port);
00152 }
00153
00154
00155 void saveSettings(void)
00156 {
00157 QSettings settings(Organization, Application);
00158 settings.setValue("geometry", widget_->saveGeometry());
00159 settings.setValue("capture_times", widget_->times_spinbox_->value());
00160 settings.setValue("raw_button_checked",
00161 widget_->raw_button_->isChecked());
00162
00163 settings.setValue("serial_connection", is_using_serial_);
00164 settings.setValue("address",
00165 ethernet_connection_widget_.address().c_str());
00166 settings.setValue("port", ethernet_connection_widget_.port());
00167 }
00168
00169
00170 void setRecording(bool recording)
00171 {
00172 widget_->record_button_->setEnabled(! recording);
00173 widget_->cancel_button_->setEnabled(recording);
00174 widget_->output_group_->setEnabled(! recording);
00175 widget_->times_group_->setEnabled(! recording);
00176 }
00177
00178
00179 void recordPressed(void)
00180 {
00181 setRecording(true);
00182
00183
00184 save_directory_ =
00185 QDateTime::currentDateTime().toString("yyyy-MM-dd_hh_mm_ss");
00186 QDir dir;
00187 dir.mkdir(save_directory_);
00188
00189
00190 is_raw_record_ = widget_->raw_button_->isChecked();
00191 if (is_raw_record_) {
00192 is_raw_record_ = true;
00193 serial_connection_ = urg_.connection();
00194 string send_file = save_directory_.toStdString() + "/send.txt";
00195 string receive_file =
00196 save_directory_.toStdString() + "/receive.txt";
00197 urg_.setConnection(new RecordConnection(serial_connection_,
00198 send_file.c_str(),
00199 receive_file.c_str()));
00200
00201
00202 urg_.loadParameter();
00203 }
00204
00205
00206 capture_max_ = widget_->times_spinbox_->value();
00207 total_times_ = 0;
00208 if (intensity_mode_) {
00209 urg_.setCaptureMode(IntensityCapture);
00210 } else {
00211 urg_.setCaptureMode(AutoCapture);
00212 }
00213 capture_timer_.setInterval(urg_.scanMsec() / 2);
00214 capture_timer_.start();
00215 }
00216
00217
00218 void recordData(void)
00219 {
00220 vector<long> data;
00221 vector<long> intensity_data;
00222
00223 int n;
00224 if (intensity_mode_) {
00225 n = urg_.captureWithIntensity(data, intensity_data);
00226 } else {
00227 n = urg_.capture(data);
00228 }
00229
00230 if (n <= 0) {
00231 return;
00232 }
00233 ++total_times_;
00234
00235 if (! is_raw_record_) {
00236
00237
00238 char buffer[] = "/data_xxxxxxxxxx.csv";
00239 snprintf(buffer, sizeof(buffer), "/data_%09d.csv", total_times_);
00240 QFile file(save_directory_ + QString(buffer));
00241 if (! file.open(QIODevice::WriteOnly)) {
00242
00243 return;
00244 }
00245
00246 QTextStream fout(&file);
00247 saveFile(fout, data, intensity_data);
00248 }
00249
00250 widget_->times_progress_->setValue(total_times_);
00251 if (total_times_ >= capture_max_) {
00252 stopRecording();
00253 }
00254 }
00255
00256
00257 void stopRecording(void)
00258 {
00259 setRecording(false);
00260 capture_timer_.stop();
00261 widget_->times_progress_->setValue(0);
00262
00263 urg_.stop();
00264
00265 if (is_raw_record_) {
00266 Connection* connection = urg_.connection();
00267 if (connection != serial_connection_) {
00268 delete connection;
00269 urg_.setConnection(serial_connection_);
00270 }
00271 }
00272 }
00273
00274
00275 void saveFile(QTextStream& fout, const vector<long>& data,
00276 vector<long>& intensity_data)
00277 {
00278 size_t n = data.size();
00279 for (size_t i = 0; i < n; ++i) {
00280 long length = data[i];
00281 double radian = urg_.index2rad(i);
00282 double x = length * cos(radian);
00283 double y = length * sin(radian);
00284 fout << i << ',' << length << ','
00285 << radian << ',' << x << ',' << y;
00286
00287 if (intensity_mode_) {
00288 fout << ',' << intensity_data[i];
00289 }
00290
00291 fout << endl;
00292 }
00293 }
00294
00295
00296 void rawButtonChanged(bool checked)
00297 {
00298 if (checked) {
00299 widget_->sample_text_->clear();
00300 widget_->sample_text_->
00301 insertPlainText("# receive data sample\n"
00302 "MD0044072501000\n"
00303 "99b\n"
00304 "...");
00305 } else {
00306 widget_->sample_text_->clear();
00307 widget_->sample_text_->
00308 insertPlainText("# index, length, radian, x, y\n"
00309 "0,669,-2.08621,-329.749,-582.088\n"
00310 "1,667,-2.08008,-325.196,-582.354\n"
00311 "...");
00312 }
00313 }
00314
00315
00316 void selectSerial(void)
00317 {
00318 widget_->change_button_->setText(tr("Change to Ethernet"));
00319 ethernet_connection_widget_.hide();
00320 serial_connection_widget_.show();
00321
00322 if (serial_connection_) {
00323 urg_.setConnection(serial_connection_);
00324 }
00325
00326 is_using_serial_ = true;
00327 }
00328
00329
00330 void selectEthernet(void)
00331 {
00332 widget_->change_button_->setText(tr("Change to Serial"));
00333 serial_connection_widget_.hide();
00334 ethernet_connection_widget_.show();
00335
00336 urg_.setConnection(ðernet_connection_);
00337
00338 is_using_serial_ = false;
00339 }
00340
00341
00342 void set_enables(bool connected)
00343 {
00344 widget_->record_group_->setEnabled(connected);
00345 widget_->cancel_button_->setEnabled(false);
00346
00347 serial_connection_widget_.setConnected(connected);
00348 ethernet_connection_widget_.setConnected(connected);
00349
00350 if (connected) {
00351
00352 widget_->record_button_->setFocus();
00353 }
00354 }
00355 };
00356
00357
00358 UrgRecorderWidget::UrgRecorderWidget(QWidget* parent)
00359 : QWidget(parent), pimpl(new pImpl(this))
00360 {
00361 setupUi(this);
00362
00363
00364 pimpl->initializeForm();
00365 rescanPressed();
00366
00367 pimpl->serial_connection_widget_.setFocus();
00368
00369
00370 (void) new QShortcut(Qt::CTRL + Qt::Key_Q, this, SLOT(close()));
00371 (void) new QShortcut(Qt::ALT + Qt::Key_F4, this, SLOT(close()));
00372 }
00373
00374
00375 UrgRecorderWidget::~UrgRecorderWidget(void)
00376 {
00377 }
00378
00379
00380 void UrgRecorderWidget::setIntensityMode(void)
00381 {
00382 if (! pimpl->intensity_mode_) {
00383 pimpl->intensity_mode_ = true;
00384 if (pimpl->intensity_mode_) {
00385 setWindowTitle(windowTitle() + " " + tr("[intensity]"));
00386 }
00387 }
00388 }
00389
00390
00391 void UrgRecorderWidget::closeEvent(QCloseEvent* event)
00392 {
00393 static_cast<void>(event);
00394
00395 pimpl->urg_.stop();
00396 pimpl->saveSettings();
00397 }
00398
00399
00400 void UrgRecorderWidget::rescanPressed(void)
00401 {
00402 vector<string> devices;
00403 pimpl->urg_finder_.find(devices);
00404 for (vector<string>::iterator it = devices.begin();
00405 it != devices.end(); ++it) {
00406 if (pimpl->urg_usb_.isUsbCom(it->c_str())) {
00407 *it = *it + " [URG]";
00408 }
00409 }
00410 pimpl->serial_connection_widget_.setDevices(devices);
00411 }
00412
00413
00414 void UrgRecorderWidget::connectPressed(bool connection,
00415 const string& device)
00416 {
00417
00418 bool connected = connection;
00419
00420 if (connection) {
00421 if (! pimpl->urg_.connect(device.c_str())) {
00422 QMessageBox::warning(this, tr("Connection error"),
00423 pimpl->urg_.what());
00424 connected = false;
00425 }
00426 } else {
00427 pimpl->stopRecording();
00428 }
00429
00430 pimpl->set_enables(connected);
00431 }
00432
00433
00434 void UrgRecorderWidget::connectPressed(bool connection,
00435 const std::string& address,
00436 unsigned short port)
00437 {
00438
00439 bool connected = connection;
00440
00441 fprintf(stderr, "%p, %p\n", &pimpl->ethernet_connection_, pimpl->urg_.connection());
00442 if (connection) {
00443 if (! pimpl->urg_.connect(address.c_str(), port)) {
00444 QMessageBox::warning(this, tr("Connection error"),
00445 pimpl->urg_.what());
00446 connected = false;
00447 }
00448 } else {
00449 pimpl->stopRecording();
00450 }
00451
00452 pimpl->set_enables(connected);
00453 }
00454
00455
00456 void UrgRecorderWidget::recordPressed(void)
00457 {
00458 if (pimpl->capture_timer_.isActive()) {
00459 return;
00460 }
00461 pimpl->recordPressed();
00462 }
00463
00464
00465 void UrgRecorderWidget::cancelPressed(void)
00466 {
00467 pimpl->stopRecording();
00468 }
00469
00470
00471 void UrgRecorderWidget::timesChanged(int times)
00472 {
00473 times_progress_->setMaximum(times);
00474
00475
00476 times_progress_->setValue(1);
00477 times_progress_->setValue(0);
00478 }
00479
00480
00481 void UrgRecorderWidget::recordData(void)
00482 {
00483 pimpl->recordData();
00484 }
00485
00486
00487 void UrgRecorderWidget::rawButtonChanged(bool checked)
00488 {
00489 pimpl->rawButtonChanged(checked);
00490 }
00491
00492
00493 void UrgRecorderWidget::changeButtonPressed(void)
00494 {
00495 if (pimpl->is_using_serial_) {
00496 pimpl->selectEthernet();
00497 } else {
00498 pimpl->selectSerial();
00499 }
00500 }