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
00036
00037 #include "sdkcommon.h"
00038 #include "hal/abs_rxtx.h"
00039 #include "hal/thread.h"
00040 #include "hal/locker.h"
00041 #include "hal/event.h"
00042 #include "rplidar_driver_serial.h"
00043
00044 #ifndef min
00045 #define min(a,b) (((a) < (b)) ? (a) : (b))
00046 #endif
00047
00048 namespace rp { namespace standalone{ namespace rplidar {
00049
00050
00051
00052 RPlidarDriver * RPlidarDriver::CreateDriver(_u32 drivertype)
00053 {
00054 switch (drivertype) {
00055 case DRIVER_TYPE_SERIALPORT:
00056 return new RPlidarDriverSerialImpl();
00057 default:
00058 return NULL;
00059 }
00060 }
00061
00062
00063 void RPlidarDriver::DisposeDriver(RPlidarDriver * drv)
00064 {
00065 delete drv;
00066 }
00067
00068
00069
00070
00071
00072 RPlidarDriverSerialImpl::RPlidarDriverSerialImpl()
00073 : _isConnected(false)
00074 , _isScanning(false)
00075 {
00076 _rxtx = rp::hal::serial_rxtx::CreateRxTx();
00077 _cached_scan_node_count = 0;
00078 }
00079
00080 RPlidarDriverSerialImpl::~RPlidarDriverSerialImpl()
00081 {
00082
00083 disconnect();
00084
00085 rp::hal::serial_rxtx::ReleaseRxTx(_rxtx);
00086 }
00087
00088 u_result RPlidarDriverSerialImpl::connect(const char * port_path, _u32 baudrate, _u32 flag)
00089 {
00090 rp::hal::AutoLocker l(_lock);
00091 if (isConnected()) return RESULT_ALREADY_DONE;
00092
00093 if (!_rxtx) return RESULT_INSUFFICIENT_MEMORY;
00094
00095
00096 if (!_rxtx->bind(port_path, baudrate) || !_rxtx->open()) {
00097 return RESULT_INVALID_DATA;
00098 }
00099
00100 _rxtx->flush(0);
00101 _isConnected = true;
00102
00103 return RESULT_OK;
00104 }
00105
00106 void RPlidarDriverSerialImpl::disconnect()
00107 {
00108 if (!_isConnected) return ;
00109 stop();
00110 _rxtx->close();
00111 }
00112
00113 bool RPlidarDriverSerialImpl::isConnected()
00114 {
00115 return _isConnected;
00116 }
00117
00118
00119 u_result RPlidarDriverSerialImpl::reset(_u32 timeout)
00120 {
00121 u_result ans;
00122 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_RESET))) {
00123 return ans;
00124 }
00125 return RESULT_OK;
00126 }
00127
00128 u_result RPlidarDriverSerialImpl::getHealth(rplidar_response_device_health_t & healthinfo, _u32 timeout)
00129 {
00130 u_result ans;
00131
00132 if (!isConnected()) return RESULT_OPERATION_FAIL;
00133
00134 _disableDataGrabbing();
00135
00136 {
00137 rp::hal::AutoLocker l(_lock);
00138 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_DEVICE_HEALTH))) {
00139 return ans;
00140 }
00141
00142 rplidar_ans_header_t response_header;
00143 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00144 return ans;
00145 }
00146
00147
00148 if (response_header.type != RPLIDAR_ANS_TYPE_DEVHEALTH) {
00149 return RESULT_INVALID_DATA;
00150 }
00151
00152 if (response_header.size < sizeof(rplidar_response_device_health_t)) {
00153 return RESULT_INVALID_DATA;
00154 }
00155
00156 if (_rxtx->waitfordata(response_header.size, timeout) != rp::hal::serial_rxtx::ANS_OK) {
00157 return RESULT_OPERATION_TIMEOUT;
00158 }
00159 _rxtx->recvdata(reinterpret_cast<_u8 *>(&healthinfo), sizeof(healthinfo));
00160 }
00161 return RESULT_OK;
00162 }
00163
00164 u_result RPlidarDriverSerialImpl::getDeviceInfo(rplidar_response_device_info_t & info, _u32 timeout)
00165 {
00166 u_result ans;
00167
00168 if (!isConnected()) return RESULT_OPERATION_FAIL;
00169
00170 _disableDataGrabbing();
00171
00172 {
00173 rp::hal::AutoLocker l(_lock);
00174 if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_DEVICE_INFO))) {
00175 return ans;
00176 }
00177
00178 rplidar_ans_header_t response_header;
00179 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00180 return ans;
00181 }
00182
00183
00184 if (response_header.type != RPLIDAR_ANS_TYPE_DEVINFO) {
00185 return RESULT_INVALID_DATA;
00186 }
00187
00188 if (response_header.size < sizeof(rplidar_response_device_info_t)) {
00189 return RESULT_INVALID_DATA;
00190 }
00191
00192 if (_rxtx->waitfordata(response_header.size, timeout) != rp::hal::serial_rxtx::ANS_OK) {
00193 return RESULT_OPERATION_TIMEOUT;
00194 }
00195
00196 _rxtx->recvdata(reinterpret_cast<_u8 *>(&info), sizeof(info));
00197 }
00198 return RESULT_OK;
00199 }
00200
00201 u_result RPlidarDriverSerialImpl::getFrequency(rplidar_response_measurement_node_t * nodebuffer, size_t count, float & frequency)
00202 {
00203 const float RPLIDAR_SAMPLE_DURATION = 490.3;
00204 if (count == 0)
00205 {
00206 frequency = 0.0f;
00207 }
00208 else
00209 {
00210 frequency = (float)(1000000/(count * RPLIDAR_SAMPLE_DURATION));
00211 }
00212 return RESULT_OK;
00213 }
00214
00215 u_result RPlidarDriverSerialImpl::startScan(bool force, _u32 timeout)
00216 {
00217 u_result ans;
00218 if (!isConnected()) return RESULT_OPERATION_FAIL;
00219 if (_isScanning) return RESULT_ALREADY_DONE;
00220
00221 stop();
00222
00223 {
00224 rp::hal::AutoLocker l(_lock);
00225
00226 if (IS_FAIL(ans = _sendCommand(force?RPLIDAR_CMD_FORCE_SCAN:RPLIDAR_CMD_SCAN))) {
00227 return ans;
00228 }
00229
00230
00231 rplidar_ans_header_t response_header;
00232 if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
00233 return ans;
00234 }
00235
00236
00237 if (response_header.type != RPLIDAR_ANS_TYPE_MEASUREMENT) {
00238 return RESULT_INVALID_DATA;
00239 }
00240
00241 if (response_header.size < sizeof(rplidar_response_measurement_node_t)) {
00242 return RESULT_INVALID_DATA;
00243 }
00244
00245 _isScanning = true;
00246 _cachethread = CLASS_THREAD(RPlidarDriverSerialImpl, _cacheScanData);
00247 }
00248 return RESULT_OK;
00249 }
00250
00251 u_result RPlidarDriverSerialImpl::stop(_u32 timeout)
00252 {
00253 _disableDataGrabbing();
00254 u_result ans = _sendCommand(RPLIDAR_CMD_STOP);
00255 return ans;
00256 }
00257
00258 u_result RPlidarDriverSerialImpl::_cacheScanData()
00259 {
00260 rplidar_response_measurement_node_t local_buf[128];
00261 size_t count = 128;
00262 rplidar_response_measurement_node_t local_scan[MAX_SCAN_NODES];
00263 size_t scan_count = 0;
00264 u_result ans;
00265 memset(local_scan, 0, sizeof(local_scan));
00266
00267 _waitScanData(local_buf, count);
00268
00269 while(_isScanning)
00270 {
00271 if (IS_FAIL(ans=_waitScanData(local_buf, count))) {
00272 if (ans != RESULT_OPERATION_TIMEOUT) {
00273 _isScanning = false;
00274 return RESULT_OPERATION_FAIL;
00275 }
00276 }
00277
00278 for (size_t pos = 0; pos < count; ++pos)
00279 {
00280 if (local_buf[pos].sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT)
00281 {
00282
00283
00284 if ((local_scan[0].sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT)) {
00285 _lock.lock();
00286 memcpy(_cached_scan_node_buf, local_scan, scan_count*sizeof(rplidar_response_measurement_node_t));
00287 _cached_scan_node_count = scan_count;
00288 _dataEvt.set();
00289 _lock.unlock();
00290 }
00291 scan_count = 0;
00292 }
00293 local_scan[scan_count++] = local_buf[pos];
00294 if (scan_count == _countof(local_scan)) scan_count-=1;
00295 }
00296 }
00297 _isScanning = false;
00298 return RESULT_OK;
00299 }
00300
00301 u_result RPlidarDriverSerialImpl::grabScanData(rplidar_response_measurement_node_t * nodebuffer, size_t & count, _u32 timeout)
00302 {
00303 switch (_dataEvt.wait(timeout))
00304 {
00305 case rp::hal::Event::EVENT_TIMEOUT:
00306 count = 0;
00307 return RESULT_OPERATION_TIMEOUT;
00308 case rp::hal::Event::EVENT_OK:
00309 {
00310 if(_cached_scan_node_count == 0) return RESULT_OPERATION_TIMEOUT;
00311
00312 rp::hal::AutoLocker l(_lock);
00313
00314 size_t size_to_copy = min(count, _cached_scan_node_count);
00315
00316 memcpy(nodebuffer, _cached_scan_node_buf, size_to_copy*sizeof(rplidar_response_measurement_node_t));
00317 count = size_to_copy;
00318 _cached_scan_node_count = 0;
00319 }
00320 return RESULT_OK;
00321
00322 default:
00323 count = 0;
00324 return RESULT_OPERATION_FAIL;
00325 }
00326 }
00327
00328 u_result RPlidarDriverSerialImpl::ascendScanData(rplidar_response_measurement_node_t * nodebuffer, size_t count)
00329 {
00330 float inc_origin_angle = 360.0/count;
00331 rplidar_response_measurement_node_t *tmpbuffer = new rplidar_response_measurement_node_t[count];
00332 int i = 0;
00333
00334
00335 for (i = 0; i < count; i++) {
00336 if(nodebuffer[i].distance_q2 == 0) {
00337 continue;
00338 } else {
00339 while(i != 0) {
00340 i--;
00341 float expect_angle = (nodebuffer[i+1].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f - inc_origin_angle;
00342 if (expect_angle < 0.0f) expect_angle = 0.0f;
00343 _u16 checkbit = nodebuffer[i].angle_q6_checkbit & RPLIDAR_RESP_MEASUREMENT_CHECKBIT;
00344 nodebuffer[i].angle_q6_checkbit = (((_u16)(expect_angle * 64.0f)) << RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT) + checkbit;
00345 }
00346 break;
00347 }
00348 }
00349
00350
00351 if (i == count){
00352 delete[] tmpbuffer;
00353 return RESULT_OPERATION_FAIL;
00354 }
00355
00356
00357 for (i = count - 1; i >= 0; i--) {
00358 if(nodebuffer[i].distance_q2 == 0) {
00359 continue;
00360 } else {
00361 while(i != (count - 1)) {
00362 i++;
00363 float expect_angle = (nodebuffer[i-1].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f + inc_origin_angle;
00364 if (expect_angle > 360.0f) expect_angle -= 360.0f;
00365 _u16 checkbit = nodebuffer[i].angle_q6_checkbit & RPLIDAR_RESP_MEASUREMENT_CHECKBIT;
00366 nodebuffer[i].angle_q6_checkbit = (((_u16)(expect_angle * 64.0f)) << RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT) + checkbit;
00367 }
00368 break;
00369 }
00370 }
00371
00372
00373 float frontAngle = (nodebuffer[0].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f;
00374 for (i = 0; i < count; i++) {
00375 if(nodebuffer[i].distance_q2 == 0) {
00376 float expect_angle = frontAngle + i * inc_origin_angle;
00377 if (expect_angle > 360.0f) expect_angle -= 360.0f;
00378 _u16 checkbit = nodebuffer[i].angle_q6_checkbit & RPLIDAR_RESP_MEASUREMENT_CHECKBIT;
00379 nodebuffer[i].angle_q6_checkbit = (((_u16)(expect_angle * 64.0f)) << RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT) + checkbit;
00380 }
00381 }
00382
00383
00384 size_t zero_pos = 0;
00385 float pre_degree = (nodebuffer[0].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f;
00386
00387 for (i = 1; i < count ; ++i) {
00388 float degree = (nodebuffer[i].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f;
00389 if (zero_pos == 0 && (pre_degree - degree > 180)) {
00390 zero_pos = i;
00391 break;
00392 }
00393 pre_degree = degree;
00394 }
00395
00396
00397 for (i = zero_pos; i < count; i++) {
00398 tmpbuffer[i-zero_pos] = nodebuffer[i];
00399 }
00400 for (i = 0; i < zero_pos; i++) {
00401 tmpbuffer[i+count-zero_pos] = nodebuffer[i];
00402 }
00403
00404 memcpy(nodebuffer, tmpbuffer, count*sizeof(rplidar_response_measurement_node_t));
00405 delete[] tmpbuffer;
00406
00407 return RESULT_OK;
00408 }
00409
00410 u_result RPlidarDriverSerialImpl::stopMotor()
00411 {
00412
00413 _rxtx->setDTR();
00414 return RESULT_OK;
00415 }
00416
00417 u_result RPlidarDriverSerialImpl::startMotor()
00418 {
00419
00420 _rxtx->clearDTR();
00421 return RESULT_OK;
00422 }
00423
00424
00425 u_result RPlidarDriverSerialImpl::_waitNode(rplidar_response_measurement_node_t * node, _u32 timeout)
00426 {
00427 int recvPos = 0;
00428 _u32 startTs = getms();
00429 _u8 recvBuffer[sizeof(rplidar_response_measurement_node_t)];
00430 _u8 *nodeBuffer = (_u8*)node;
00431 _u32 waitTime;
00432
00433 while ((waitTime=getms() - startTs) <= timeout) {
00434 size_t remainSize = sizeof(rplidar_response_measurement_node_t) - recvPos;
00435 size_t recvSize;
00436
00437 int ans = _rxtx->waitfordata(remainSize, timeout-waitTime, &recvSize);
00438 if (ans == rp::hal::serial_rxtx::ANS_DEV_ERR)
00439 return RESULT_OPERATION_FAIL;
00440 else if (ans == rp::hal::serial_rxtx::ANS_TIMEOUT)
00441 return RESULT_OPERATION_TIMEOUT;
00442
00443 if (recvSize > remainSize) recvSize = remainSize;
00444
00445 _rxtx->recvdata(recvBuffer, recvSize);
00446
00447 for (size_t pos = 0; pos < recvSize; ++pos) {
00448 _u8 currentByte = recvBuffer[pos];
00449 switch (recvPos) {
00450 case 0:
00451 {
00452 _u8 tmp = (currentByte>>1);
00453 if ( (tmp ^ currentByte) & 0x1 ) {
00454
00455 } else {
00456 continue;
00457 }
00458
00459 }
00460 break;
00461 case 1:
00462 {
00463 if (currentByte & RPLIDAR_RESP_MEASUREMENT_CHECKBIT) {
00464
00465 } else {
00466 recvPos = 0;
00467 continue;
00468 }
00469 }
00470 break;
00471 }
00472 nodeBuffer[recvPos++] = currentByte;
00473
00474 if (recvPos == sizeof(rplidar_response_measurement_node_t)) {
00475 return RESULT_OK;
00476 }
00477 }
00478 }
00479
00480 return RESULT_OPERATION_TIMEOUT;
00481 }
00482
00483 u_result RPlidarDriverSerialImpl::_waitScanData(rplidar_response_measurement_node_t * nodebuffer, size_t & count, _u32 timeout)
00484 {
00485 if (!_isConnected) {
00486 count = 0;
00487 return RESULT_OPERATION_FAIL;
00488 }
00489
00490 size_t recvNodeCount = 0;
00491 _u32 startTs = getms();
00492 _u32 waitTime;
00493 u_result ans;
00494
00495 while ((waitTime = getms() - startTs) <= timeout && recvNodeCount < count) {
00496 rplidar_response_measurement_node_t node;
00497 if (IS_FAIL(ans = _waitNode(&node, timeout - waitTime))) {
00498 return ans;
00499 }
00500
00501 nodebuffer[recvNodeCount++] = node;
00502
00503 if (recvNodeCount == count) return RESULT_OK;
00504 }
00505 count = recvNodeCount;
00506 return RESULT_OPERATION_TIMEOUT;
00507 }
00508
00509 u_result RPlidarDriverSerialImpl::_sendCommand(_u8 cmd, const void * payload, size_t payloadsize)
00510 {
00511 _u8 pkt_header[10];
00512 rplidar_cmd_packet_t * header = reinterpret_cast<rplidar_cmd_packet_t * >(pkt_header);
00513 _u8 checksum = 0;
00514
00515 if (!_isConnected) return RESULT_OPERATION_FAIL;
00516
00517 if (payloadsize && payload) {
00518 cmd |= RPLIDAR_CMDFLAG_HAS_PAYLOAD;
00519 }
00520
00521 header->syncByte = RPLIDAR_CMD_SYNC_BYTE;
00522 header->cmd_flag = cmd;
00523
00524
00525 _rxtx->senddata(pkt_header, 2) ;
00526
00527 if (cmd & RPLIDAR_CMDFLAG_HAS_PAYLOAD) {
00528 checksum ^= RPLIDAR_CMD_SYNC_BYTE;
00529 checksum ^= cmd;
00530 checksum ^= (payloadsize & 0xFF);
00531
00532
00533 for (size_t pos = 0; pos < payloadsize; ++pos) {
00534 checksum ^= ((_u8 *)payload)[pos];
00535 }
00536
00537
00538 _u8 sizebyte = payloadsize;
00539 _rxtx->senddata(&sizebyte, 1);
00540
00541
00542 _rxtx->senddata((const _u8 *)payload, sizebyte);
00543
00544
00545 _rxtx->senddata(&checksum, 1);
00546 }
00547
00548 return RESULT_OK;
00549 }
00550
00551
00552 u_result RPlidarDriverSerialImpl::_waitResponseHeader(rplidar_ans_header_t * header, _u32 timeout)
00553 {
00554 int recvPos = 0;
00555 _u32 startTs = getms();
00556 _u8 recvBuffer[sizeof(rplidar_ans_header_t)];
00557 _u8 *headerBuffer = reinterpret_cast<_u8 *>(header);
00558 _u32 waitTime;
00559
00560 while ((waitTime=getms() - startTs) <= timeout) {
00561 size_t remainSize = sizeof(rplidar_ans_header_t) - recvPos;
00562 size_t recvSize;
00563
00564 int ans = _rxtx->waitfordata(remainSize, timeout - waitTime, &recvSize);
00565 if (ans == rp::hal::serial_rxtx::ANS_DEV_ERR)
00566 return RESULT_OPERATION_FAIL;
00567 else if (ans == rp::hal::serial_rxtx::ANS_TIMEOUT)
00568 return RESULT_OPERATION_TIMEOUT;
00569
00570 if(recvSize > remainSize) recvSize = remainSize;
00571
00572 _rxtx->recvdata(recvBuffer, recvSize);
00573
00574 for (size_t pos = 0; pos < recvSize; ++pos) {
00575 _u8 currentByte = recvBuffer[pos];
00576 switch (recvPos) {
00577 case 0:
00578 if (currentByte != RPLIDAR_ANS_SYNC_BYTE1) {
00579 continue;
00580 }
00581
00582 break;
00583 case 1:
00584 if (currentByte != RPLIDAR_ANS_SYNC_BYTE2) {
00585 recvPos = 0;
00586 continue;
00587 }
00588 break;
00589 }
00590 headerBuffer[recvPos++] = currentByte;
00591
00592 if (recvPos == sizeof(rplidar_ans_header_t)) {
00593 return RESULT_OK;
00594 }
00595 }
00596 }
00597
00598 return RESULT_OPERATION_TIMEOUT;
00599 }
00600
00601
00602
00603 void RPlidarDriverSerialImpl::_disableDataGrabbing()
00604 {
00605 _isScanning = false;
00606 _cachethread.join();
00607 }
00608
00609 }}}