硬件:思岚RPLIDAR A1M8
一、接收雷达数据
接收数据用的是一个新线程。根据不同扫描模式会用不同线程函数,针对RPLIDAR A1M8是RPlidarDriverImplCommon::_cacheUltraCapsuledScanData。启动时机是在向rplidar发送开始扫描命令时。
1.1 _waitUltraCapsuledNode
u_result RPlidarDriverImplCommon::_waitUltraCapsuledNode(rplidar_response_ultra_capsule_measurement_nodes_t & node, _u32 timeout)
从串口接收一个胶囊字节数(132字节),数据存放在node。
- @node。收到的数据放到这个node。sizeof(rplidar_response_ultra_capsule_measurement_nodes_t)=132。
- @timeout。接收此个node数据的溢出时间。默认2秒。2秒内没收完这个node,返回RESULT_OPERATION_TIMEOUT。
- 返回值。1)RESULT_OK:成功。2)RESULT_OPERATION_TIMEOUT:接收时间超过了timeout。3)RESULT_INVALID_DATA:132字节是收全了,但较验失败。
1.2 _ultraCapsuleToNormal
typedef struct rplidar_response_measurement_node_hq_t { _u16 angle_z_q14; _u32 dist_mm_q2; _u8 quality; _u8 flag; } __attribute__((packed)) rplidar_response_measurement_node_hq_t; void RPlidarDriverImplCommon::_ultraCapsuleToNormal(const rplidar_response_ultra_capsule_measurement_nodes_t & capsule, rplidar_response_measurement_node_hq_t *nodebuffer, size_t &nodeCount)
直接从串口收到的数据用了思岚自个的压缩算法,_ultraCapsuleToNormal负责进行解压缩,解压缩后的数据放在nodebuffer。nodebuffer是个数组,一个nodebuffer单元字节数sizeof(rplidar_response_measurement_node_hq_t),所以解压缩一个132字节胶囊后会得到多个nodebuffer,参数nodeCount记录了这个数目。
[_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [生成一帧]commit one, scan_count(1083) * sizeof(rplidar_response_measurement_node_hq_t)(8) = 8664 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [_ultraCapsuleToNormal]sizeof(ultra_capsule_node): 132, sizeof(rplidar_response_measurement_node_hq_t): 8, count: 96 [生成一帧]commit one, scan_count(1082) * sizeof(rplidar_response_measurement_node_hq_t)(8) = 8656
上面是数次解压缩,并形成帧。它显示了两帧,第一帧1083圈,一帧8664字节。第二帧1882圈,一帧8656字节。从上面可看出,一个132字节胶囊解压缩后可得到8圈768字节(8*96)。
综上所述,数据线程把数据以着一圈圈放在了(_cached_scan_node_hq_buf, _cached_scan_node_hq_count)。_cached_scan_node_hq_buf是个数组,元素类型是rplidar_response_measurement_node_hq_t。cached_scan_node_hq_count就圈数,值可能像1083、1082等。知道这个结果后,就能很快理解main线程调用的grabScanDataHq。
1.3 grabScanDataHq
u_result RPlidarDriverImplCommon::grabScanDataHq(rplidar_response_measurement_node_hq_t * nodebuffer, size_t & count, _u32 timeout) { if (!_dataEvt.Wait(timeout)) { // rp::hal::Event::EVENT_TIMEOUT count = 0; return RESULT_OPERATION_TIMEOUT; } else { // rp::hal::Event::EVENT_OK: if (_cached_scan_node_hq_count == 0) return RESULT_OPERATION_TIMEOUT; //consider as timeout threading::lock l(_lock); size_t size_to_copy = min(count, _cached_scan_node_hq_count); memcpy(nodebuffer, _cached_scan_node_hq_buf, size_to_copy * sizeof(rplidar_response_measurement_node_hq_t)); count = size_to_copy; _cached_scan_node_hq_count = 0; } return RESULT_OK; }
_cached_scan_node_hq_count不等0,意味着数据线程收到新数据,grabScanDataHq反这些数据复制到nodebuffer,count存储着圈数。复制完后,_cached_scan_node_hq_count置0,保证下次grabScanDataHq得到的会是新数据。