00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "sdkcommon.h"
00036 #include "hal/abs_rxtx.h"
00037 #include "hal/thread.h"
00038 #include "hal/locker.h"
00039 #include "hal/event.h"
00040 #include "rplidar_driver_serial.h"
00041
00042 #ifndef min
00043 #define min(a,b) (((a) < (b)) ? (a) : (b))
00044 #endif
00045
00046 namespace rp { namespace standalone{ namespace rplidar {
00047
00048
00049
00050 RPlidarDriver * RPlidarDriver::CreateDriver(_u32 drivertype)
00051 {
00052 switch (drivertype) {
00053 case DRIVER_TYPE_SERIALPORT:
00054 return new RPlidarDriverSerialImpl();
00055 default:
00056 return NULL;
00057 }
00058 }
00059
00060
00061 void RPlidarDriver::DisposeDriver(RPlidarDriver * drv)
00062 {
00063 delete drv;
00064 }
00065
00066
00067
00068
00069
00070 RPlidarDriverSerialImpl::RPlidarDriverSerialImpl()
00071 : _isConnected(false)
00072 , _isScanning(false)
00073 , _isSupportingMotorCtrl(false)
00074 {
00075 _rxtx = rp::hal::serial_rxtx::CreateRxTx();
00076 _cached_scan_node_count = 0;
00077 _cached_sampleduration_std = LEGACY_SAMPLE_DURATION;
00078 _cached_sampleduration_express = LEGACY_SAMPLE_DURATION;
00079 }
00080
00081 RPlidarDriverSerialImpl::~RPlidarDriverSerialImpl()
00082 {
00083
00084 disconnect();
00085
00086 rp::hal::serial_rxtx::ReleaseRxTx(_rxtx);
00087 }
00088
00089 u_result RPlidarDriverSerialImpl::connect(const char * port_path, _u32 baudrate, _u32 flag)
00090 {
00091 if (isConnected()) return RESULT_ALREADY_DONE;
00092
00093 if (!_rxtx) return RESULT_INSUFFICIENT_MEMORY;
00094
00095 {
00096 rp::hal::AutoLocker l(_lock);
00097
00098
00099 if (!_rxtx->bind(port_path, baudrate) || !_rxtx->open()) {
00100 return RESULT_INVALID_DATA;
00101 }
00102
00103 _rxtx->flush(0);
00104 }
00105
00106 _isConnected = true;
00107
00108 checkMotorCtrlSupport(_isSupportingMotorCtrl);
00109 stopMotor();
00110
00111 return RESULT_OK;
00112 }
00113
00114 void RPlidarDriverSerialImpl::disconnect()
00115 {
00116 if (!_isConnected) return ;
00117 stop();
00118 _rxtx->close();
00119 }
00120
00121 bool RPlidarDriverSerialImpl::isConnected()
00122 {
00123 return _isConnected;
00124 }
00125
00126
00127 u_result RPlidarDriverSerialImpl::reset(_u32 timeout)
00128 {
00129 u_result ans;
00130
00131 {
00132 rp::hal::AutoLocker l(_lock);
00133
00134 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_RESET))) {
00135 return ans;
00136 }
00137 }
00138 return RESULT_OK;
00139 }
00140
00141 u_result RPlidarDriverSerialImpl::getHealth(rplidar_response_device_health_t & healthinfo, _u32 timeout)
00142 {
00143 u_result ans;
00144
00145 if (!isConnected()) return RESULT_OPERATION_FAIL;
00146
00147 _disableDataGrabbing();
00148
00149 {
00150 rp::hal::AutoLocker l(_lock);
00151
00152 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_DEVICE_HEALTH))) {
00153 return ans;
00154 }
00155
00156 rplidar_ans_header_t response_header;
00157 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00158 return ans;
00159 }
00160
00161
00162 if (response_header.type != RPLIDAR_ANS_TYPE_DEVHEALTH) {
00163 return RESULT_INVALID_DATA;
00164 }
00165
00166 _u32 header_size = (response_header.size_q30_subtype & RPLIDAR_ANS_HEADER_SIZE_MASK);
00167 if ( header_size < sizeof(rplidar_response_device_health_t)) {
00168 return RESULT_INVALID_DATA;
00169 }
00170
00171 if (_rxtx->waitfordata(header_size, timeout) != rp::hal::serial_rxtx::ANS_OK) {
00172 return RESULT_OPERATION_TIMEOUT;
00173 }
00174 _rxtx->recvdata(reinterpret_cast<_u8 *>(&healthinfo), sizeof(healthinfo));
00175 }
00176 return RESULT_OK;
00177 }
00178
00179 u_result RPlidarDriverSerialImpl::getDeviceInfo(rplidar_response_device_info_t & info, _u32 timeout)
00180 {
00181 u_result ans;
00182
00183 if (!isConnected()) return RESULT_OPERATION_FAIL;
00184
00185 _disableDataGrabbing();
00186
00187 {
00188 rp::hal::AutoLocker l(_lock);
00189
00190 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_DEVICE_INFO))) {
00191 return ans;
00192 }
00193
00194 rplidar_ans_header_t response_header;
00195 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00196 return ans;
00197 }
00198
00199
00200 if (response_header.type != RPLIDAR_ANS_TYPE_DEVINFO) {
00201 return RESULT_INVALID_DATA;
00202 }
00203
00204 _u32 header_size = (response_header.size_q30_subtype & RPLIDAR_ANS_HEADER_SIZE_MASK);
00205 if (header_size < sizeof(rplidar_response_device_info_t)) {
00206 return RESULT_INVALID_DATA;
00207 }
00208
00209 if (_rxtx->waitfordata(header_size, timeout) != rp::hal::serial_rxtx::ANS_OK) {
00210 return RESULT_OPERATION_TIMEOUT;
00211 }
00212
00213 _rxtx->recvdata(reinterpret_cast<_u8 *>(&info), sizeof(info));
00214 }
00215 return RESULT_OK;
00216 }
00217
00218 u_result RPlidarDriverSerialImpl::getFrequency(bool inExpressMode, size_t count, float & frequency, bool & is4kmode)
00219 {
00220 _u16 sample_duration = inExpressMode?_cached_sampleduration_express:_cached_sampleduration_std;
00221 frequency = 1000000.0f/(count * sample_duration);
00222
00223 if (sample_duration <= 277) {
00224 is4kmode = true;
00225 } else {
00226 is4kmode = false;
00227 }
00228
00229 return RESULT_OK;
00230 }
00231
00232 u_result RPlidarDriverSerialImpl::startScanNormal(bool force, _u32 timeout)
00233 {
00234 u_result ans;
00235 if (!isConnected()) return RESULT_OPERATION_FAIL;
00236 if (_isScanning) return RESULT_ALREADY_DONE;
00237
00238 stop();
00239
00240 {
00241 rp::hal::AutoLocker l(_lock);
00242
00243 if (IS_FAIL(ans = _sendCommand(force?RPLIDAR_CMD_FORCE_SCAN:RPLIDAR_CMD_SCAN))) {
00244 return ans;
00245 }
00246
00247
00248 rplidar_ans_header_t response_header;
00249 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00250 return ans;
00251 }
00252
00253
00254 if (response_header.type != RPLIDAR_ANS_TYPE_MEASUREMENT) {
00255 return RESULT_INVALID_DATA;
00256 }
00257
00258 _u32 header_size = (response_header.size_q30_subtype & RPLIDAR_ANS_HEADER_SIZE_MASK);
00259 if (header_size < sizeof(rplidar_response_measurement_node_t)) {
00260 return RESULT_INVALID_DATA;
00261 }
00262
00263 _isScanning = true;
00264 _cachethread = CLASS_THREAD(RPlidarDriverSerialImpl, _cacheScanData);
00265 if (_cachethread.getHandle() == 0) {
00266 return RESULT_OPERATION_FAIL;
00267 }
00268 }
00269 return RESULT_OK;
00270 }
00271
00272 u_result RPlidarDriverSerialImpl::checkExpressScanSupported(bool & support, _u32 timeout)
00273 {
00274 rplidar_response_device_info_t devinfo;
00275
00276 support = false;
00277 u_result ans = getDeviceInfo(devinfo, timeout);
00278
00279 if (IS_FAIL(ans)) return ans;
00280
00281 if (devinfo.firmware_version >= ((0x1<<8) | 17)) {
00282 support = true;
00283 rplidar_response_sample_rate_t sample_rate;
00284 getSampleDuration_uS(sample_rate);
00285 _cached_sampleduration_express = sample_rate.express_sample_duration_us;
00286 _cached_sampleduration_std = sample_rate.std_sample_duration_us;
00287 }
00288
00289 return RESULT_OK;
00290 }
00291
00292 u_result RPlidarDriverSerialImpl::startScanExpress(bool fixedAngle, _u32 timeout)
00293 {
00294 u_result ans;
00295 if (!isConnected()) return RESULT_OPERATION_FAIL;
00296 if (_isScanning) return RESULT_ALREADY_DONE;
00297
00298 stop();
00299
00300 {
00301 rp::hal::AutoLocker l(_lock);
00302
00303 rplidar_payload_express_scan_t scanReq;
00304 scanReq.working_mode = (fixedAngle?RPLIDAR_EXPRESS_SCAN_MODE_FIXANGLE:RPLIDAR_EXPRESS_SCAN_MODE_NORMAL);
00305 scanReq.reserved = 0;
00306
00307 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_EXPRESS_SCAN,&scanReq, sizeof(scanReq)))) {
00308 return ans;
00309 }
00310
00311
00312 rplidar_ans_header_t response_header;
00313 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00314 return ans;
00315 }
00316
00317
00318 if (response_header.type != RPLIDAR_ANS_TYPE_MEASUREMENT_CAPSULED) {
00319 return RESULT_INVALID_DATA;
00320 }
00321
00322 _u32 header_size = (response_header.size_q30_subtype & RPLIDAR_ANS_HEADER_SIZE_MASK);
00323 if (header_size < sizeof(rplidar_response_capsule_measurement_nodes_t)) {
00324 return RESULT_INVALID_DATA;
00325 }
00326
00327 _isScanning = true;
00328 _cachethread = CLASS_THREAD(RPlidarDriverSerialImpl, _cacheCapsuledScanData);
00329 if (_cachethread.getHandle() == 0) {
00330 return RESULT_OPERATION_FAIL;
00331 }
00332 }
00333 return RESULT_OK;
00334 }
00335
00336
00337 u_result RPlidarDriverSerialImpl::startScan(bool force, bool autoExpressMode)
00338 {
00339 bool isExpressModeSupported;
00340 u_result ans;
00341
00342 if (autoExpressMode) {
00343 ans = checkExpressScanSupported(isExpressModeSupported);
00344
00345 if (IS_FAIL(ans)) return ans;
00346
00347 if (isExpressModeSupported) {
00348 return startScanExpress(false);
00349 }
00350 }
00351
00352 return startScanNormal(force);
00353 }
00354
00355 u_result RPlidarDriverSerialImpl::stop(_u32 timeout)
00356 {
00357 u_result ans;
00358 _disableDataGrabbing();
00359
00360 {
00361 rp::hal::AutoLocker l(_lock);
00362
00363 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_STOP))) {
00364 return ans;
00365 }
00366 }
00367
00368 return RESULT_OK;
00369 }
00370
00371 u_result RPlidarDriverSerialImpl::_cacheScanData()
00372 {
00373 rplidar_response_measurement_node_t local_buf[128];
00374 size_t count = 128;
00375 rplidar_response_measurement_node_t local_scan[MAX_SCAN_NODES];
00376 size_t scan_count = 0;
00377 u_result ans;
00378 memset(local_scan, 0, sizeof(local_scan));
00379
00380 _waitScanData(local_buf, count);
00381
00382 while(_isScanning)
00383 {
00384 if (IS_FAIL(ans=_waitScanData(local_buf, count))) {
00385 if (ans != RESULT_OPERATION_TIMEOUT) {
00386 _isScanning = false;
00387 return RESULT_OPERATION_FAIL;
00388 }
00389 }
00390
00391 for (size_t pos = 0; pos < count; ++pos)
00392 {
00393 if (local_buf[pos].sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT)
00394 {
00395
00396
00397 if ((local_scan[0].sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT)) {
00398 _lock.lock();
00399 memcpy(_cached_scan_node_buf, local_scan, scan_count*sizeof(rplidar_response_measurement_node_t));
00400 _cached_scan_node_count = scan_count;
00401 _dataEvt.set();
00402 _lock.unlock();
00403 }
00404 scan_count = 0;
00405 }
00406 local_scan[scan_count++] = local_buf[pos];
00407 if (scan_count == _countof(local_scan)) scan_count-=1;
00408 }
00409 }
00410 _isScanning = false;
00411 return RESULT_OK;
00412 }
00413
00414 void RPlidarDriverSerialImpl::_capsuleToNormal(const rplidar_response_capsule_measurement_nodes_t & capsule, rplidar_response_measurement_node_t *nodebuffer, size_t &nodeCount)
00415 {
00416 nodeCount = 0;
00417 if (_is_previous_capsuledataRdy) {
00418 int diffAngle_q8;
00419 int currentStartAngle_q8 = ((capsule.start_angle_sync_q6 & 0x7FFF)<< 2);
00420 int prevStartAngle_q8 = ((_cached_previous_capsuledata.start_angle_sync_q6 & 0x7FFF) << 2);
00421
00422 diffAngle_q8 = (currentStartAngle_q8) - (prevStartAngle_q8);
00423 if (prevStartAngle_q8 > currentStartAngle_q8) {
00424 diffAngle_q8 += (360<<8);
00425 }
00426
00427 int angleInc_q16 = (diffAngle_q8 << 3);
00428 int currentAngle_raw_q16 = (prevStartAngle_q8 << 8);
00429 for (size_t pos = 0; pos < _countof(_cached_previous_capsuledata.cabins); ++pos)
00430 {
00431 int dist_q2[2];
00432 int angle_q6[2];
00433 int syncBit[2];
00434
00435 dist_q2[0] = (_cached_previous_capsuledata.cabins[pos].distance_angle_1 & 0xFFFC);
00436 dist_q2[1] = (_cached_previous_capsuledata.cabins[pos].distance_angle_2 & 0xFFFC);
00437
00438 int angle_offset1_q3 = ( (_cached_previous_capsuledata.cabins[pos].offset_angles_q3 & 0xF) | ((_cached_previous_capsuledata.cabins[pos].distance_angle_1 & 0x3)<<4));
00439 int angle_offset2_q3 = ( (_cached_previous_capsuledata.cabins[pos].offset_angles_q3 >> 4) | ((_cached_previous_capsuledata.cabins[pos].distance_angle_2 & 0x3)<<4));
00440
00441 angle_q6[0] = ((currentAngle_raw_q16 - (angle_offset1_q3<<13))>>10);
00442 syncBit[0] = (( (currentAngle_raw_q16 + angleInc_q16) % (360<<16)) < angleInc_q16 )?1:0;
00443 currentAngle_raw_q16 += angleInc_q16;
00444
00445
00446 angle_q6[1] = ((currentAngle_raw_q16 - (angle_offset2_q3<<13))>>10);
00447 syncBit[1] = (( (currentAngle_raw_q16 + angleInc_q16) % (360<<16)) < angleInc_q16 )?1:0;
00448 currentAngle_raw_q16 += angleInc_q16;
00449
00450 for (int cpos = 0; cpos < 2; ++cpos) {
00451
00452 if (angle_q6[cpos] < 0) angle_q6[cpos] += (360<<6);
00453 if (angle_q6[cpos] >= (360<<6)) angle_q6[cpos] -= (360<<6);
00454
00455 rplidar_response_measurement_node_t node;
00456
00457 node.sync_quality = (syncBit[cpos] | ((!syncBit[cpos]) << 1));
00458 if (dist_q2[cpos]) node.sync_quality |= (0x2F << RPLIDAR_RESP_MEASUREMENT_QUALITY_SHIFT);
00459
00460 node.angle_q6_checkbit = (1 | (angle_q6[cpos]<<1));
00461 node.distance_q2 = dist_q2[cpos];
00462
00463 nodebuffer[nodeCount++] = node;
00464 }
00465
00466 }
00467 }
00468
00469 _cached_previous_capsuledata = capsule;
00470 _is_previous_capsuledataRdy = true;
00471 }
00472
00473
00474 u_result RPlidarDriverSerialImpl::_cacheCapsuledScanData()
00475 {
00476 rplidar_response_capsule_measurement_nodes_t capsule_node;
00477 rplidar_response_measurement_node_t local_buf[128];
00478 size_t count = 128;
00479 rplidar_response_measurement_node_t local_scan[MAX_SCAN_NODES];
00480 size_t scan_count = 0;
00481 u_result ans;
00482 memset(local_scan, 0, sizeof(local_scan));
00483
00484 _waitCapsuledNode(capsule_node);
00485
00486 while(_isScanning)
00487 {
00488 if (IS_FAIL(ans=_waitCapsuledNode(capsule_node))) {
00489 if (ans != RESULT_OPERATION_TIMEOUT && ans != RESULT_INVALID_DATA) {
00490 _isScanning = false;
00491 return RESULT_OPERATION_FAIL;
00492 } else {
00493
00494 continue;
00495 }
00496 }
00497
00498 _capsuleToNormal(capsule_node, local_buf, count);
00499
00500 for (size_t pos = 0; pos < count; ++pos)
00501 {
00502 if (local_buf[pos].sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT)
00503 {
00504
00505
00506 if ((local_scan[0].sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT)) {
00507 _lock.lock();
00508 memcpy(_cached_scan_node_buf, local_scan, scan_count*sizeof(rplidar_response_measurement_node_t));
00509 _cached_scan_node_count = scan_count;
00510 _dataEvt.set();
00511 _lock.unlock();
00512 }
00513 scan_count = 0;
00514 }
00515 local_scan[scan_count++] = local_buf[pos];
00516 if (scan_count == _countof(local_scan)) scan_count-=1;
00517 }
00518 }
00519 _isScanning = false;
00520
00521 return RESULT_OK;
00522 }
00523
00524 u_result RPlidarDriverSerialImpl::grabScanData(rplidar_response_measurement_node_t * nodebuffer, size_t & count, _u32 timeout)
00525 {
00526 switch (_dataEvt.wait(timeout))
00527 {
00528 case rp::hal::Event::EVENT_TIMEOUT:
00529 count = 0;
00530 return RESULT_OPERATION_TIMEOUT;
00531 case rp::hal::Event::EVENT_OK:
00532 {
00533 if(_cached_scan_node_count == 0) return RESULT_OPERATION_TIMEOUT;
00534
00535 rp::hal::AutoLocker l(_lock);
00536
00537 size_t size_to_copy = min(count, _cached_scan_node_count);
00538
00539 memcpy(nodebuffer, _cached_scan_node_buf, size_to_copy*sizeof(rplidar_response_measurement_node_t));
00540 count = size_to_copy;
00541 _cached_scan_node_count = 0;
00542 }
00543 return RESULT_OK;
00544
00545 default:
00546 count = 0;
00547 return RESULT_OPERATION_FAIL;
00548 }
00549 }
00550
00551 u_result RPlidarDriverSerialImpl::ascendScanData(rplidar_response_measurement_node_t * nodebuffer, size_t count)
00552 {
00553 float inc_origin_angle = 360.0/count;
00554 size_t i = 0;
00555
00556
00557 for (i = 0; i < count; i++) {
00558 if(nodebuffer[i].distance_q2 == 0) {
00559 continue;
00560 } else {
00561 while(i != 0) {
00562 i--;
00563 float expect_angle = (nodebuffer[i+1].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f - inc_origin_angle;
00564 if (expect_angle < 0.0f) expect_angle = 0.0f;
00565 _u16 checkbit = nodebuffer[i].angle_q6_checkbit & RPLIDAR_RESP_MEASUREMENT_CHECKBIT;
00566 nodebuffer[i].angle_q6_checkbit = (((_u16)(expect_angle * 64.0f)) << RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT) + checkbit;
00567 }
00568 break;
00569 }
00570 }
00571
00572
00573 if (i == count) return RESULT_OPERATION_FAIL;
00574
00575
00576 for (i = count - 1; i >= 0; i--) {
00577 if(nodebuffer[i].distance_q2 == 0) {
00578 continue;
00579 } else {
00580 while(i != (count - 1)) {
00581 i++;
00582 float expect_angle = (nodebuffer[i-1].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f + inc_origin_angle;
00583 if (expect_angle > 360.0f) expect_angle -= 360.0f;
00584 _u16 checkbit = nodebuffer[i].angle_q6_checkbit & RPLIDAR_RESP_MEASUREMENT_CHECKBIT;
00585 nodebuffer[i].angle_q6_checkbit = (((_u16)(expect_angle * 64.0f)) << RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT) + checkbit;
00586 }
00587 break;
00588 }
00589 }
00590
00591
00592 float frontAngle = (nodebuffer[0].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f;
00593 for (i = 1; i < count; i++) {
00594 if(nodebuffer[i].distance_q2 == 0) {
00595 float expect_angle = frontAngle + i * inc_origin_angle;
00596 if (expect_angle > 360.0f) expect_angle -= 360.0f;
00597 _u16 checkbit = nodebuffer[i].angle_q6_checkbit & RPLIDAR_RESP_MEASUREMENT_CHECKBIT;
00598 nodebuffer[i].angle_q6_checkbit = (((_u16)(expect_angle * 64.0f)) << RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT) + checkbit;
00599 }
00600 }
00601
00602
00603 for (i = 0; i < (count-1); i++){
00604 for (size_t j = (i+1); j < count; j++){
00605 if(nodebuffer[i].angle_q6_checkbit > nodebuffer[j].angle_q6_checkbit){
00606 rplidar_response_measurement_node_t temp = nodebuffer[i];
00607 nodebuffer[i] = nodebuffer[j];
00608 nodebuffer[j] = temp;
00609 }
00610 }
00611 }
00612
00613 return RESULT_OK;
00614 }
00615
00616 u_result RPlidarDriverSerialImpl::_waitNode(rplidar_response_measurement_node_t * node, _u32 timeout)
00617 {
00618 int recvPos = 0;
00619 _u32 startTs = getms();
00620 _u8 recvBuffer[sizeof(rplidar_response_measurement_node_t)];
00621 _u8 *nodeBuffer = (_u8*)node;
00622 _u32 waitTime;
00623
00624 while ((waitTime=getms() - startTs) <= timeout) {
00625 size_t remainSize = sizeof(rplidar_response_measurement_node_t) - recvPos;
00626 size_t recvSize;
00627
00628 int ans = _rxtx->waitfordata(remainSize, timeout-waitTime, &recvSize);
00629 if (ans == rp::hal::serial_rxtx::ANS_DEV_ERR)
00630 return RESULT_OPERATION_FAIL;
00631 else if (ans == rp::hal::serial_rxtx::ANS_TIMEOUT)
00632 return RESULT_OPERATION_TIMEOUT;
00633
00634 if (recvSize > remainSize) recvSize = remainSize;
00635
00636 _rxtx->recvdata(recvBuffer, recvSize);
00637
00638 for (size_t pos = 0; pos < recvSize; ++pos) {
00639 _u8 currentByte = recvBuffer[pos];
00640 switch (recvPos) {
00641 case 0:
00642 {
00643 _u8 tmp = (currentByte>>1);
00644 if ( (tmp ^ currentByte) & 0x1 ) {
00645
00646 } else {
00647 continue;
00648 }
00649
00650 }
00651 break;
00652 case 1:
00653 {
00654 if (currentByte & RPLIDAR_RESP_MEASUREMENT_CHECKBIT) {
00655
00656 } else {
00657 recvPos = 0;
00658 continue;
00659 }
00660 }
00661 break;
00662 }
00663 nodeBuffer[recvPos++] = currentByte;
00664
00665 if (recvPos == sizeof(rplidar_response_measurement_node_t)) {
00666 return RESULT_OK;
00667 }
00668 }
00669 }
00670
00671 return RESULT_OPERATION_TIMEOUT;
00672 }
00673
00674
00675 u_result RPlidarDriverSerialImpl::_waitScanData(rplidar_response_measurement_node_t * nodebuffer, size_t & count, _u32 timeout)
00676 {
00677 if (!_isConnected) {
00678 count = 0;
00679 return RESULT_OPERATION_FAIL;
00680 }
00681
00682 size_t recvNodeCount = 0;
00683 _u32 startTs = getms();
00684 _u32 waitTime;
00685 u_result ans;
00686
00687 while ((waitTime = getms() - startTs) <= timeout && recvNodeCount < count) {
00688 rplidar_response_measurement_node_t node;
00689 if (IS_FAIL(ans = _waitNode(&node, timeout - waitTime))) {
00690 return ans;
00691 }
00692
00693 nodebuffer[recvNodeCount++] = node;
00694
00695 if (recvNodeCount == count) return RESULT_OK;
00696 }
00697 count = recvNodeCount;
00698 return RESULT_OPERATION_TIMEOUT;
00699 }
00700
00701
00702 u_result RPlidarDriverSerialImpl::_waitCapsuledNode(rplidar_response_capsule_measurement_nodes_t & node, _u32 timeout)
00703 {
00704 int recvPos = 0;
00705 _u32 startTs = getms();
00706 _u8 recvBuffer[sizeof(rplidar_response_capsule_measurement_nodes_t)];
00707 _u8 *nodeBuffer = (_u8*)&node;
00708 _u32 waitTime;
00709
00710 while ((waitTime=getms() - startTs) <= timeout) {
00711 size_t remainSize = sizeof(rplidar_response_capsule_measurement_nodes_t) - recvPos;
00712 size_t recvSize;
00713
00714 int ans = _rxtx->waitfordata(remainSize, timeout-waitTime, &recvSize);
00715 if (ans == rp::hal::serial_rxtx::ANS_DEV_ERR)
00716 return RESULT_OPERATION_FAIL;
00717 else if (ans == rp::hal::serial_rxtx::ANS_TIMEOUT)
00718 return RESULT_OPERATION_TIMEOUT;
00719
00720 if (recvSize > remainSize) recvSize = remainSize;
00721
00722 _rxtx->recvdata(recvBuffer, recvSize);
00723
00724 for (size_t pos = 0; pos < recvSize; ++pos) {
00725 _u8 currentByte = recvBuffer[pos];
00726 switch (recvPos) {
00727 case 0:
00728 {
00729 _u8 tmp = (currentByte>>4);
00730 if ( tmp == RPLIDAR_RESP_MEASUREMENT_EXP_SYNC_1 ) {
00731
00732 } else {
00733 _is_previous_capsuledataRdy = false;
00734 continue;
00735 }
00736
00737 }
00738 break;
00739 case 1:
00740 {
00741 _u8 tmp = (currentByte>>4);
00742 if (tmp == RPLIDAR_RESP_MEASUREMENT_EXP_SYNC_2) {
00743
00744 } else {
00745 recvPos = 0;
00746 _is_previous_capsuledataRdy = false;
00747 continue;
00748 }
00749 }
00750 break;
00751 }
00752 nodeBuffer[recvPos++] = currentByte;
00753
00754 if (recvPos == sizeof(rplidar_response_capsule_measurement_nodes_t)) {
00755
00756 _u8 checksum = 0;
00757 _u8 recvChecksum = ((node.s_checksum_1 & 0xF) | (node.s_checksum_2<<4));
00758 for (size_t cpos = offsetof(rplidar_response_capsule_measurement_nodes_t, start_angle_sync_q6);
00759 cpos < sizeof(rplidar_response_capsule_measurement_nodes_t); ++cpos)
00760 {
00761 checksum ^= nodeBuffer[cpos];
00762 }
00763 if (recvChecksum == checksum)
00764 {
00765
00766 if (node.start_angle_sync_q6 & RPLIDAR_RESP_MEASUREMENT_EXP_SYNCBIT)
00767 {
00768
00769 _is_previous_capsuledataRdy = false;
00770 return RESULT_OK;
00771 }
00772 return RESULT_OK;
00773 }
00774 _is_previous_capsuledataRdy = false;
00775 return RESULT_INVALID_DATA;
00776 }
00777 }
00778 }
00779 _is_previous_capsuledataRdy = false;
00780 return RESULT_OPERATION_TIMEOUT;
00781 }
00782
00783
00784 u_result RPlidarDriverSerialImpl::_sendCommand(_u8 cmd, const void * payload, size_t payloadsize)
00785 {
00786 _u8 pkt_header[10];
00787 rplidar_cmd_packet_t * header = reinterpret_cast<rplidar_cmd_packet_t * >(pkt_header);
00788 _u8 checksum = 0;
00789
00790 if (!_isConnected) return RESULT_OPERATION_FAIL;
00791
00792 if (payloadsize && payload) {
00793 cmd |= RPLIDAR_CMDFLAG_HAS_PAYLOAD;
00794 }
00795
00796 header->syncByte = RPLIDAR_CMD_SYNC_BYTE;
00797 header->cmd_flag = cmd;
00798
00799
00800 _rxtx->senddata(pkt_header, 2) ;
00801
00802 if (cmd & RPLIDAR_CMDFLAG_HAS_PAYLOAD) {
00803 checksum ^= RPLIDAR_CMD_SYNC_BYTE;
00804 checksum ^= cmd;
00805 checksum ^= (payloadsize & 0xFF);
00806
00807
00808 for (size_t pos = 0; pos < payloadsize; ++pos) {
00809 checksum ^= ((_u8 *)payload)[pos];
00810 }
00811
00812
00813 _u8 sizebyte = payloadsize;
00814 _rxtx->senddata(&sizebyte, 1);
00815
00816
00817 _rxtx->senddata((const _u8 *)payload, sizebyte);
00818
00819
00820 _rxtx->senddata(&checksum, 1);
00821 }
00822
00823 return RESULT_OK;
00824 }
00825
00826
00827 u_result RPlidarDriverSerialImpl::_waitResponseHeader(rplidar_ans_header_t * header, _u32 timeout)
00828 {
00829 int recvPos = 0;
00830 _u32 startTs = getms();
00831 _u8 recvBuffer[sizeof(rplidar_ans_header_t)];
00832 _u8 *headerBuffer = reinterpret_cast<_u8 *>(header);
00833 _u32 waitTime;
00834
00835 while ((waitTime=getms() - startTs) <= timeout) {
00836 size_t remainSize = sizeof(rplidar_ans_header_t) - recvPos;
00837 size_t recvSize;
00838
00839 int ans = _rxtx->waitfordata(remainSize, timeout - waitTime, &recvSize);
00840 if (ans == rp::hal::serial_rxtx::ANS_DEV_ERR)
00841 return RESULT_OPERATION_FAIL;
00842 else if (ans == rp::hal::serial_rxtx::ANS_TIMEOUT)
00843 return RESULT_OPERATION_TIMEOUT;
00844
00845 if(recvSize > remainSize) recvSize = remainSize;
00846
00847 _rxtx->recvdata(recvBuffer, recvSize);
00848
00849 for (size_t pos = 0; pos < recvSize; ++pos) {
00850 _u8 currentByte = recvBuffer[pos];
00851 switch (recvPos) {
00852 case 0:
00853 if (currentByte != RPLIDAR_ANS_SYNC_BYTE1) {
00854 continue;
00855 }
00856
00857 break;
00858 case 1:
00859 if (currentByte != RPLIDAR_ANS_SYNC_BYTE2) {
00860 recvPos = 0;
00861 continue;
00862 }
00863 break;
00864 }
00865 headerBuffer[recvPos++] = currentByte;
00866
00867 if (recvPos == sizeof(rplidar_ans_header_t)) {
00868 return RESULT_OK;
00869 }
00870 }
00871 }
00872
00873 return RESULT_OPERATION_TIMEOUT;
00874 }
00875
00876
00877
00878 void RPlidarDriverSerialImpl::_disableDataGrabbing()
00879 {
00880 _isScanning = false;
00881 _cachethread.join();
00882 }
00883
00884 u_result RPlidarDriverSerialImpl::getSampleDuration_uS(rplidar_response_sample_rate_t & rateInfo, _u32 timeout)
00885 {
00886 if (!isConnected()) return RESULT_OPERATION_FAIL;
00887
00888 _disableDataGrabbing();
00889
00890 rplidar_response_device_info_t devinfo;
00891
00892 u_result ans = getDeviceInfo(devinfo, timeout);
00893
00894 rateInfo.express_sample_duration_us = _cached_sampleduration_express;
00895 rateInfo.std_sample_duration_us = _cached_sampleduration_std;
00896
00897 if (devinfo.firmware_version < ((0x1<<8) | 17)) {
00898
00899
00900 return RESULT_OK;
00901 }
00902
00903
00904 {
00905 rp::hal::AutoLocker l(_lock);
00906
00907 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_SAMPLERATE))) {
00908 return ans;
00909 }
00910
00911 rplidar_ans_header_t response_header;
00912 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00913 return ans;
00914 }
00915
00916
00917 if (response_header.type != RPLIDAR_ANS_TYPE_SAMPLE_RATE) {
00918 return RESULT_INVALID_DATA;
00919 }
00920
00921 _u32 header_size = (response_header.size_q30_subtype & RPLIDAR_ANS_HEADER_SIZE_MASK);
00922 if ( header_size < sizeof(rplidar_response_sample_rate_t)) {
00923 return RESULT_INVALID_DATA;
00924 }
00925
00926 if (_rxtx->waitfordata(header_size, timeout) != rp::hal::serial_rxtx::ANS_OK) {
00927 return RESULT_OPERATION_TIMEOUT;
00928 }
00929 _rxtx->recvdata(reinterpret_cast<_u8 *>(&rateInfo), sizeof(rateInfo));
00930 }
00931 return RESULT_OK;
00932 }
00933
00934 u_result RPlidarDriverSerialImpl::checkMotorCtrlSupport(bool & support, _u32 timeout)
00935 {
00936 u_result ans;
00937 support = false;
00938
00939 if (!isConnected()) return RESULT_OPERATION_FAIL;
00940
00941 _disableDataGrabbing();
00942
00943 {
00944 rp::hal::AutoLocker l(_lock);
00945
00946 rplidar_payload_acc_board_flag_t flag;
00947 flag.reserved = 0;
00948
00949 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_ACC_BOARD_FLAG, &flag, sizeof(flag)))) {
00950 return ans;
00951 }
00952
00953 rplidar_ans_header_t response_header;
00954 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00955 return ans;
00956 }
00957
00958
00959 if (response_header.type != RPLIDAR_ANS_TYPE_ACC_BOARD_FLAG) {
00960 return RESULT_INVALID_DATA;
00961 }
00962
00963 _u32 header_size = (response_header.size_q30_subtype & RPLIDAR_ANS_HEADER_SIZE_MASK);
00964 if ( header_size < sizeof(rplidar_response_acc_board_flag_t)) {
00965 return RESULT_INVALID_DATA;
00966 }
00967
00968 if (_rxtx->waitfordata(header_size, timeout) != rp::hal::serial_rxtx::ANS_OK) {
00969 return RESULT_OPERATION_TIMEOUT;
00970 }
00971 rplidar_response_acc_board_flag_t acc_board_flag;
00972 _rxtx->recvdata(reinterpret_cast<_u8 *>(&acc_board_flag), sizeof(acc_board_flag));
00973
00974 if (acc_board_flag.support_flag & RPLIDAR_RESP_ACC_BOARD_FLAG_MOTOR_CTRL_SUPPORT_MASK) {
00975 support = true;
00976 }
00977 }
00978 return RESULT_OK;
00979 }
00980
00981 u_result RPlidarDriverSerialImpl::setMotorPWM(_u16 pwm)
00982 {
00983 u_result ans;
00984 rplidar_payload_motor_pwm_t motor_pwm;
00985 motor_pwm.pwm_value = pwm;
00986
00987 {
00988 rp::hal::AutoLocker l(_lock);
00989
00990 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_SET_MOTOR_PWM,(const _u8 *)&motor_pwm, sizeof(motor_pwm)))) {
00991 return ans;
00992 }
00993 }
00994
00995 return RESULT_OK;
00996 }
00997
00998 u_result RPlidarDriverSerialImpl::startMotor()
00999 {
01000 if (_isSupportingMotorCtrl) {
01001 setMotorPWM(DEFAULT_MOTOR_PWM);
01002 delay(500);
01003 return RESULT_OK;
01004 } else {
01005 rp::hal::AutoLocker l(_lock);
01006 _rxtx->clearDTR();
01007 delay(500);
01008 return RESULT_OK;
01009 }
01010 }
01011
01012 u_result RPlidarDriverSerialImpl::stopMotor()
01013 {
01014 if (_isSupportingMotorCtrl) {
01015 setMotorPWM(0);
01016 delay(500);
01017 return RESULT_OK;
01018 } else {
01019 rp::hal::AutoLocker l(_lock);
01020 _rxtx->setDTR();
01021 delay(500);
01022 return RESULT_OK;
01023 }
01024 }
01025
01026 }}}