All Classes Namespaces Files Functions Variables Enumerations Enumerator
libs/range_sensor/ScipHandler.cpp
Go to the documentation of this file.
00001 
00010 #include "ScipHandler.h"
00011 #include "RangeSensorParameter.h"
00012 #include "Connection.h"
00013 #include "ConnectionUtils.h"
00014 #include "ticks.h"
00015 #include "delay.h"
00016 #include "DetectOS.h"
00017 #include "log_printf.h"
00018 #include <cstring>
00019 #include <cstdio>
00020 
00021 #ifdef MSC
00022 #define snprintf _snprintf
00023 #endif
00024 
00025 using namespace qrk;
00026 using namespace std;
00027 
00028 
00029 namespace
00030 {
00031   typedef enum {
00032     ProcessContinue,
00033     ProcessBreak,
00034     ProcessNormal,
00035   } LoopProcess;
00036 
00037   void clearReceived(vector<long>& data, CaptureType& type,
00038                      int& line_count, int& timeout,
00039                      string& remain_string,
00040                      string& left_packet_data)
00041   {
00042     data.clear();
00043     type = TypeUnknown;
00044     line_count = 0;
00045     timeout = 0;
00046     remain_string.clear();
00047     left_packet_data.clear();
00048   }
00049 }
00050 
00051 
00052 struct ScipHandler::pImpl
00053 {
00054   enum {
00055     TotalTimeout = 1000,        // [msec]
00056     ContinuousTimeout = 100,    // [msec]
00057     FirstTimeout = 1000,        // [msec]
00058 
00059     BufferSize = 64 + 1 + 1,    // データ長 + チェックサム + 改行
00060 
00061     ResponseTimeout = -1,
00062     MismatchResponse = -2,
00063     SendFail = -3,
00064     ChecksumFail = -4,
00065     Scip11Response = -14,
00066 
00067     InvalidRange = -1,
00068   };
00069 
00070   typedef enum {
00071     LaserUnknown = 0,
00072     LaserOn,
00073     LaserOff,
00074   } LaserState;
00075 
00076   string error_message_;
00077   Connection* con_;
00078   LaserState laser_state_;
00079   bool mx_capturing_;
00080 
00081   bool isPreCommand_QT_;
00082 
00083 
00084   pImpl(void)
00085     : error_message_("no error."), con_(NULL), laser_state_(LaserUnknown),
00086       mx_capturing_(false), isPreCommand_QT_(false)
00087   {
00088   }
00089 
00090 
00091   bool connect(const char* device, long baudrate)
00092   {
00093     if (! con_->connect(device, baudrate)) {
00094       error_message_ = con_->what();
00095       return false;
00096     }
00097 
00098     long try_baudrates[] = { 115200, 19200, 38400, };
00099     size_t try_size = sizeof(try_baudrates) / sizeof(try_baudrates[0]);
00100 
00101     // 接続したいボーレートを配列の先頭と入れ換える
00102     for (size_t i = 1; i < try_size; ++i) {
00103       if (baudrate == try_baudrates[i]) {
00104         swap(try_baudrates[0], try_baudrates[i]);
00105         break;
00106       }
00107     }
00108 
00109     // 指定のボーレートで接続し、応答が返されるかどうか試す
00110     for (size_t i = 0; i < try_size; ++i) {
00111 
00112       // ホスト側のボーレートを変更
00113       if (! con_->setBaudrate(try_baudrates[i])) {
00114         error_message_ = con_->what();
00115         return false;
00116       }
00117 
00118       // 前回分の受信パケットを読み捨て
00119       con_->clear();
00120 
00121       // QT の発行
00122       int return_code = -1;
00123       char qt_expected_response[] = { 0, -1 };
00124       // return_code を使いたいため、setLaserOutput() を用いずに QT を送信する
00125       if (response(return_code, "QT\n", qt_expected_response)) {
00126         laser_state_ = LaserOff;
00127         return changeBothBaudrate(baudrate);
00128 
00129       } else if (return_code == ResponseTimeout) {
00130         // ボーレートが違っていて、通信できなかったとみなす
00131         error_message_ = "baudrate is not detected.";
00132         continue;
00133 
00134       } else if (return_code == MismatchResponse) {
00135         // MD/MS の応答とみなし、受信データを読み飛ばす
00136         con_->clear();
00137         skip(con_, ContinuousTimeout);
00138         return changeBothBaudrate(baudrate);
00139 
00140       } else if (return_code == Scip11Response) {
00141         // SCIP1.1 プロトコルの場合のみ、SCIP2.0 を送信する
00142         char scip20_expected_response[] = { 0, -1 };
00143         if (! response(return_code, "SCIP2.0\n", scip20_expected_response)) {
00144           error_message_ =
00145             "SCIP1.1 protocol is not supported. Please update URG firmware, or reconnect after a few seconds because sensor is booting.";
00146           return false;
00147         }
00148         laser_state_ = LaserOff;
00149         return changeBothBaudrate(baudrate);
00150 
00151       } else if (return_code == 0xE) {
00152         // TM モードとみなし、TM2 を発行する
00153         char tm2_expected_response[] = { 0, -1 };
00154         if (response(return_code, "TM2\n", tm2_expected_response)) {
00155           laser_state_ = LaserOff;
00156           return changeBothBaudrate(baudrate);
00157         }
00158       }
00159     }
00160 
00161     con_->disconnect();
00162     return false;
00163   }
00164 
00165 
00166   bool changeBothBaudrate(long baudrate)
00167   {
00168     // 既に目標対象のボーレート値ならば、成功とみなす
00169     // この関数は、ScipHandler::connect() か、それ以後でないと呼ばれないため
00170     if (con_->baudrate() == baudrate) {
00171       return true;
00172     }
00173 
00174     // URG 側のボーレートを変更
00175     int pre_ticks = ticks();
00176     if (! changeBaudrate(baudrate)) {
00177       return false;
00178     }
00179 
00180     // シリアル通信の場合、ボーレート変更後、1周分だけ待つ必要がある
00181     int reply_msec = ticks() - pre_ticks;
00182     delay((reply_msec * 4 / 3) + 10);
00183 
00184     // ホスト側のボーレートを変更
00185     return con_->setBaudrate(baudrate);
00186   }
00187 
00188 
00189   bool changeBaudrate(long baudrate)
00190   {
00191 #if 0
00192     // Tcpip 接続に対応するため、コメントアウト
00193     if (! ((baudrate == 19200) || (baudrate == 38400) ||
00194            (baudrate == 57600) || (baudrate == 115200))) {
00195       error_message_ = "Invalid baudrate value.";
00196       return false;
00197     }
00198 #endif
00199 
00200     // SS を送信し、URG 側のボーレートを変更する
00201     char send_buffer[] = "SSxxxxxx\n";
00202     snprintf(send_buffer, 10, "SS%06ld\n", baudrate);
00203     int return_code = -1;
00204     // !!! 既に設定対象のボーレート、の場合の戻り値を ss_expected... に追加する
00205     char ss_expected_response[] = { 0, 0x3, 0x4, 0xf, -1 };
00206     if (! response(return_code, send_buffer, ss_expected_response)) {
00207       error_message_ = "Baudrate change fail.";
00208       return false;
00209     }
00210 
00211     return true;
00212   }
00213 
00214 
00215   bool loadParameter(RangeSensorParameter& parameters)
00216   {
00217     // PP の送信とデータの受信
00218     int return_code = -1;
00219     char pp_expected_response[] = { 0, -1 };
00220     vector<string> lines;
00221     if (! response(return_code, "PP\n", pp_expected_response, &lines)) {
00222       error_message_ = "PP fail.";
00223       return false;
00224     }
00225 
00226     // PP 応答内容の格納
00227     if (lines.size() != 8) {
00228       error_message_ = "Invalid PP response.";
00229       return false;
00230     }
00231 
00232     // !!! チェックサムの評価を行うべき
00233 
00234     int modl_length =
00235       static_cast<int>(lines[RangeSensorParameter::MODL].size());
00236     // 最初のタグと、チェックサムを除いた文字列を返す
00237     if (modl_length > (5 + 2)) {
00238       modl_length -= (5 + 2);
00239     }
00240     parameters.model = lines[RangeSensorParameter::MODL].substr(5, modl_length);
00241 
00242     parameters.distance_min = substr2int(lines[RangeSensorParameter::DMIN], 5);
00243     parameters.distance_max = substr2int(lines[RangeSensorParameter::DMAX], 5);
00244     parameters.area_total = substr2int(lines[RangeSensorParameter::ARES], 5);
00245     parameters.area_min = substr2int(lines[RangeSensorParameter::AMIN], 5);
00246     parameters.area_max = substr2int(lines[RangeSensorParameter::AMAX], 5);
00247     parameters.area_front = substr2int(lines[RangeSensorParameter::AFRT], 5);
00248     parameters.scan_rpm = substr2int(lines[RangeSensorParameter::SCAN], 5);
00249 
00250     return true;
00251   }
00252 
00253 
00254   int substr2int(const string& line, int from_n, int length = string::npos)
00255   {
00256     return atoi(line.substr(from_n, length).c_str());
00257   }
00258 
00259 
00260   bool response(int& return_code, const char send_command[],
00261                 char expected_response[],
00262                 vector<string>* lines = NULL)
00263   {
00264     return_code = -1;
00265     if (! con_) {
00266       error_message_ = "no connection.";
00267       return false;
00268     }
00269 
00270     size_t send_size = strlen(send_command);
00271     int actual_send_size = con_->send(send_command, send_size);
00272     if (strncmp(send_command, "QT\n", send_size)) {
00273       isPreCommand_QT_ = false;
00274     }
00275     if (actual_send_size != static_cast<int>(send_size)) {
00276       return_code = SendFail;
00277       return false;
00278     }
00279 
00280     // エコーバックの受信
00281     char buffer[BufferSize];
00282     int recv_size = readline(con_, buffer, BufferSize, FirstTimeout);
00283     if (recv_size < 0) {
00284       error_message_ = "response timeout.";
00285       return_code = ResponseTimeout;
00286       return false;
00287     }
00288 
00289     // シリアル接続でボーレート変更直後の 0x00 は、判定外とする
00290     if (! ((recv_size == 1) && (buffer[0] == 0x00))) {
00291       if ((recv_size != static_cast<int>(send_size - 1)) ||
00292           (strncmp(buffer, send_command, recv_size))) {
00293         error_message_ = "mismatch response: " + string(buffer);
00294         return_code = MismatchResponse;
00295         return false;
00296       }
00297     }
00298 
00299     // 応答の受信
00300     // !!! 上記の処理となるべく共通にする
00301     // !!! SCIP1.1 プロトコルの応答は、負号を付加した上で return_code に格納する
00302     recv_size = readline(con_, buffer, BufferSize, ContinuousTimeout);
00303     if (recv_size < 0) {
00304       // !!! この処理をくくる
00305       error_message_ = "response timeout.";
00306       return_code = ResponseTimeout;
00307       return false;
00308     }
00309     if (recv_size == 3) {
00310       // 3文字ならば、SCIP2.0 とみなしてチェックサムを確認する
00311       // !!! チェックサムの確認
00312       if (! checkSum(buffer, recv_size - 1, buffer[recv_size - 1])) {
00313         return_code = ChecksumFail;
00314         return false;
00315       }
00316       buffer[2] = '\0';
00317       return_code = strtol(buffer, NULL, 16);
00318 
00319     } else if (recv_size == 1) {
00320       // 1文字ならば、SCIP1.1 とみなして 16進変換した値に負号をつけて返す
00321       buffer[1] = '\0';
00322       return_code = -strtol(buffer, NULL, 16);
00323     }
00324 
00325     // データ領域の受信
00326     // 1行読み出し、改行のみならば終了とみなす
00327     do {
00328       recv_size = readline(con_, buffer, BufferSize, ContinuousTimeout);
00329       if (lines && (recv_size > 0)) {
00330         lines->push_back(buffer);
00331       }
00332     } while (recv_size > 0);
00333 
00334     for (int i = 0; expected_response[i] != -1; ++i) {
00335       if (return_code == expected_response[i]) {
00336         return true;
00337       }
00338     }
00339     return false;
00340   }
00341 
00342 
00343   bool setLaserOutput(bool on, bool force)
00344   {
00345     if (((on == true) && (laser_state_ == LaserOn)) ||
00346         ((on == false) && (laser_state_ == LaserOff))) {
00347       if (! force) {
00348         // レーザ出力が現在の状態と同じならば戻る
00349         // 強制設定フラグが true のときは戻らずに設定を行う
00350         return true;
00351       }
00352     }
00353     if ((!on) && isPreCommand_QT_) {
00354       return false;
00355     }
00356 
00357     if (on) {
00358       int return_code = -1;
00359       char expected_response[] = { 0, -1 };
00360       if (! response(return_code, "BM\n", expected_response)) {
00361         error_message_ = "BM fail.";
00362         return false;
00363       }
00364       laser_state_ = LaserOn;
00365       return true;
00366 
00367     } else {
00368       // "QT"
00369       if (! mx_capturing_) {
00370         // 消灯するための QT では、応答を待つべき
00371         int return_code = -1;
00372         char qt_expected_response[] = { 0, -1 };
00373         if (! response(return_code, "QT\n", qt_expected_response)) {
00374           return false;
00375         }
00376         laser_state_ = LaserOff;
00377         isPreCommand_QT_ = true;
00378         return true;
00379 
00380       } else {
00381         // MD を中断するための QT では、応答を待ってはならない
00382         // 応答は、受信スレッド内で処理される
00383         con_->send("QT\n", 3);
00384         isPreCommand_QT_ = true;
00385       }
00386 
00387       return true;
00388     }
00389   }
00390 
00391 
00392   bool testChecksum(const char* buffer, int line_size,
00393                     vector<long>& data, CaptureType& type,
00394                     int line_count, int timeout,
00395                     string& remain_string, string& left_packet_data)
00396   {
00397     if (! checkSum(buffer, line_size - 1, buffer[line_size - 1])) {
00398       log_printf("checksum error: %s\n", buffer);
00399       // return InvalidData;
00400       // !!! URG のパケットエラーがなくなったら、この実装に戻す
00401 
00402       // !!! 存在するだけのパケットを読み飛ばす
00403       error_message_ = "invalid packet.";
00404       clearReceived(data, type, line_count, timeout,
00405                     remain_string, left_packet_data);
00406       return false;
00407     }
00408 
00409     return true;
00410   }
00411 
00412 
00413   LoopProcess handleEchoback(const char* buffer, CaptureSettings& settings,
00414                              CaptureType& type, vector<long>& data,
00415                              int line_count, int timeout,
00416                              string& remain_string,
00417                              string& left_packet_data)
00418   {
00419     string line = buffer;
00420     if ((! line.compare(0, 2, "GD")) || (! line.compare(0, 2, "GS"))) {
00421       if (! parseGdEchoback(settings, line)) {
00422         return ProcessBreak;
00423       }
00424       type = (line[1] = 'D') ? GD : GS;
00425 
00426     } else if ((! line.compare(0, 2, "MD")) ||
00427                (! line.compare(0, 2, "MS"))) {
00428       if (! parseMdEchoback(settings, line)) {
00429         return ProcessBreak;
00430       }
00431       type = (line[1] = 'D') ? MD : MS;
00432       laser_state_ = LaserOn;
00433 
00434     } else if (! line.compare(0, 2, "ME")) {
00435       if (! parseMeEchoback(settings, line)) {
00436         return ProcessBreak;
00437       }
00438       type = ME;
00439       laser_state_ = LaserOn;
00440 
00441     } else if (! line.compare(0, 2, "QT")) {
00442       settings.remain_times = 0;
00443       laser_state_ = LaserOff;
00444       mx_capturing_ = false;
00445       return ProcessNormal;
00446 
00447     } else {
00448       //return InvalidData;
00449       // !!! URG が正常なパケットを返すようになったら、この実装に戻す
00450 
00451       clearReceived(data, type, line_count, timeout,
00452                     remain_string, left_packet_data);
00453       //fprintf(stderr, "invalid data: %s\n", buffer);
00454       return ProcessContinue;
00455     }
00456 
00457     data.reserve(settings.capture_last + 1);
00458     return ProcessNormal;
00459   }
00460 
00461 
00462   void handleReturnCode(char* buffer, CaptureSettings& settings, int timeout,
00463                         CaptureType& type, int* total_times)
00464   {
00465     // !!! 長さが 2 + 1 かのチェックをすべき
00466     buffer[2] = '\0';
00467     settings.error_code = atoi(buffer);
00468 
00469     if (settings.error_code == 10) {
00470       // レーザ消灯を検出
00471       laser_state_ = pImpl::LaserOff;
00472     }
00473 
00474     // "0B" が返された場合、センサとホストの応答がずれている可能性があるので
00475     // 続く応答を読み捨てる
00476     if (! strncmp(buffer, "0B", 2)) {
00477       skip(con_, TotalTimeout, timeout);
00478     }
00479 
00480     // !!! "00P" との比較をすべき
00481     if ((settings.error_code == 0) &&
00482         ((type == MD) || (type == MS) || (type == ME))) {
00483       if (total_times) {
00484         *total_times = settings.remain_times;
00485       }
00486       type = Mx_Reply;
00487     }
00488   }
00489 
00490 
00491   CaptureType receiveCaptureData(vector<long>& data,
00492                                  CaptureSettings& settings, long* timestamp,
00493                                  int* remain_times, int* total_times)
00494   {
00495     int line_count = 0;
00496     data.clear();
00497 
00498     string remain_string;
00499 
00500     string left_packet_data;
00501     char buffer[BufferSize];
00502 
00503     error_message_ = "no response.";
00504 
00505     CaptureType type = TypeUnknown;
00506     int timeout = FirstTimeout;
00507     int line_size = 0;
00508     while ((line_size = readline(con_, buffer, BufferSize, timeout)) > 0) {
00509       //fprintf(stderr, "%d: % 3d: %s\n", ticks(), line_count, buffer);
00510 
00511       // チェックサムの確認
00512       if (line_count != 0) {
00513         // エコーバックにはチェックサム文字列がないので、無視
00514         if (! testChecksum(buffer, line_size, data, type, line_count, timeout,
00515                            remain_string, left_packet_data)) {
00516           continue;
00517         }
00518       }
00519 
00520       if (line_count == 0) {
00521         // エコーバック
00522         LoopProcess loop_process =
00523           handleEchoback(buffer, settings, type, data, line_count, timeout,
00524                          remain_string, left_packet_data);
00525         if (loop_process == ProcessContinue) {
00526           continue;
00527 
00528         } else if (loop_process == ProcessBreak) {
00529           break;
00530         }
00531 
00532       } else if (line_count == 1) {
00533         // 応答コード
00534         handleReturnCode(buffer, settings, timeout, type, total_times);
00535 
00536       } else if (line_count == 2) {
00537         // タイムスタンプ
00538         if (timestamp) {
00539           *timestamp = decode(buffer, 4);
00540         }
00541       } else {
00542         if (line_count == 3) {
00543           // 受信データがない先頭からの領域を、ダミーデータで埋める
00544           for (int i = 0; i < settings.capture_first; ++i) {
00545             data.push_back(InvalidRange);
00546             if (type == ME) {
00547               // ME 受信のときは、強度データ分も埋める
00548               data.push_back(InvalidRange);
00549             }
00550           }
00551         }
00552         // 距離データの格納
00553         left_packet_data =
00554           addLengthData(data, string(buffer), left_packet_data,
00555                         settings.data_byte, settings.skip_lines);
00556       }
00557       ++line_count;
00558       timeout = ContinuousTimeout;
00559     }
00560 
00561     // !!! type が距離データ取得のときは、正常に受信が完了したか、を確認すべき
00562 
00563     // ME で "まとめる数" 設定以上のデータが返されるバグに対処
00564     size_t expected_n = settings.capture_last * ((type == ME) ? 2 : 1);
00565     if (expected_n < data.size()) {
00566       data.erase(data.begin() + expected_n, data.end());
00567     }
00568 
00569     if (remain_times) {
00570       *remain_times = settings.remain_times;
00571     }
00572     return type;
00573   }
00574 
00575 
00576   bool parseGdEchoback(CaptureSettings& settings, const string& line)
00577   {
00578     if (line.size() != 12) {
00579       error_message_ = "Invalid Gx packet has arrived.";
00580       return false;
00581     }
00582 
00583     settings.capture_first = substr2int(line, 2, 4);
00584     settings.capture_last = substr2int(line, 6, 4) + 1;
00585     int skip_lines = substr2int(line, 10, 2);
00586     settings.skip_lines = (skip_lines == 0) ? 1 : skip_lines;
00587     settings.data_byte = (line[1] == 'D') ? 3 : 2;
00588 
00589     return true;
00590   }
00591 
00592 
00593   bool parseMdEchoback(CaptureSettings& settings, const string& line)
00594   {
00595     if (line.size() != 15) {
00596       error_message_ = "Invalid Mx packet has arrived.";
00597       return false;
00598     }
00599 
00600     settings.capture_first = substr2int(line, 2, 4);
00601     settings.capture_last = substr2int(line, 6, 4) + 1;
00602     int skip_lines = substr2int(line, 10, 2);
00603     settings.skip_lines = (skip_lines == 0) ? 1 : skip_lines;
00604     settings.skip_frames = substr2int(line, 12, 1);
00605     settings.remain_times = substr2int(line, 13, 2);
00606     settings.data_byte = (line[1] == 'D') ? 3 : 2;
00607 
00608     if (settings.remain_times == 1) {
00609       // 最後のデータ取得で、レーザを消灯扱いにする
00610       // 本当は、次のデータ取得後にレーザは消灯されている
00611       // 1 で判定すると、取得回数が 1 のときにも正常に動作するため
00612       mx_capturing_ = false;
00613 
00614     } else {
00615       if (settings.remain_times > 0) {
00616         mx_capturing_ = true;
00617       } else if (settings.remain_times == 0) {
00618         settings.remain_times = 100;
00619       }
00620     }
00621 
00622     return true;
00623   }
00624 
00625 
00626   bool parseMeEchoback(CaptureSettings& settings, const string& line)
00627   {
00628     if (line.size() != 15) {
00629       error_message_ = "Invalid ME packet has arrived.";
00630       return false;
00631     }
00632 
00633     settings.capture_first = substr2int(line, 2, 4);
00634     settings.capture_last = substr2int(line, 6, 4) + 1;
00635     int skip_lines = substr2int(line, 10, 2);
00636     settings.skip_lines = (skip_lines == 0) ? 1 : skip_lines;
00637     settings.skip_frames = substr2int(line, 12, 1);
00638     settings.remain_times = substr2int(line, 13, 2);
00639     settings.data_byte = 3;
00640 
00641     if (settings.remain_times == 1) {
00642       mx_capturing_ = false;
00643 
00644     } else {
00645       mx_capturing_ = true;
00646     }
00647 
00648     return true;
00649   }
00650 
00651 
00652   string addLengthData(vector<long>& data,
00653                        const string& line,
00654                        const string& left_packet_data,
00655                        const size_t data_byte, const int skip_lines = 1)
00656   {
00657     if (line.empty()) {
00658       // 空行の場合、戻る
00659       return left_packet_data;
00660     }
00661 
00662     // 端数。次回に処理する分
00663     string left_byte = left_packet_data;
00664 
00665     size_t data_size = (left_byte.size() + (line.size() - 1)) / data_byte;
00666     size_t n = data_size * data_byte - left_byte.size();
00667     for (size_t i = 0; i < n; ++i) {
00668       left_byte.push_back(line[i]);
00669       if (left_byte.size() >= data_byte) {
00670         // データを距離に変換して、格納
00671         long length = decode(&left_byte[0], data_byte);
00672         for (int j = 0; j < skip_lines; ++j) {
00673           data.push_back(length);
00674         }
00675         left_byte.clear();
00676       }
00677     }
00678     left_byte += line.substr(n, (line.size() - n) - 1);
00679 
00680     return left_byte;
00681   }
00682 };
00683 
00684 
00685 ScipHandler::ScipHandler(void) : pimpl(new pImpl)
00686 {
00687 }
00688 
00689 
00690 ScipHandler::~ScipHandler(void)
00691 {
00692 }
00693 
00694 
00695 const char* ScipHandler::what(void) const
00696 {
00697   return pimpl->error_message_.c_str();
00698 }
00699 
00700 
00701 long ScipHandler::decode(const char* data, size_t size)
00702 {
00703   const char* p = data;
00704   const char* last_p = p + size;
00705 
00706   int value = 0;
00707   while (p < last_p) {
00708     value <<= 6;
00709     value &= ~0x3f;
00710     value |= *p++ - 0x30;
00711   }
00712   return value;
00713 }
00714 
00715 
00716 bool ScipHandler::checkSum(const char* buffer, int size, char actual_sum)
00717 {
00718   const char* p = buffer;
00719   const char* last_p = p + size;
00720 
00721   char expected_sum = 0x00;
00722   while (p < last_p) {
00723     expected_sum += *p++;
00724   }
00725   expected_sum = (expected_sum & 0x3f) + 0x30;
00726 
00727   return (expected_sum == actual_sum) ? true : false;
00728 }
00729 
00730 
00731 void ScipHandler::setConnection(Connection* con)
00732 {
00733   pimpl->con_ = con;
00734 }
00735 
00736 
00737 Connection* ScipHandler::connection(void)
00738 {
00739   return pimpl->con_;
00740 }
00741 
00742 
00743 bool ScipHandler::connect(const char* device, long baudrate)
00744 {
00745   return pimpl->connect(device, baudrate);
00746 }
00747 
00748 
00749 int ScipHandler::send(const char data[], int size)
00750 {
00751   if (size >= 2) {
00752     // コマンド送信後の受信前だと、レーザ点灯中の判定ができないため、
00753     // ここでレーザ点灯中の状態を判定する
00754     if ((! strncmp("MD", data, 2)) || (! strncmp("MS", data, 2)) ||
00755         (! strncmp("ME", data, 2))) {
00756       pimpl->laser_state_ = pImpl::LaserOn;
00757       pimpl->mx_capturing_ = true;
00758       pimpl->isPreCommand_QT_ = false;
00759     }
00760   }
00761   return pimpl->con_->send(data, size);
00762 }
00763 
00764 
00765 int ScipHandler::recv(char data[], int size, int timeout)
00766 {
00767   return pimpl->con_->receive(data, size, timeout);
00768 }
00769 
00770 
00771 bool ScipHandler::loadParameter(RangeSensorParameter& parameters)
00772 {
00773   return pimpl->loadParameter(parameters);
00774 }
00775 
00776 
00777 bool ScipHandler::versionLines(vector<string>& lines)
00778 {
00779   int return_code = -1;
00780   char expected_response[] = { 0, -1 };
00781   if (! pimpl->response(return_code, "VV\n", expected_response, &lines)) {
00782     return false;
00783   }
00784   return true;
00785 }
00786 
00787 
00788 bool ScipHandler::setRawTimestampMode(bool on)
00789 {
00790   char send_command[] = "TMx\n";
00791   send_command[2] = (on) ? '0' : '2';
00792 
00793   // TM0 or TM2 の送信
00794   int return_code = -1;
00795   char expected_response[] = { 0, -1 };
00796   if (! pimpl->response(return_code, send_command, expected_response)) {
00797     pimpl->error_message_ = (on) ? "TM0 fail." : "TM2 fail.";
00798     return false;
00799   }
00800 
00801   // TM1, TM2 の応答が正常ならば、レーザは消灯しているはず
00802   pimpl->laser_state_ = pImpl::LaserOff;
00803 
00804   return true;
00805 }
00806 
00807 
00808 bool ScipHandler::rawTimestamp(int* timestamp)
00809 {
00810   // TM1 の値を返す
00811   int return_code = -1;
00812   char expected_response[] = { 0, -1 };
00813   vector<string> lines;
00814   if (! pimpl->response(return_code, "TM1\n", expected_response, &lines)) {
00815     pimpl->error_message_ = "TM1 fail.";
00816     return false;
00817   }
00818 
00819   if ((lines.size() != 1) || (lines[0].size() != 5)) {
00820     pimpl->error_message_ = "response mismatch.";
00821     return false;
00822   }
00823 
00824   *timestamp = decode(lines[0].c_str(), 4);
00825   return true;
00826 }
00827 
00828 
00829 bool ScipHandler::setLaserOutput(bool on, bool force)
00830 {
00831   return pimpl->setLaserOutput(on, force);
00832 }
00833 
00834 
00835 CaptureType ScipHandler::receiveCaptureData(vector<long>& data,
00836                                             CaptureSettings& settings,
00837                                             long* timestamp, int* remain_times,
00838                                             int* total_times)
00839 {
00840   return pimpl->receiveCaptureData(data, settings,
00841                                    timestamp, remain_times, total_times);
00842 }