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,
00056 ContinuousTimeout = 100,
00057 FirstTimeout = 1000,
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
00122 int return_code = -1;
00123 char qt_expected_response[] = { 0, -1 };
00124
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
00136 con_->clear();
00137 skip(con_, ContinuousTimeout);
00138 return changeBothBaudrate(baudrate);
00139
00140 } else if (return_code == Scip11Response) {
00141
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
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
00170 if (con_->baudrate() == baudrate) {
00171 return true;
00172 }
00173
00174
00175 int pre_ticks = ticks();
00176 if (! changeBaudrate(baudrate)) {
00177 return false;
00178 }
00179
00180
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
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
00201 char send_buffer[] = "SSxxxxxx\n";
00202 snprintf(send_buffer, 10, "SS%06ld\n", baudrate);
00203 int return_code = -1;
00204
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
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
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
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
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
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
00321 buffer[1] = '\0';
00322 return_code = -strtol(buffer, NULL, 16);
00323 }
00324
00325
00326
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
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
00369 if (! mx_capturing_) {
00370
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
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
00400
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
00449
00450
00451 clearReceived(data, type, line_count, timeout,
00452 remain_string, left_packet_data);
00453
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
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
00475
00476 if (! strncmp(buffer, "0B", 2)) {
00477 skip(con_, TotalTimeout, timeout);
00478 }
00479
00480
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
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
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
00562
00563
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
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
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
00802 pimpl->laser_state_ = pImpl::LaserOff;
00803
00804 return true;
00805 }
00806
00807
00808 bool ScipHandler::rawTimestamp(int* timestamp)
00809 {
00810
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 }