Skip to content

Commit f08db1f

Browse files
committed
AP_Proximity: add RPLidar S2, remove memory copy for each measurement
1 parent 7f61ace commit f08db1f

File tree

2 files changed

+40
-133
lines changed

2 files changed

+40
-133
lines changed

libraries/AP_Proximity/AP_Proximity_RPLidarA2.cpp

Lines changed: 37 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "AP_Proximity_RPLidarA2.h"
3434

3535
#include <AP_HAL/AP_HAL.h>
36-
#include "AP_Proximity_RPLidarA2.h"
3736
#include <AP_InternalError/AP_InternalError.h>
3837

3938
#include <ctype.h>
@@ -75,15 +74,6 @@ void AP_Proximity_RPLidarA2::update(void)
7574
return;
7675
}
7776

78-
// request device info 3sec after reset
79-
// required for S1 support that sends only 9 bytes after a reset (A1,A2 send 63)
80-
uint32_t now_ms = AP_HAL::millis();
81-
if ((_state == State::RESET) && (now_ms - _last_reset_ms > 3000)) {
82-
send_request_for_device_info();
83-
_state = State::AWAITING_RESPONSE;
84-
_byte_count = 0;
85-
}
86-
8777
get_readings();
8878

8979
// check for timeout and set health status
@@ -112,6 +102,8 @@ float AP_Proximity_RPLidarA2::distance_max() const
112102
return 12.0f;
113103
case Model::S1:
114104
return 40.0f;
105+
case Model::S2:
106+
return 50.0f;
115107
}
116108
return 0.0f;
117109
}
@@ -127,18 +119,20 @@ float AP_Proximity_RPLidarA2::distance_min() const
127119
case Model::C1:
128120
case Model::S1:
129121
return 0.2f;
122+
case Model::S2:
123+
return 0.05f;
130124
}
131125
return 0.0f;
132126
}
133127

128+
// reset lidar
134129
void AP_Proximity_RPLidarA2::reset_rplidar()
135130
{
136131
static const uint8_t tx_buffer[2] {RPLIDAR_PREAMBLE, RPLIDAR_CMD_RESET};
137132
_uart->write(tx_buffer, 2);
138133
Debug(1, "LIDAR reset");
139-
// To-Do: ensure delay of 8m after sending reset request
140134
_last_reset_ms = AP_HAL::millis();
141-
reset();
135+
_state = State::RESET;
142136
}
143137

144138
// set Lidar into SCAN mode
@@ -165,114 +159,36 @@ void AP_Proximity_RPLidarA2::send_request_for_device_info()
165159
Debug(1, "Sent device information request");
166160
}
167161

168-
void AP_Proximity_RPLidarA2::consume_bytes(uint16_t count)
169-
{
170-
if (count > _byte_count) {
171-
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
172-
_byte_count = 0;
173-
return;
174-
}
175-
_byte_count -= count;
176-
if (_byte_count) {
177-
memmove((void*)&_payload[0], (void*)&_payload[count], _byte_count);
178-
}
179-
}
180-
181-
void AP_Proximity_RPLidarA2::reset()
182-
{
183-
_state = State::RESET;
184-
_byte_count = 0;
185-
}
186-
187-
bool AP_Proximity_RPLidarA2::make_first_byte_in_payload(uint8_t desired_byte)
188-
{
189-
if (_byte_count == 0) {
190-
return false;
191-
}
192-
if (_payload[0] == desired_byte) {
193-
return true;
194-
}
195-
for (auto i=1; i<_byte_count; i++) {
196-
if (_payload[i] == desired_byte) {
197-
consume_bytes(i);
198-
return true;
199-
}
200-
}
201-
// just not in our buffer. Throw everything away:
202-
_byte_count = 0;
203-
return false;
204-
}
205-
206162
void AP_Proximity_RPLidarA2::get_readings()
207163
{
208-
Debug(2, " CURRENT STATE: %u ", (unsigned)_state);
209-
const uint32_t nbytes = _uart->available();
210-
if (nbytes == 0) {
211-
return;
212-
}
213-
const uint32_t bytes_to_read = MIN(nbytes, sizeof(_payload)-_byte_count);
214-
if (bytes_to_read == 0) {
215-
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
216-
reset();
217-
return;
218-
}
219-
const uint32_t bytes_read = _uart->read(&_payload[_byte_count], bytes_to_read);
220-
if (bytes_read == 0) {
221-
// this is bad; we were told there were bytes available
222-
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
223-
reset();
224-
return;
225-
}
226-
_byte_count += bytes_read;
227-
228-
uint32_t previous_loop_byte_count = UINT32_MAX;
229-
while (_byte_count) {
230-
if (_byte_count >= previous_loop_byte_count) {
231-
// this is a serious error, we should always consume some
232-
// bytes. Avoid looping forever.
233-
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
234-
_uart = nullptr;
235-
return;
236-
}
237-
previous_loop_byte_count = _byte_count;
238-
164+
uint16_t _bytes_read = 0;
165+
Debug(2, "CURRENT STATE: %u ", (unsigned)_state);
166+
while (_uart->available() && _bytes_read < MAX_BYTES_CONSUME) {
239167
switch(_state){
240168
case State::RESET: {
241-
// looking for 0x52 at start of buffer; the 62 following
242-
// bytes are "information"
243-
if (!make_first_byte_in_payload('R')) { // that's 'R' as in RPiLidar
169+
if (AP_HAL::millis() - _last_reset_ms < 1000) {
244170
return;
245171
}
246-
if (_byte_count < 63) {
247-
return;
248-
}
249-
#if RP_DEBUG_LEVEL
250-
// optionally spit out via mavlink the 63-bytes of cruft
251-
// that is spat out on device reset
252-
Debug(1, "Got RPLidar Information");
253-
char xbuffer[64]{};
254-
memcpy((void*)xbuffer, (void*)&_payload.information, 63);
255-
gcs().send_text(MAV_SEVERITY_INFO, "RPLidar: (%s)", xbuffer);
256-
#endif
257-
// 63 is the magic number of bytes in the spewed-out
258-
// reset data ... so now we'll just drop that stuff on
259-
// the floor.
260-
consume_bytes(63);
172+
_uart->discard_input();
261173
send_request_for_device_info();
262174
_state = State::AWAITING_RESPONSE;
263175
continue;
264176
}
265177
case State::AWAITING_RESPONSE:
266-
if (_payload[0] != RPLIDAR_PREAMBLE) {
267-
// this is a protocol error. Reset.
268-
reset();
178+
// descriptor packet has 7 byte in total
179+
if (_uart->available() < sizeof(_descriptor)) {
269180
return;
270181
}
182+
_uart->read(&_payload[0], sizeof(_descriptor));
183+
_bytes_read += sizeof(_descriptor);
271184

272-
// descriptor packet has 7 byte in total
273-
if (_byte_count < sizeof(_descriptor)) {
185+
if (_payload[0] != RPLIDAR_PREAMBLE) {
186+
Debug(1, "protocol error");
187+
// this is a protocol error do a reset.
188+
reset_rplidar();
274189
return;
275190
}
191+
276192
// identify the payload data after the descriptor
277193
static const _descriptor SCAN_DATA_DESCRIPTOR[] {
278194
{ RPLIDAR_PREAMBLE, 0x5A, 0x05, 0x00, 0x00, 0x40, 0x81 }
@@ -293,31 +209,33 @@ void AP_Proximity_RPLidarA2::get_readings()
293209
} else {
294210
// unknown descriptor. Ignore it.
295211
}
296-
consume_bytes(sizeof(_descriptor));
297212
break;
298213

299214
case State::AWAITING_DEVICE_INFO:
300-
if (_byte_count < sizeof(_payload.device_info)) {
215+
if (_uart->available() < sizeof(_payload.device_info)) {
301216
return;
302217
}
218+
_uart->read(&_payload[0], sizeof(_payload.device_info));
219+
_bytes_read += sizeof(_payload.device_info);
303220
parse_response_device_info();
304-
consume_bytes(sizeof(_payload.device_info));
305221
break;
306222

307223
case State::AWAITING_SCAN_DATA:
308-
if (_byte_count < sizeof(_payload.sensor_scan)) {
224+
if (_uart->available() < sizeof(_payload.sensor_scan)) {
309225
return;
310226
}
227+
_uart->read(&_payload[0], sizeof(_payload.sensor_scan));
228+
_bytes_read += sizeof(_payload.sensor_scan);
311229
parse_response_data();
312-
consume_bytes(sizeof(_payload.sensor_scan));
313230
break;
314231

315232
case State::AWAITING_HEALTH:
316-
if (_byte_count < sizeof(_payload.sensor_health)) {
233+
if (_uart->available() < sizeof(_payload.sensor_health)) {
317234
return;
318235
}
236+
_uart->read(&_payload[0], sizeof(_payload.sensor_health));
237+
_bytes_read += sizeof(_payload.sensor_health);
319238
parse_response_health();
320-
consume_bytes(sizeof(_payload.sensor_health));
321239
break;
322240
}
323241
}
@@ -344,6 +262,10 @@ void AP_Proximity_RPLidarA2::parse_response_device_info()
344262
model = Model::S1;
345263
device_type = "S1";
346264
break;
265+
case 0x71:
266+
model = Model::S2;
267+
device_type = "S2";
268+
break;
347269
default:
348270
Debug(1, "Unknown device (%u)", _payload.device_info.model);
349271
}
@@ -356,12 +278,13 @@ void AP_Proximity_RPLidarA2::parse_response_data()
356278
{
357279
if (_sync_error) {
358280
// out of 5-byte sync mask -> catch new revolution
359-
Debug(1, " OUT OF SYNC");
281+
Debug(1, "OUT OF SYNC");
360282
// on first revolution bit 1 = 1, bit 2 = 0 of the first byte
361283
if ((_payload[0] & 0x03) == 0x01) {
362284
_sync_error = 0;
363-
Debug(1, " RESYNC");
285+
Debug(1, "RESYNC");
364286
} else {
287+
Debug(1, "NO RESYNC");
365288
return;
366289
}
367290
}
@@ -412,7 +335,7 @@ void AP_Proximity_RPLidarA2::parse_response_data()
412335

413336
void AP_Proximity_RPLidarA2::parse_response_health()
414337
{
415-
// health issue if status is "3" ->HW error
338+
// health issue if status is "3" -> HW error
416339
if (_payload.sensor_health.status == 3) {
417340
Debug(1, "LIDAR Error");
418341
}

libraries/AP_Proximity/AP_Proximity_RPLidarA2.h

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class AP_Proximity_RPLidarA2 : public AP_Proximity_Backend_Serial
7272
AWAITING_DEVICE_INFO,
7373
} _state = State::RESET;
7474

75+
static constexpr uint16_t MAX_BYTES_CONSUME = 1024;
76+
7577
// send request for something from sensor
7678
void send_request_for_health();
7779
void send_scan_mode_request();
@@ -83,13 +85,8 @@ class AP_Proximity_RPLidarA2 : public AP_Proximity_Backend_Serial
8385

8486
void get_readings();
8587
void reset_rplidar();
86-
void reset();
87-
88-
// remove bytes from read buffer:
89-
void consume_bytes(uint16_t count);
9088

9189
uint8_t _sync_error;
92-
uint16_t _byte_count;
9390

9491
// request related variables
9592
uint32_t _last_distance_received_ms; ///< system time of last distance measurement received from sensor
@@ -127,35 +124,22 @@ class AP_Proximity_RPLidarA2 : public AP_Proximity_Backend_Serial
127124
uint8_t bytes[7];
128125
};
129126

130-
// we don't actually *need* to store this. If we don't, _payload
131-
// can be just 7 bytes, but that doesn't make for efficient
132-
// reading. It also simplifies the state machine to have the read
133-
// buffer at least this big. Note that we force the buffer to a
134-
// larger size below anyway.
135-
struct PACKED _rpi_information {
136-
uint8_t bytes[63];
137-
};
138-
139127
union PACKED {
140128
DEFINE_BYTE_ARRAY_METHODS
141129
_sensor_scan sensor_scan;
142130
_sensor_health sensor_health;
143131
_descriptor descriptor;
144-
_rpi_information information;
145132
_device_info device_info;
146-
uint8_t forced_buffer_size[256]; // just so we read(...) efficiently
147133
} _payload;
148-
static_assert(sizeof(_payload) >= 63, "Needed for parsing out reboot data");
149134

150135
enum class Model {
151136
UNKNOWN,
152137
A1,
153138
A2,
154139
C1,
155140
S1,
141+
S2,
156142
} model = Model::UNKNOWN;
157-
158-
bool make_first_byte_in_payload(uint8_t desired_byte);
159143
};
160144

161145
#endif // AP_PROXIMITY_RPLIDARA2_ENABLED

0 commit comments

Comments
 (0)