All Classes Namespaces Files Functions Variables Enumerations Enumerator
libs/range_sensor/UrgDevice.cpp
Go to the documentation of this file.
00001 
00012 #include "UrgDevice.h"
00013 #include "SerialDevice.h"
00014 #include "ScipHandler.h"
00015 #include "RangeSensorParameter.h"
00016 #include "ticks.h"
00017 #include "Thread.h"
00018 #include "LockGuard.h"
00019 #include "Lock.h"
00020 #include <deque>
00021 #include <limits>
00022 #include <cstring>
00023 #include <cstdio>
00024 
00025 #ifdef MSC
00026 #define snprintf _snprintf
00027 #endif
00028 
00029 using namespace qrk;
00030 using namespace std;
00031 
00032 
00033 namespace
00034 {
00035   enum {
00036     MdScansMax = 100,           // [times]
00037   };
00038 }
00039 
00040 
00041 struct UrgDevice::pImpl
00042 {
00043   struct ScanData
00044   {
00045     vector<long> length_data;
00046     long timestamp;
00047     CaptureSettings settings;
00048 
00049     ScanData(void) : timestamp(-1)
00050     {
00051     }
00052   };
00053 
00054 
00055   class Capture
00056   {
00057   public:
00058     virtual ~Capture(void)
00059     {
00060     }
00061 
00062     virtual string createCaptureCommand(void) = 0;
00063     virtual int capture(vector<long>& data, long* timestamp) = 0;
00064     virtual void setCapturesSize(size_t size) = 0;
00065     virtual size_t capturesSize(void) = 0;
00066     virtual size_t remainCaptureTimes(void) = 0;
00067   };
00068 
00069 
00070   class RawManualCapture : public Capture
00071   {
00072     pImpl* pimpl_;
00073 
00074   public:
00075     RawManualCapture(pImpl* pimpl) : pimpl_(pimpl)
00076     {
00077     }
00078 
00079 
00080     ~RawManualCapture(void)
00081     {
00082     }
00083 
00084 
00085     string createCaptureCommand(void)
00086     {
00087       // !!! parameter 受信直後に、送受信パラメータへの代入を行う
00088       // !!! ここでの送受信には、送受信パラメータの内容を用いる
00089 
00090       char buffer[] = "GDbbbbeeeegg\n";
00091       snprintf(buffer, strlen(buffer) + 1, "GD%04d%04d%02u\n",
00092                pimpl_->capture_begin_, pimpl_->capture_end_,
00093                pimpl_->capture_skip_lines_);
00094 
00095       return buffer;
00096     }
00097 
00098 
00099     int capture(vector<long>& data, long* timestamp)
00100     {
00101       pimpl_->retry_times_ = 0;
00102 
00103       // レーザを点灯させておく
00104       pimpl_->scip_.setLaserOutput(ScipHandler::On);
00105 
00106       // データ取得コマンドの送信
00107       string command = createCaptureCommand();
00108       int n = pimpl_->scip_.send(command.c_str(),
00109                                  static_cast<int>(command.size()));
00110       if (n != static_cast<int>(command.size())) {
00111         pimpl_->error_message_ = "Send command:" + command + " fail.";
00112         return -1;
00113       }
00114 
00115       CaptureSettings settings;
00116       pimpl_->scip_.receiveCaptureData(data, settings, timestamp, NULL);
00117       return static_cast<int>(data.size());
00118     }
00119 
00120 
00121     void setCapturesSize(size_t size)
00122     {
00123       static_cast<void>(size);
00124 
00125       // 何もしない
00126     }
00127 
00128 
00129     size_t capturesSize(void)
00130     {
00131       return 1;
00132     }
00133 
00134 
00135     size_t remainCaptureTimes(void)
00136     {
00137       return 0;
00138     }
00139   };
00140 
00141 
00142   class RawAutoCapture : public Capture
00143   {
00144     pImpl* pimpl_;
00145     size_t captures_size_;
00146 
00147 
00148   public:
00149     RawAutoCapture(pImpl* pimpl) : pimpl_(pimpl), captures_size_(1)
00150     {
00151     }
00152 
00153 
00154     ~RawAutoCapture(void)
00155     {
00156     }
00157 
00158 
00159     string createCaptureCommand(void)
00160     {
00161       char buffer[] = "MDbbbbeeeeggstt\n";
00162       snprintf(buffer, strlen(buffer) + 1, "MD%04d%04d%02u%01u%02u\n",
00163                pimpl_->capture_begin_, pimpl_->capture_end_,
00164                pimpl_->capture_skip_lines_,
00165                pimpl_->capture_frame_interval_,
00166                (pimpl_->capture_times_ > 99) ? 0 : pimpl_->capture_times_);
00167 
00168       pimpl_->remain_times_ = pimpl_->capture_times_;
00169 
00170       return buffer;
00171     }
00172 
00173 
00174     int capture(vector<long>& data, long* timestamp)
00175     {
00176       if (pimpl_->retry_times_ > pimpl_->max_retry_times_) {
00177         return -1;
00178       }
00179 
00180       // スレッドを起動
00181       LockGuard guard(pimpl_->mutex_);
00182       if ((! pimpl_->thread_.isRunning()) && pimpl_->data_buffer_.empty()) {
00183         pimpl_->thread_.run(1);
00184       }
00185 
00186       // 取得済みデータがなければ、戻る
00187       if (pimpl_->data_buffer_.empty()) {
00188         if (pimpl_->invalid_packet_) {
00189           return -1;
00190         }
00191         return 0;
00192       }
00193 
00194       swap(data, pimpl_->data_buffer_.front().length_data);
00195       if (timestamp) {
00196         *timestamp = pimpl_->data_buffer_.front().timestamp;
00197         //fprintf(stderr, "MD: %ld, %ld\n", ticks(), *timestamp);
00198       }
00199       pimpl_->data_buffer_.pop_front();
00200 
00201       return static_cast<int>(data.size());
00202     }
00203 
00204 
00205     void setCapturesSize(size_t size)
00206     {
00207       captures_size_ = size;
00208     }
00209 
00210 
00211     size_t capturesSize(void)
00212     {
00213       return captures_size_;
00214     }
00215 
00216 
00217     size_t remainCaptureTimes(void)
00218     {
00219       if (pimpl_->capture_times_ == 0) {
00220         return numeric_limits<size_t>::max();
00221       }
00222 
00223       LockGuard guard(pimpl_->mutex_);
00224       return pimpl_->remain_times_;
00225     }
00226   };
00227 
00228 
00229   class RawIntensityCapture : public Capture
00230   {
00231     pImpl* pimpl_;
00232     size_t captures_size_;
00233 
00234 
00235   public:
00236     RawIntensityCapture(pImpl* pimpl) : pimpl_(pimpl), captures_size_(1)
00237     {
00238     }
00239 
00240 
00241     ~RawIntensityCapture(void)
00242     {
00243     }
00244 
00245 
00246     string createCaptureCommand(void)
00247     {
00248       char buffer[] = "MEbbbbeeeeggstt\n";
00249       if ((! pimpl_->urg_type_.compare("URG-04LX")) ||
00250           (! pimpl_->urg_type_.compare("URG-04LX-UG01")) ||
00251           (! pimpl_->urg_type_.compare("UBG-04LX-F01"))) {
00252           // URG-04LX ならば、FF 形式でデータ送信を行う
00253           snprintf(buffer, strlen(buffer) + 1, "MD%04d%04dFF%01u%02u\n",
00254                    pimpl_->capture_begin_, pimpl_->capture_end_,
00255                    pimpl_->capture_frame_interval_,
00256                    (pimpl_->capture_times_ > 99) ? 0 : pimpl_->capture_times_);
00257 
00258       } else {
00259           // UTM-30LX ならば、ME コマンドを用いる
00260           snprintf(buffer, strlen(buffer) + 1, "ME%04d%04d%02u%01u%02u\n",
00261                    pimpl_->capture_begin_, pimpl_->capture_end_,
00262                    pimpl_->capture_skip_lines_,
00263                    pimpl_->capture_frame_interval_,
00264                    (pimpl_->capture_times_ > 99) ? 0 : pimpl_->capture_times_);
00265       }
00266       pimpl_->remain_times_ = pimpl_->capture_times_;
00267 
00268       return buffer;
00269     }
00270 
00271 
00272     int capture(vector<long>& data, long* timestamp)
00273     {
00274       if (pimpl_->retry_times_ > pimpl_->max_retry_times_) {
00275         return -1;
00276       }
00277 
00278       LockGuard guard(pimpl_->mutex_);
00279       // 取得済みデータがなければ、スレッドを起動
00280       if ((! pimpl_->thread_.isRunning()) && pimpl_->data_buffer_.empty()) {
00281         pimpl_->thread_.run(1);
00282       }
00283 
00284       // 取得済みデータがなければ、戻る
00285       if (pimpl_->data_buffer_.empty()) {
00286         if (pimpl_->invalid_packet_) {
00287           return -1;
00288         }
00289         return 0;
00290       }
00291 
00292       swap(data, pimpl_->data_buffer_.front().length_data);
00293       if (timestamp) {
00294         *timestamp = pimpl_->data_buffer_.front().timestamp;
00295       }
00296       CaptureSettings settings = pimpl_->data_buffer_.front().settings;
00297       pimpl_->data_buffer_.pop_front();
00298       pimpl_->intensity_data_.timestamp = *timestamp;
00299       pimpl_->intensity_data_.length_data.clear();
00300 
00301       if (pimpl_->urg_type_.compare("URG-04LX") &&
00302           pimpl_->urg_type_.compare("URG-04LX-UG01") &&
00303           pimpl_->urg_type_.compare("UBG-04LX-F01")) {
00304           // UTM-30LX のとき
00305         int skip_lines = settings.skip_lines;
00306         int min_length = pimpl_->parameters_.distance_min;
00307         int n = data.size() / skip_lines / 2;
00308         pimpl_->intensity_data_.length_data.reserve(n * skip_lines);
00309 
00310         int filled = 0;
00311         for (int i = 0; i < n; ++i) {
00312           size_t index = 2 * skip_lines * i;
00313           long length = data[index];
00314           long intensity_value =
00315             (length < min_length) ? 0 : data[index + skip_lines];
00316           for (int j = 0; j < skip_lines; ++j) {
00317             pimpl_->intensity_data_.length_data.push_back(intensity_value);
00318             data[filled++] = length;
00319           }
00320         }
00321         vector<long>::iterator first_it = data.begin() + (data.size() / 2);
00322         data.erase(first_it, data.end());
00323 
00324       } else if ((! pimpl_->urg_type_.compare("URG-04LX")) ||
00325                  (! pimpl_->urg_type_.compare("URG-04LX-UG01")) ||
00326                  (! pimpl_->urg_type_.compare("UBG-04LX-F01"))) {
00327         // URG-04LX のとき
00328         size_t n = data.size();
00329         int min_length = pimpl_->parameters_.distance_min;
00330         pimpl_->intensity_data_.length_data.reserve(data.size());
00331         size_t offset = pimpl_->capture_begin_ & 0x1;
00332         for (size_t i = 0; i < n; i += 2) {
00333           size_t index = i + offset;
00334           long length = data[index];
00335           if ((index + 1) < n) {
00336             long intensity_value = (length < min_length) ? 0 : data[index + 1];
00337             pimpl_->intensity_data_.length_data.push_back(intensity_value);
00338             pimpl_->intensity_data_.length_data.push_back(intensity_value);
00339             data[index + 1] = length;
00340           }
00341         }
00342       } else {
00343         // !!! エラー処理
00344       }
00345 
00346       return static_cast<int>(data.size());
00347     }
00348 
00349 
00350     void setCapturesSize(size_t size)
00351     {
00352       captures_size_ = size;
00353     }
00354 
00355 
00356     size_t capturesSize(void)
00357     {
00358       return captures_size_;
00359     }
00360 
00361     size_t remainCaptureTimes(void)
00362     {
00363       if (pimpl_->capture_times_ == 0) {
00364         return numeric_limits<size_t>::max();
00365       }
00366 
00367       LockGuard guard(pimpl_->mutex_);
00368       return pimpl_->remain_times_;
00369     }
00370   };
00371 
00372 
00373   string error_message_;
00374   UrgDevice* parent_;
00375   Connection* con_;
00376   SerialDevice* serial_; 
00377   ScipHandler scip_;
00378   RangeSensorParameter parameters_;
00379   string urg_type_;
00380   long recent_timestamp_;
00381   int timestamp_offset_;
00382 
00383   RangeCaptureMode capture_mode_;
00384   RawManualCapture manual_capture_;
00385   RawAutoCapture auto_capture_;
00386   RawIntensityCapture intensity_capture_;
00387   Capture* capture_;
00388   Thread thread_;
00389   Lock mutex_;
00390 
00391   deque<ScanData> data_buffer_;
00392   ScanData intensity_data_;
00393 
00394   int capture_begin_;
00395   int capture_end_;
00396   size_t capture_skip_lines_;
00397   int capture_skip_frames_;
00398 
00399   size_t capture_frame_interval_;
00400   size_t capture_times_;
00401   size_t remain_times_;
00402   bool invalid_packet_;
00403   size_t max_retry_times_;
00404   size_t retry_times_;
00405 
00406   long base_timestamp_;
00407   long pre_timestamp_;
00408 
00409 
00410   pImpl(UrgDevice* parent)
00411     : error_message_("no error."), parent_(parent),
00412       con_(NULL), serial_(NULL), urg_type_(""),
00413       recent_timestamp_(0), timestamp_offset_(0),
00414       capture_mode_(ManualCapture),
00415       manual_capture_(this), auto_capture_(this),
00416       intensity_capture_(this), capture_(&manual_capture_),
00417       thread_(&capture_thread, this),
00418       capture_begin_(0), capture_end_(0),
00419       capture_skip_lines_(1), capture_skip_frames_(0),
00420       capture_frame_interval_(0), capture_times_(0),
00421       remain_times_(0), invalid_packet_(false),
00422       max_retry_times_(DefaultRetryTimes), retry_times_(0),
00423       base_timestamp_(0), pre_timestamp_(0)
00424   {
00425   }
00426 
00427 
00428   ~pImpl(void)
00429   {
00430     disconnect();
00431 
00432     // con_ は外部からセットされる可能性があるため、このクラスでは解放しない
00433     // serial_ のみ解放する
00434     delete serial_;
00435   }
00436 
00437 
00438   void initializeSerial(void)
00439   {
00440     if (! serial_) {
00441       serial_ = new SerialDevice;
00442     }
00443     con_ = serial_;
00444   }
00445 
00446 
00447   bool connect(const char* device, long baudrate)
00448   {
00449     disconnect();
00450     if (! con_) {
00451       initializeSerial();
00452     }
00453     scip_.setConnection(con_);
00454 
00455     // ボーレートを検出した上でのデバイスとの接続
00456     if (! scip_.connect(device, baudrate)) {
00457       error_message_ = scip_.what();
00458       return false;
00459     }
00460 
00461     if (! loadParameter()) {
00462       return false;
00463     }
00464     updateCaptureParameters();
00465 
00466     return true;
00467   }
00468 
00469 
00470   bool loadParameter(void)
00471   {
00472     // URG パラメータの取得
00473     RangeSensorParameter parameters;
00474     if (! scip_.loadParameter(parameters)) {
00475       error_message_ = scip_.what();
00476       return false;
00477     }
00478     swap(parameters_, parameters);
00479 
00480     size_t type_length = min(parameters_.model.find('('),
00481                              parameters_.model.find('['));
00482     urg_type_ = parameters_.model.substr(0, type_length);
00483 
00484     // !!! capture_begin_, capture_end_ との調整をすべき
00485     // !!! min(), max() を使うこと
00486 
00487     return true;
00488   }
00489 
00490 
00491   void disconnect(void)
00492   {
00493     stop();
00494     if (con_) {
00495       con_->disconnect();
00496     }
00497   }
00498 
00499 
00500   void updateCaptureParameters(void)
00501   {
00502     capture_begin_ = parameters_.area_min;
00503     capture_end_ = parameters_.area_max;
00504   }
00505 
00506 
00507   // AutoCapture, IntensityCapture のデータ取得を行う
00508   static int capture_thread(void* args)
00509   {
00510     pImpl* obj = static_cast<pImpl*>(args);
00511 
00512     // 設定に基づいて、データ受信コマンドを作成して発行
00513     string capture_command = obj->capture_->createCaptureCommand();
00514     if (capture_command.empty()) {
00515       // ここのエラーが IntensityCapture のときのみ発生するのに依存した実装
00516       obj->error_message_ = "This urg is not support intensity capture.";
00517       return -1;
00518     }
00519     int n = obj->scip_.send(capture_command.c_str(),
00520                             static_cast<int>(capture_command.size()));
00521     if (n != static_cast<int>(capture_command.size())) {
00522       obj->error_message_ = capture_command + " fail.";
00523       ++obj->retry_times_;
00524       return -1;
00525     }
00526 
00527     // 受信待ち
00528     ScanData data;
00529     int remain_times = MdScansMax;
00530     int total_times = 0;
00531     while (1) {
00532       // 受信完了、およびエラーで抜ける
00533       obj->invalid_packet_ = false;
00534       CaptureType type =
00535         obj->scip_.receiveCaptureData(data.length_data, data.settings,
00536                                       &data.timestamp,
00537                                       &remain_times, &total_times);
00538       if (type == Mx_Reply) {
00539         // MS/MD の応答パケットの場合、次のデータを待つ
00540         continue;
00541       }
00542 
00543       if (! ((type == MD) || (type == MS) || (type == ME))) {
00544         // 受信データでなければ、スレッド処理を中断する
00545         obj->invalid_packet_ = true;
00546         ++obj->retry_times_;
00547         break;
00548       }
00549       obj->retry_times_ = 0;
00550 
00551       // タイムスタンプが 24 bit しかないため、1巡することへの対処
00552       if ((data.timestamp >= 0) && (data.timestamp < obj->pre_timestamp_)) {
00553         obj->base_timestamp_ += 1 << 24;
00554       }
00555       obj->pre_timestamp_ = data.timestamp;
00556       data.timestamp += obj->base_timestamp_;
00557 
00558       LockGuard guard(obj->mutex_);
00559       deque<ScanData>& data_buffer = obj->data_buffer_;
00560 
00561       // 古くなったデータを取り除く
00562       int current_size = static_cast<int>(data_buffer.size());
00563       int erase_size =
00564         current_size - static_cast<int>(obj->capture_->capturesSize());
00565       if (erase_size > 0) {
00566         data_buffer.erase(data_buffer.begin(),
00567                           data_buffer.begin() + erase_size);
00568       }
00569 
00570       // 今回のデータを追加
00571       ScanData dummy_data;
00572       data_buffer.push_back(dummy_data);
00573       swap(data_buffer.back(), data);
00574 
00575       if ((obj->capture_times_ > 0) && (remain_times < MdScansMax)) {
00576         obj->remain_times_ = remain_times;
00577       } else {
00578         --obj->remain_times_;
00579         if (obj->remain_times_ == 0) {
00580           obj->scip_.setLaserOutput(Off);
00581         }
00582       }
00583       obj->parent_->captureReceived();
00584 
00585       if ((total_times > 0) && (remain_times == 0)) {
00586         // 取得が終了したら、抜ける
00587         break;
00588       }
00589     }
00590 
00591     return 0;
00592   }
00593 
00594 
00595   int capture(vector<long>& data, long* timestamp)
00596   {
00597     long raw_timestamp = 0;
00598     int n = capture_->capture(data, &raw_timestamp);
00599     if (n < 0) {
00600       error_message_ = scip_.what();
00601       return n;
00602     }
00603 
00604     recent_timestamp_ = raw_timestamp - timestamp_offset_;
00605     if (timestamp) {
00606       *timestamp = recent_timestamp_;
00607     }
00608     return n;
00609   }
00610 
00611 
00612   int captureWithIntensity(vector<long>& data,
00613                            vector<long>& intensity_data,
00614                            long* timestamp)
00615   {
00616     int n = capture(data, timestamp);
00617     if (n < 0) {
00618       return n;
00619     }
00620     return captureIntensity(intensity_data, NULL);
00621   }
00622 
00623 
00624   int captureIntensity(vector<long>& intensity_data, int* timestamp)
00625   {
00626     if (capture_mode_ != IntensityCapture) {
00627       error_message_ = "please call setCaptureMode(IntensityCapture).";
00628       return -1;
00629     }
00630 
00631     if (intensity_data_.length_data.empty()) {
00632       return 0;
00633     }
00634 
00635     if (timestamp) {
00636       *timestamp = intensity_data_.timestamp;
00637       recent_timestamp_ = *timestamp;
00638     }
00639     swap(intensity_data, intensity_data_.length_data);
00640     intensity_data_.length_data.clear();
00641 
00642     return static_cast<int>(intensity_data.size());
00643   }
00644 
00645 
00646   bool setTimestamp(int timestamp, int* response_msec, int* force_delay_msec)
00647   {
00648     long prepare_ticks = ticks();
00649 
00650     // TM0 モードに遷移
00651     // !!! true, false をキーワードで置換すること
00652     if (! scip_.setRawTimestampMode(true)) {
00653       return false;
00654     }
00655 
00656     // TM1 のタイムスタンプを取得し、通信遅延と URG のタイムスタンプを取得する
00657     int urg_timestamp = 0;
00658     int first_ticks = ticks();
00659     if (scip_.rawTimestamp(&urg_timestamp)) {
00660 
00661       //fprintf(stderr, "raw: %d, %d\n", timestamp, urg_timestamp);
00662 
00663       int delay = ticks() - first_ticks;
00664       if (force_delay_msec) {
00665         delay = *force_delay_msec;
00666       }
00667       if (response_msec) {
00668         *response_msec = delay;
00669       }
00670       timestamp_offset_ =
00671           (urg_timestamp + (delay / 2))
00672           - (timestamp + (first_ticks - prepare_ticks));
00673     }
00674 
00675     // URG タイムスタンプ用のオフセット時間を計算し、TM2 で抜ける
00676     if (! scip_.setRawTimestampMode(false)) {
00677       return false;
00678     }
00679 
00680     return true;
00681   }
00682 
00683 
00684   int rad2index(const double radian) const
00685   {
00686     int area_total = parameters_.area_total;
00687     int index =
00688       static_cast<int>(floor(((radian * area_total) / (2.0 * M_PI)) + 0.5)
00689                        + parameters_.area_front);
00690 
00691     if (index < 0) {
00692       index = 0;
00693     } else if (index > parameters_.area_max) {
00694       index = parameters_.area_max;
00695     }
00696     return index;
00697   }
00698 
00699 
00700   bool isConnected(void) const
00701   {
00702     return (con_ == NULL) ? false : con_->isConnected();
00703   }
00704 
00705 
00706   void stop(void)
00707   {
00708     if (! isConnected()) {
00709       return;
00710     }
00711 
00712     if (capture_mode_ == ManualCapture) {
00713       return;
00714     }
00715 
00716     // QT コマンドの発行
00717     scip_.setLaserOutput(ScipHandler::Off);
00718 
00719     // 応答を待つ
00720     if (thread_.isRunning()) {
00721       thread_.wait();
00722     }
00723   }
00724 
00725 
00726   void clear(void)
00727   {
00728     LockGuard guard(mutex_);
00729     data_buffer_.clear();
00730     intensity_data_.length_data.clear();
00731   }
00732 };
00733 
00734 
00735 UrgDevice::UrgDevice(void) : pimpl(new pImpl(this))
00736 {
00737 }
00738 
00739 
00740 UrgDevice::~UrgDevice(void)
00741 {
00742 }
00743 
00744 
00745 void UrgDevice::captureReceived(void)
00746 {
00747   // 受信完了を継承先のクラスが利用するためのメソッド
00748 }
00749 
00750 
00751 const char* UrgDevice::what(void) const
00752 {
00753   return pimpl->error_message_.c_str();
00754 }
00755 
00756 
00757 bool UrgDevice::connect(const char* device, long baudrate)
00758 {
00759   return pimpl->connect(device, baudrate);
00760 }
00761 
00762 
00763 void UrgDevice::setConnection(Connection* con)
00764 {
00765   pimpl->serial_ = NULL;
00766   pimpl->con_ = con;
00767   pimpl->scip_.setConnection(con);
00768 }
00769 
00770 
00771 Connection* UrgDevice::connection(void)
00772 {
00773   return pimpl->con_;
00774 }
00775 
00776 
00777 void UrgDevice::disconnect(void)
00778 {
00779   pimpl->disconnect();
00780 }
00781 
00782 
00783 bool UrgDevice::isConnected(void) const
00784 {
00785   return pimpl->isConnected();
00786 }
00787 
00788 
00789 long UrgDevice::minDistance(void) const
00790 {
00791   return pimpl->parameters_.distance_min;
00792 }
00793 
00794 
00795 long UrgDevice::maxDistance(void) const
00796 {
00797   return pimpl->parameters_.distance_max;
00798 }
00799 
00800 
00801 int UrgDevice::maxScanLines(void) const
00802 {
00803   // +1 は、parameters_ が未初期化のときに new long [0] しないための処置
00804   return pimpl->parameters_.area_max + 1;
00805 }
00806 
00807 
00808 void UrgDevice::setRetryTimes(size_t times)
00809 {
00810   pimpl->max_retry_times_ = times;
00811 }
00812 
00813 
00814 void UrgDevice::setCapturesSize(size_t size)
00815 {
00816   pimpl->capture_->setCapturesSize(size);
00817 }
00818 
00819 
00820 size_t UrgDevice::remainCaptureTimes(void)
00821 {
00822   return pimpl->capture_->remainCaptureTimes();
00823 }
00824 
00825 
00826 int UrgDevice::scanMsec(void) const
00827 {
00828   int scan_rpm = pimpl->parameters_.scan_rpm;
00829   return (scan_rpm <= 0) ? 1 : (1000 * 60 / scan_rpm);
00830 }
00831 
00832 
00833 void UrgDevice::setCaptureMode(RangeCaptureMode mode)
00834 {
00835   // capture を停止する。capture の再開は行わない
00836   stop();
00837   pimpl->clear();
00838 
00839   if (mode == ManualCapture) {
00840     pimpl->capture_ = &pimpl->manual_capture_;
00841 
00842   } else if (mode == AutoCapture) {
00843     pimpl->capture_ = &pimpl->auto_capture_;
00844 
00845   } else if (mode == IntensityCapture) {
00846     pimpl->capture_ = &pimpl->intensity_capture_;
00847   }
00848 
00849   pimpl->capture_mode_ = mode;
00850 }
00851 
00852 
00853 RangeCaptureMode UrgDevice::captureMode(void)
00854 {
00855   return pimpl->capture_mode_;
00856 }
00857 
00858 
00859 void UrgDevice::setCaptureRange(int begin_index, int end_index)
00860 {
00861   // !!! 排他制御
00862 
00863   // capture を停止する。capture の再開は行わない
00864   stop();
00865   pimpl->clear();
00866 
00867   pimpl->capture_begin_ = begin_index;
00868   pimpl->capture_end_ = end_index;
00869 }
00870 
00871 
00872 void UrgDevice::setCaptureFrameInterval(size_t interval)
00873 {
00874   // !!! 排他制御
00875 
00876   // capture を停止する。capture の再開は行わない
00877   stop();
00878   pimpl->clear();
00879 
00880   pimpl->capture_frame_interval_ = interval;
00881 }
00882 
00883 
00884 void UrgDevice::setCaptureTimes(size_t times)
00885 {
00886   // !!! 排他制御
00887 
00888   // capture を停止する。capture の再開は行わない
00889   stop();
00890   pimpl->clear();
00891 
00892   // !!! 範囲制限の判定処理
00893   pimpl->capture_times_ = times;
00894 }
00895 
00896 
00897 
00898 void UrgDevice::setCaptureSkipLines(size_t skip_lines)
00899 {
00900   // capture を停止する。capture の再開は行わない
00901   stop();
00902   pimpl->clear();
00903 
00904   pimpl->capture_skip_lines_ = skip_lines;
00905 }
00906 
00907 
00908 int UrgDevice::capture(vector<long>& data, long* timestamp)
00909 {
00910   // !!! 未接続ならば、戻す
00911 
00912   return pimpl->capture(data, timestamp);
00913 }
00914 
00915 
00916 int UrgDevice::captureWithIntensity(vector<long>& data,
00917                                   vector<long>& intensity_data,
00918                                   long* timestamp)
00919 {
00920   // !!! 未接続ならば、戻す
00921   return pimpl->captureWithIntensity(data, intensity_data, timestamp);
00922 }
00923 
00924 
00925 void UrgDevice::stop(void)
00926 {
00927   pimpl->stop();
00928 }
00929 
00930 
00931 bool UrgDevice::setTimestamp(int ticks, int* response_msec,
00932                              int* force_delay_msec)
00933 {
00934   // !!! 未接続ならば、戻す
00935 
00936   return pimpl->setTimestamp(ticks, response_msec, force_delay_msec);
00937 }
00938 
00939 
00940 long UrgDevice::recentTimestamp(void) const
00941 {
00942   return pimpl->recent_timestamp_;
00943 }
00944 
00945 
00946 bool UrgDevice::setLaserOutput(bool on)
00947 {
00948   // !!! 未接続ならば、戻す
00949 
00950   return pimpl->scip_.setLaserOutput(on, ScipHandler::Force);
00951 }
00952 
00953 
00954 double UrgDevice::index2rad(const int index) const
00955 {
00956   int index_from_front = index - pimpl->parameters_.area_front;
00957   return index_from_front * (2.0 * M_PI) / pimpl->parameters_.area_total;
00958 }
00959 
00960 
00961 int UrgDevice::rad2index(const double radian) const
00962 {
00963   return pimpl->rad2index(radian);
00964 }
00965 
00966 
00967 void UrgDevice::setParameter(const RangeSensorParameter& parameter)
00968 {
00969   pimpl->parameters_ = parameter;
00970   pimpl->updateCaptureParameters();
00971 }
00972 
00973 
00974 RangeSensorParameter UrgDevice::parameter(void) const
00975 {
00976   return pimpl->parameters_;
00977 }
00978 
00979 
00980 bool UrgDevice::loadParameter(void)
00981 {
00982   return pimpl->loadParameter();
00983 }
00984 
00985 
00986 bool UrgDevice::versionLines(vector<string>& lines)
00987 {
00988   if (! isConnected()) {
00989     return false;
00990   }
00991 
00992   return pimpl->scip_.versionLines(lines);
00993 }
00994 
00995 
00996 bool UrgDevice::reboot(void)
00997 {
00998   UrgDevice::setLaserOutput(Off);
00999 
01000   // send "RB" twice.
01001   for (int i = 0; i < 2; ++i) {
01002     pimpl->scip_.send("RB\n", 3);
01003 
01004     enum {
01005       RB_Timeout = 1000,        // [msec]
01006     };
01007     char recv_buffer[3];
01008     int send_n = pimpl->scip_.recv(recv_buffer, 3, RB_Timeout);
01009     if (send_n != 3) {
01010       return false;
01011     }
01012     if (strncmp(recv_buffer, "RB\n", 3)) {
01013       return false;
01014     }
01015   }
01016 
01017   UrgDevice::disconnect();
01018 
01019   return true;
01020 }