00001
00010 #include "math_utils.h"
00011 #include "urg_ctrl.h"
00012 #include "scip_handler.h"
00013 #include "urg_errno.h"
00014 #include "serial_ctrl.h"
00015 #include "serial_utils.h"
00016 #include "serial_errno.h"
00017 #include "urg_ticks.h"
00018 #include "urg_delay.h"
00019 #include <string.h>
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022
00023 #if defined(WINDOWS_OS)
00024 #define snprintf _snprintf
00025 #endif
00026
00027
00028 enum {
00029 ScipTimeout = 1000,
00030 EachTimeout = 100 * 2,
00032 InvalidRange = -1,
00033 };
00034
00035
00036 void urg_initialize(urg_t *urg)
00037 {
00038 serial_initialize(&urg->serial_);
00039 urg->errno_ = UrgNoError;
00040 urg->last_timestamp_ = 0;
00041 }
00042
00043
00044 static int urg_firstConnection(urg_t *urg, long baudrate)
00045 {
00046 long try_baudrates[] = { 115200, 19200, 38400 };
00047 int try_size = sizeof(try_baudrates) / sizeof(try_baudrates[0]);
00048 long pre_ticks;
00049 int reply = 0;
00050 int ret;
00051 int i;
00052
00053
00054
00055 for (i = 1; i < try_size; ++i) {
00056 if (baudrate == try_baudrates[i]) {
00057 long swap_tmp = try_baudrates[i];
00058 try_baudrates[i] = try_baudrates[0];
00059 try_baudrates[0] = swap_tmp;
00060 break;
00061 }
00062 }
00063
00064
00065 for (i = 0; i < try_size; ++i) {
00066
00067
00068 ret = serial_setBaudrate(&urg->serial_, try_baudrates[i]);
00069 if (ret < 0) {
00070 return ret;
00071 }
00072
00073 serial_clear(&urg->serial_);
00074
00075
00076 ret = scip_qt(&urg->serial_, &reply, ScipWaitReply);
00077 if (ret == UrgSerialRecvFail) {
00078
00079 continue;
00080 }
00081
00082 if ((ret == UrgMismatchResponse) && (reply != -0xE)) {
00083
00084
00085
00086 serial_clear(&urg->serial_);
00087 serial_skip(&urg->serial_, ScipTimeout, EachTimeout);
00088 reply = 0x00;
00089 }
00090
00091
00092
00093 if (reply != 0x00) {
00094 if ((ret = scip_scip20(&urg->serial_)) < 0) {
00095
00096 continue;
00097 }
00098 if (ret == 12) {
00099
00100 return UrgScip10;
00101 }
00102 }
00103
00104
00105 if (baudrate == try_baudrates[i]) {
00106 return 0;
00107 }
00108
00109
00110 pre_ticks = urg_ticks();
00111 if (scip_ss(&urg->serial_, baudrate) < 0) {
00112 return UrgSsFail;
00113
00114 } else {
00115
00116
00117 long reply_msec = urg_ticks() - pre_ticks;
00118 urg_delay((reply_msec * 4 / 3) + 10);
00119
00120 return serial_setBaudrate(&urg->serial_, baudrate);
00121 }
00122 }
00123
00124 return UrgAdjustBaudrateFail;
00125 }
00126
00127
00128 static void urg_t_initialize(urg_t *urg)
00129 {
00130 urg->parameters_.area_max_ = 0;
00131 urg->parameters_.scan_rpm_ = 0;
00132 urg->parameters_.sensor_type[0] = '\0';
00133 urg->remain_byte_ = 0;
00134 }
00135
00136
00137
00138 int urg_connect(urg_t *urg, const char *device, long baudrate)
00139 {
00140 int ret;
00141 urg_t_initialize(urg);
00142
00143
00144 ret = serial_connect(&urg->serial_, device, baudrate);
00145 if (ret != 0) {
00146 urg->errno_ = UrgSerialConnectionFail;
00147 return ret;
00148 }
00149
00150 urg_delay(0);
00151
00152
00153 ret = urg_firstConnection(urg, baudrate);
00154 if (ret < 0) {
00155 urg->errno_ = ret;
00156 serial_disconnect(&urg->serial_);
00157 return ret;
00158 }
00159
00160
00161 ret = scip_pp(&urg->serial_, &urg->parameters_);
00162 if (ret < 0) {
00163 urg->errno_ = ret;
00164 serial_disconnect(&urg->serial_);
00165 return ret;
00166 }
00167 urg->skip_lines_ = 1;
00168 urg->skip_frames_ = 0;
00169 urg->capture_times_ = 0;
00170 urg->is_laser_on_ = UrgLaserUnknown;
00171 urg->remain_times_ = 0;
00172
00173 urg->errno_ = UrgNoError;
00174 return 0;
00175 }
00176
00177
00178 void urg_disconnect(urg_t *urg)
00179 {
00180
00181 urg_laserOff(urg);
00182 serial_skip(&urg->serial_, ScipTimeout, EachTimeout);
00183
00184
00185 serial_disconnect(&urg->serial_);
00186 }
00187
00188
00189 int urg_isConnected(const urg_t *urg)
00190 {
00191
00192 return serial_isConnected(&urg->serial_);
00193 }
00194
00195
00196 const char *urg_error(const urg_t *urg)
00197 {
00198 return urg_strerror(urg->errno_);
00199 }
00200
00201
00202 int urg_versionLines(urg_t *urg, char* lines[], int lines_max)
00203 {
00204 if (! urg_isConnected(urg)) {
00205 return -1;
00206 }
00207 return scip_vv(&urg->serial_, lines, lines_max);
00208 }
00209
00210
00211
00212 int urg_parameters(urg_t *urg, urg_parameter_t* parameters)
00213 {
00214 if (urg_isConnected(urg)) {
00215 *parameters = urg->parameters_;
00216 } else {
00217 scip_pp(&urg->serial_, &urg->parameters_);
00218 if (parameters) {
00219 *parameters = urg->parameters_;
00220 }
00221 }
00222
00223 urg->errno_ = UrgNoError;
00224 return 0;
00225 }
00226
00227
00228 const char* urg_model(const urg_t *urg)
00229 {
00230 return urg->parameters_.sensor_type;
00231 }
00232
00233
00234 int urg_dataMax(const urg_t *urg)
00235 {
00236 return urg->parameters_.area_max_ + 1;
00237 }
00238
00239
00240 int urg_scanMsec(const urg_t *urg)
00241 {
00242 int scan_rpm = urg->parameters_.scan_rpm_;
00243 return (scan_rpm <= 0) ? 1 : (1000 * 60 / scan_rpm);
00244 }
00245
00246
00247 long urg_maxDistance(const urg_t *urg)
00248 {
00249 return urg->parameters_.distance_max_;
00250 }
00251
00252
00253 long urg_minDistance(const urg_t *urg)
00254 {
00255 return urg->parameters_.distance_min_;
00256 }
00257
00258
00259 int urg_setSkipLines(urg_t *urg, int lines)
00260 {
00261
00262 if (lines == 0) {
00263 lines = 1;
00264 }
00265 if ((lines < 0) || (lines > 99)) {
00266 return -1;
00267 }
00268
00269 urg->skip_lines_ = lines;
00270 return 0;
00271 }
00272
00273
00274 int urg_setSkipFrames(urg_t *urg, int frames)
00275 {
00276
00277 if ((frames < 0) || (frames > 9)) {
00278 return -1;
00279 }
00280
00281 urg->skip_frames_ = frames;
00282 return 0;
00283 }
00284
00285
00286 int urg_setCaptureTimes(urg_t *urg, int times)
00287 {
00288
00289 if ((times < 0) || (times >= 100)) {
00290 urg->capture_times_ = 0;
00291 } else {
00292 urg->capture_times_ = times;
00293 }
00294
00295 return 0;
00296 }
00297
00298
00299 int urg_remainCaptureTimes(const urg_t *urg)
00300 {
00301 if (urg->capture_times_ == 0) {
00302
00303 return 100;
00304
00305 } else {
00306 return urg->remain_times_;
00307 }
00308 }
00309
00310
00311 int urg_requestData(urg_t *urg,
00312 urg_request_type request_type,
00313 int first_index,
00314 int last_index)
00315 {
00316 char buffer[] = "MDsssseeeellstt\n";
00317
00318 if (first_index == URG_FIRST) {
00319 first_index = urg->parameters_.area_min_;
00320 }
00321 if (last_index == URG_LAST) {
00322 last_index = urg->parameters_.area_max_;
00323 }
00324
00325 if ((request_type == URG_GD) || (request_type == URG_GS) ||
00326 (request_type == URG_GD_INTENSITY)) {
00327
00328
00329 snprintf(buffer, 14, "G%c%04d%04d%02d\n",
00330 (((request_type == URG_GD) ||
00331 (request_type == URG_GD_INTENSITY)) ? 'D' : 'S'),
00332 first_index, last_index,
00333 urg->skip_lines_);
00334
00335
00336 if (urg->is_laser_on_ != UrgLaserOn) {
00337 int ret = urg_laserOn(urg);
00338 if (ret < 0) {
00339 return ret;
00340 }
00341 }
00342
00343 } else if ((request_type == URG_MD) || (request_type == URG_MS) ||
00344 (request_type == URG_MD_INTENSITY)) {
00345 char type = (request_type == URG_MS) ? 'S' : 'D';
00346
00347
00348 snprintf(buffer, 17, "M%c%04d%04d%02d%d%02d\n",
00349 type,
00350 first_index, last_index,
00351 urg->skip_lines_,
00352 urg->skip_frames_,
00353 urg->capture_times_);
00354 urg->remain_times_ = urg->capture_times_;
00355
00356 } else {
00357 urg->errno_ = UrgInvalidArgs;;
00358 return urg->errno_;
00359 }
00360
00361 if ((request_type == URG_GD_INTENSITY) ||
00362 (request_type == URG_MD_INTENSITY)) {
00363 if (! strcmp("UTM-30LX", urg->parameters_.sensor_type)) {
00364 if (request_type == URG_GD_INTENSITY) {
00365 urg->errno_ = UtmNoGDIntensity;
00366 return urg->errno_;
00367 }
00368
00369 buffer[0] = 'M';
00370 buffer[1] = 'E';
00371
00372
00373 buffer[10] = '0';
00374 buffer[11] = '2';
00375
00376 } else {
00377
00378 buffer[10] = 'F';
00379 buffer[11] = 'F';
00380 }
00381 }
00382
00383 return scip_send(&urg->serial_, buffer);
00384 }
00385
00386
00387
00388 static long decode(const char* data, int data_byte)
00389 {
00390 const char* p = data;
00391 const char* last_p = p + data_byte;
00392
00393 int value = 0;
00394 while (p < last_p) {
00395 value <<= 6;
00396 value &= ~0x3f;
00397 value |= *p++ - 0x30;
00398 }
00399 return value;
00400 }
00401
00402
00403 static int convertRawData(long data[], int data_max,
00404 const char* buffer, int buffer_size, int filled,
00405 int data_bytes, int skip_lines,
00406 int store_last, urg_t* urg)
00407 {
00408 int n;
00409 int i;
00410 int j;
00411 int remain_byte = urg->remain_byte_;
00412 long length;
00413 long *data_p = data + filled;
00414
00415 if (data_max > store_last) {
00416 data_max = store_last;
00417 }
00418
00419 if (filled == 0) {
00420
00421
00422 remain_byte = 0;
00423 }
00424
00425 if (buffer_size <= 0) {
00426 return filled;
00427 }
00428
00429
00430 if (remain_byte > 0) {
00431 memcpy(&urg->remain_data_[remain_byte], buffer, data_bytes - remain_byte);
00432 n = skip_lines;
00433 if ((filled + n) > data_max) {
00434 n = data_max - filled;
00435 }
00436 length = decode(urg->remain_data_, data_bytes);
00437 for (j = 0; j < n; ++j) {
00438 *data_p++ = length;
00439 }
00440 filled += n;
00441 }
00442
00443
00444 n = buffer_size - data_bytes;
00445 for (i = (data_bytes - remain_byte) % data_bytes; i <= n; i += data_bytes) {
00446 length = decode(&buffer[i], data_bytes);
00447 for (j = 0; j < skip_lines; ++j) {
00448 if (filled >= data_max) {
00449 return data_max;
00450 }
00451 *data_p++ = length;
00452 ++filled;
00453 }
00454 }
00455
00456
00457 urg->remain_byte_ = buffer_size - i;
00458 memcpy(urg->remain_data_, &buffer[i], urg->remain_byte_);
00459
00460 return filled;
00461 }
00462
00463
00464 static int checkSum(const char buffer[], int size, char actual_sum)
00465 {
00466 const char *p = buffer;
00467 const char *last_p = p + size;
00468 char expected_sum = 0x00;
00469
00470 while (p < last_p) {
00471 expected_sum += *p++;
00472 }
00473 expected_sum = (expected_sum & 0x3f) + 0x30;
00474
00475 return (expected_sum == actual_sum) ? 0 : -1;
00476 }
00477
00478
00479 static int atoi_substr(const char *str, size_t len)
00480 {
00481 char buffer[13];
00482
00483 strncpy(buffer, str, len);
00484 buffer[len] = '\0';
00485
00486 return atoi(buffer);
00487 }
00488
00489
00490 static int internal_receiveData(urg_t *urg, long data[], int data_max,
00491 int store_first, int store_last,
00492 int skip_lines)
00493 {
00494 enum {
00495 EchoBack = 0,
00496 ReplyCode,
00497 Timestamp,
00498
00499 False = 0,
00500 True = 1,
00501
00502 MD_MS_Length = 15,
00503 GD_GS_Length = 12,
00504 };
00505
00506 int lines = 0;
00507 char buffer[UrgLineWidth];
00508 int filled = 0;
00509 int is_echoback = False;
00510 int n;
00511
00512 char current_type[] = "xx";
00513 int current_first = -1;
00514
00515
00516
00517
00518 int current_data_bytes = 3;
00519 int dummy_last;
00520 int timeout = ScipTimeout;
00521
00522
00523 urg->last_timestamp_ = UrgInvalidTimestamp;
00524
00525 urg->errno_ = UrgNoResponse;
00526
00527 while (1) {
00528 n = serial_getLine(&urg->serial_, buffer, ScipLineWidth, timeout);
00529
00530 if (n <= 0) {
00531 if (is_echoback) {
00532 is_echoback = False;
00533 lines = 0;
00534 continue;
00535 }
00536 break;
00537 }
00538
00539 if (lines > 0) {
00540
00541 if (checkSum(buffer, n - 1, buffer[n - 1]) < 0) {
00542 urg->errno_ = UrgInvalidResponse;
00543 lines = 0;
00544 filled = 0;
00545 is_echoback = False;
00546 continue;
00547 }
00548 }
00549
00550 if (lines > Timestamp) {
00551
00552 filled = convertRawData(data, data_max, buffer, n - 1, filled,
00553 current_data_bytes, skip_lines,
00554 store_last, urg);
00555
00556 } else if (lines == EchoBack) {
00557
00558 if ((n != GD_GS_Length) && (n != MD_MS_Length)) {
00559
00560 urg->errno_ = UrgInvalidResponse;
00561 lines = 0;
00562 filled = 0;
00563 is_echoback = False;
00564 continue;
00565 }
00566
00567 current_type[0] = buffer[0];
00568 current_type[1] = buffer[1];
00569
00570
00571 current_first = atoi_substr(&buffer[2], 4);
00572
00573
00574
00575 if ((current_first - store_first) >= data_max) {
00576
00577 return 0;
00578 }
00579
00580
00581 dummy_last = current_first - store_first;
00582 for (filled = 0; filled < dummy_last; ++filled) {
00583 data[filled] = InvalidRange;
00584 }
00585
00586 if (n == GD_GS_Length) {
00587
00588
00589 urg->remain_times_ = 0;
00590
00591 } else {
00592
00593
00594
00595
00596 urg->remain_times_ = atoi(&buffer[13]);
00597 }
00598 current_data_bytes = (current_type[1] == 'S') ? 2 : 3;
00599
00600 } else if (lines == ReplyCode) {
00601 if (! strncmp(buffer, "10", 2)) {
00602 urg->is_laser_on_ = UrgLaserOff;
00603 }
00604
00605
00606
00607 if (! strncmp(buffer, "0B", 2)) {
00608 serial_skip(&urg->serial_, ScipTimeout, timeout);
00609 }
00610
00611
00612
00613 if (current_type[0] == 'M' && (! strncmp(buffer, "00", 2))) {
00614 is_echoback = True;
00615 }
00616
00617 } else if (lines == Timestamp) {
00618 urg->last_timestamp_ = decode(buffer, 4);
00619 }
00620
00621 ++lines;
00622 timeout = EachTimeout;
00623 }
00624
00625 if (filled <= 0) {
00626 return urg->errno_;
00627 } else {
00628 #if 0
00629
00630 int last_index = data_max;
00631 if (urg->parameters_.area_max_ < last_index) {
00632 last_index = urg->parameters_.area_max_;
00633 }
00634 for (; filled <= last_index; ++filled) {
00635 data[filled] = InvalidRagne;
00636 }
00637 #endif
00638
00639 return filled;
00640 }
00641 }
00642
00643
00644 int urg_receiveData(urg_t *urg, long data[], int data_max)
00645 {
00646 if (! urg_isConnected(urg)) {
00647 return -1;
00648 }
00649 return internal_receiveData(urg, data, data_max,
00650 0, data_max, urg->skip_lines_);
00651 }
00652
00653
00654 int urg_receiveDataWithIntensity(urg_t *urg, long data[], int data_max,
00655 long intensity[])
00656 {
00657 int i;
00658 int n;
00659
00660 n = internal_receiveData(urg, data, data_max,
00661 0, data_max, urg->skip_lines_);
00662
00663 for (i = 0; i < n; i += 2) {
00664 long length = data[i];
00665
00666 if ((i + 1) < data_max) {
00667 long intensity_value = data[i + 1];
00668 intensity[i] = intensity_value;
00669 intensity[i + 1] = intensity_value;
00670 data[i + 1] = length;
00671 }
00672 }
00673 return n;
00674 }
00675
00676
00677 int urg_receivePartialData(urg_t *urg, long data[], int data_max,
00678 int first_index, int last_index)
00679 {
00680 return internal_receiveData(urg, data, data_max, first_index, last_index, 1);
00681 }
00682
00683
00684 long urg_recentTimestamp(const urg_t *urg)
00685 {
00686
00687 return urg->last_timestamp_;
00688 }
00689
00690
00691 double urg_index2rad(const urg_t *urg, int index)
00692 {
00693 double radian = (2.0 * M_PI) *
00694 (index - urg->parameters_.area_front_) / urg->parameters_.area_total_;
00695
00696 return radian;
00697 }
00698
00699
00700 int urg_index2deg(const urg_t *urg, int index)
00701 {
00702 int degree = (int)floor((urg_index2rad(urg, index) * 180 / M_PI) + 0.5);
00703
00704 return degree;
00705 }
00706
00707
00708 int urg_rad2index(const urg_t *urg, double radian)
00709 {
00710 int index =
00711 (int)floor((((radian * urg->parameters_.area_total_) / (2.0*M_PI))
00712 + urg->parameters_.area_front_) + 0.5);
00713
00714 if (index < 0) {
00715 index = 0;
00716 } else if (index > urg->parameters_.area_max_) {
00717 index = urg->parameters_.area_max_;
00718 }
00719 return index;
00720 }
00721
00722
00723 int urg_deg2index(const urg_t *urg, int degree)
00724 {
00725 return urg_rad2index(urg, M_PI * degree / 180.0);
00726 }
00727
00728
00729 int urg_laserOn(urg_t *urg)
00730 {
00731
00732 int expected_ret[] = { 0, 2, -1 };
00733 int send_n = scip_send(&urg->serial_, "BM\n");
00734 if (send_n != 3) {
00735
00736 return SerialSendFail;
00737 }
00738 if (scip_recv(&urg->serial_, "BM", NULL, expected_ret, ScipTimeout) == 0) {
00739 urg->is_laser_on_ = UrgLaserOn;
00740 }
00741
00742 return 0;
00743 }
00744
00745
00746 int urg_laserOff(urg_t *urg)
00747 {
00748 return scip_qt(&urg->serial_, NULL, ScipWaitReply);
00749 }
00750
00751
00752 int urg_reboot(urg_t *urg)
00753 {
00754 int expected_ret[][2] = {
00755 { 1, -1 },
00756 { 0, -1 },
00757 };
00758 int send_n;
00759 int recv_n;
00760 int i;
00761
00762 urg_laserOff(urg);
00763
00764
00765 for (i = 0; i < 2; ++i) {
00766 send_n = scip_send(&urg->serial_, "RB\n");
00767 if (send_n != 3) {
00768 return SerialSendFail;
00769 }
00770
00771 recv_n = scip_recv(&urg->serial_, "RB", NULL,
00772 expected_ret[i], ScipTimeout);
00773 if (recv_n < 0) {
00774 return recv_n;
00775 }
00776 }
00777
00778
00779 urg_disconnect(urg);
00780
00781 return 0;
00782 }
00783
00784
00785 int urg_reset(urg_t *urg)
00786 {
00787 return urg_reboot(urg);
00788 }
00789
00790
00791 int urg_enableTimestampMode(urg_t *urg)
00792 {
00793
00794 int expected_ret[] = { 0, 2, -1 };
00795 int send_n = scip_send(&urg->serial_, "TM0\n");
00796 if (send_n != 4) {
00797 return SerialSendFail;
00798 }
00799 return scip_recv(&urg->serial_, "TM", NULL, expected_ret, ScipTimeout);
00800 }
00801
00802
00803 int urg_disableTimestampMode(urg_t *urg)
00804 {
00805
00806 int expected_ret[] = { 0, 3, -1 };
00807 int send_n = scip_send(&urg->serial_, "TM2\n");
00808 if (send_n != 4) {
00809 return SerialSendFail;
00810 }
00811 return scip_recv(&urg->serial_, "TM", NULL, expected_ret, ScipTimeout);
00812 }
00813
00814
00815 long urg_currentTimestamp(urg_t *urg)
00816 {
00817 char buffer[ScipLineWidth];
00818 long timestamp = -1;
00819 int ret = 0;
00820 int n;
00821
00822
00823 int expected_ret[] = { 0, -1 };
00824 int send_n = scip_send(&urg->serial_, "TM1\n");
00825 if (send_n != 4) {
00826 return SerialSendFail;
00827 }
00828 ret = scip_recv(&urg->serial_, "TM", NULL, expected_ret, ScipTimeout);
00829 if (ret != 0) {
00830 return ret;
00831 }
00832
00833
00834 n = serial_getLine(&urg->serial_, buffer, ScipLineWidth, ScipTimeout);
00835 if (n == 5) {
00836 timestamp = decode(buffer, 4);
00837 }
00838
00839
00840 n = serial_recv(&urg->serial_, buffer, 1, ScipTimeout);
00841 if (! serial_isLF(buffer[0])) {
00842 serial_ungetc(&urg->serial_, buffer[0]);
00843 }
00844
00845 return timestamp;
00846 }