19 #define _USE_MATH_DEFINES
42 #define DEG2RAD M_PI/180.0
49 maxsize = bufferSize + 1;
52 elems = (
byte *)calloc(maxsize,
sizeof(
byte));
64 info =
"Fake Laser device for test/debugging";
65 device_status = DEVICE_OK_STANBY;
74 bool br = config.
check(
"GENERAL");
78 clip_max_enable = general_config.
check(
"clip_max");
79 clip_min_enable = general_config.
check(
"clip_min");
80 if (clip_max_enable) { max_distance = general_config.
find(
"clip_max").
asFloat64(); }
81 if (clip_min_enable) { min_distance = general_config.
find(
"clip_min").
asFloat64(); }
82 if (general_config.
check(
"max_angle") ==
false) {
yCError(
RPLIDAR) <<
"Missing max_angle param";
return false; }
83 if (general_config.
check(
"min_angle") ==
false) {
yCError(
RPLIDAR) <<
"Missing min_angle param";
return false; }
84 if (general_config.
check(
"resolution") ==
false) {
yCError(
RPLIDAR) <<
"Missing resolution param";
return false; }
88 do_not_clip_infinity_enable = (general_config.
find(
"allow_infinity").
asInt32()!=0);
96 bool bs = config.
check(
"SKIP");
102 size_t s_mins = mins.
size();
103 size_t s_maxs = mins.
size();
104 if (s_mins == s_maxs && s_maxs > 1 )
106 for (
size_t s = 1; s < s_maxs; s++)
111 if (range.
max >= 0 && range.
max <= 360 &&
112 range.
min >= 0 && range.
min <= 360 &&
115 range_skip_vector.push_back(range);
127 if (max_angle <= min_angle) {
yCError(
RPLIDAR) <<
"max_angle should be > min_angle";
return false; }
128 double fov = (max_angle - min_angle);
129 if (fov >360) {
yCError(
RPLIDAR) <<
"max_angle - min_angle <= 360";
return false; }
130 sensorsNum = (int)(fov/resolution);
131 laser_data.resize(sensorsNum,0.0);
134 yCInfo(
RPLIDAR,
"max_dist %f, min_dist %f", max_distance, min_distance);
135 yCInfo(
RPLIDAR,
"max_angle %f, min_angle %f", max_angle, min_angle);
140 bool ok = general_config.
check(
"Serial_Configuration");
143 yCError(
RPLIDAR,
"Cannot find configuration file for serial port communication!");
146 std::string serial_filename = general_config.
find(
"Serial_Configuration").
asString();
150 std::string serial_completefilename= rf.
findFileByName(serial_filename);
152 prop.
put(
"device",
"serialport");
156 yCError(
RPLIDAR,
"Unable to read from serial port configuration file");
162 if (!driver.isValid())
167 driver.view(pSerial);
170 yCError(
RPLIDAR,
"Error opening serial driver. Device not available");
175 int cleanup = pSerial->flush();
182 bool b_health = HW_getHealth();
183 if (b_health ==
false)
187 b_health = HW_getHealth();
188 if (b_health ==
false)
195 yCInfo(
RPLIDAR,
"Sensor recovered from a previous error status");
203 return PeriodicThread::start();
208 PeriodicThread::stop();
225 std::lock_guard<std::mutex> guard(mutex);
233 std::lock_guard<std::mutex> guard(mutex);
241 std::lock_guard<std::mutex> guard(mutex);
249 std::lock_guard<std::mutex> guard(mutex);
257 std::lock_guard<std::mutex> guard(mutex);
264 std::lock_guard<std::mutex> guard(mutex);
271 std::lock_guard<std::mutex> guard(mutex);
278 std::lock_guard<std::mutex> guard(mutex);
286 std::lock_guard<std::mutex> guard(mutex);
294 std::lock_guard<std::mutex> guard(mutex);
298 size_t size = laser_data.size();
300 if (max_angle < min_angle) {
yCError(
RPLIDAR) <<
"getLaserMeasurement failed";
return false; }
301 double laser_angle_of_view = max_angle - min_angle;
302 for (
size_t i = 0; i < size; i++)
304 double angle = (i / double(size)*laser_angle_of_view + min_angle)*
DEG2RAD;
305 data[i].set_polar(laser_data[i], angle);
312 std::lock_guard<std::mutex> guard(mutex);
313 status = device_status;
332 bool RpLidar::HW_getInfo(
string& s_info)
335 unsigned char cmd_arr[2];
338 pSerial->send((
char *)cmd_arr, 2);
342 unsigned char s[255];
343 r = pSerial->receiveBytes(s, 7);
350 if ((
unsigned char)s[0] != 0xA5 || (
unsigned char)s[1] != 0x5A || (
unsigned char)s[2] != 0x14 || (
unsigned char)s[6] != 0x04)
356 r = pSerial->receiveBytes(s, 20);
363 sprintf(info,
"model %d fw_major %d fw_minor %d hardware %d serial number %c%c%c%c%c %c%c%c%c%c %c%c%c%c%c%c",
364 s[0], s[1], s[2], s[3],
365 s[4], s[5], s[6], s[7], s[8],
366 s[9], s[10], s[11], s[12], s[13],
367 s[14], s[15], s[16], s[17], s[18], s[19]);
372 bool RpLidar::HW_getHealth()
377 unsigned char cmd_arr[2];
380 pSerial->send((
char *)cmd_arr, 2);
384 unsigned char s[255];
386 r = pSerial->receiveBytes(s,7);
393 if ((
unsigned char)s[0] != 0xA5 || (
unsigned char)s[1] != 0x5A || (
unsigned char)s[2] != 3 || (
unsigned char)s[6] != 0x06)
400 r = pSerial->receiveBytes(s,3);
408 int code = s[1] << 8 | s[2];
413 else if (status == 1)
418 else if (status == 2)
427 bool RpLidar::HW_reset()
431 unsigned char cmd_arr[2];
434 pSerial->send((
char *)cmd_arr, 2);
440 bool RpLidar::HW_start()
446 unsigned char cmd_arr[2];
453 pSerial->send((
char *)cmd_arr,2);
457 unsigned char s[255];
459 r = pSerial->receiveBytes(s, 7);
466 if ((
unsigned char)s[0] != 0xA5 || (
unsigned char)s[1] != 0x5A || (
unsigned char)s[2] != 0x05 ||
467 (
unsigned char)s[5] != 0x40 || (
unsigned char)s[6] != 0x81)
476 bool RpLidar::HW_stop()
480 unsigned char cmd_arr[2];
483 pSerial->send((
char*)cmd_arr,2);
489 #define DEBUG_LOCKING 1
496 const int packet = 100;
497 std::lock_guard<std::mutex> guard(mutex);
499 unsigned char buff[packet*3];
500 memset(buff, 0, packet*3);
503 static unsigned int total_r = 0;
504 unsigned int count = 0;
507 r = pSerial->receiveBytes(buff, packet);
508 #ifdef DEBUG_BYTES_READ_1
511 buffer->write_elems(buff, r);
514 #ifdef DEBUG_BYTES_READ_2
521 while (
buffer->size() < (packet * 2) || r < packet);
523 unsigned char minibuff[15];
524 unsigned int ok_count = 0;
525 bool new_scan =
false;
528 buffer->select_elems(minibuff,15);
530 int start = (minibuff[0]) & 0x01;
531 int lock = (minibuff[0] >> 1) & 0x01;
532 int check = (minibuff[1] & 0x01);
534 int start_n1 = (minibuff[5]) & 0x01;
535 int lock_n1 = (minibuff[5] >> 1) & 0x01;
536 int start_n2 = (minibuff[10]) & 0x01;
537 int lock_n2 = (minibuff[10] >> 1) & 0x01;
538 int check_n1 = (minibuff[6] & 0x01);
539 int check_n2 = (minibuff[11] & 0x01);
541 int quality = (minibuff[0] >> 2);
542 int i_angle = ((minibuff[2] >> 1) << 8) | (minibuff[1]);
543 int i_distance = (minibuff[4] << 8) | (minibuff[3]);
548 yCError(
RPLIDAR) <<
"lock error 1 " <<
"previous ok" << ok_count <<
"total r" << total_r;
550 buffer->throw_away_elem();
556 if (start_n1 == lock_n1)
559 yCError(
RPLIDAR) <<
"lock error 2 " <<
"previous ok" << ok_count <<
"total r" << total_r;
561 buffer->throw_away_elem();
567 if (start_n2 == lock_n2)
570 yCError(
RPLIDAR) <<
"lock error 3 " <<
"previous ok" << ok_count <<
"total r" << total_r;
572 buffer->throw_away_elem();
578 if (start == 1 && start_n1 == 1)
581 yCError(
RPLIDAR) <<
"lock error 4 " <<
"previous ok" << ok_count <<
"total r" << total_r;
583 buffer->throw_away_elem();
592 yCError(
RPLIDAR) <<
"checksum error 1" <<
"previous ok" << ok_count <<
"total r" << total_r;
594 buffer->throw_away_elem();
603 yCError(
RPLIDAR) <<
"checksum error 2" <<
"previous ok" << ok_count <<
"total r" << total_r;
605 buffer->throw_away_elem();
614 yCError(
RPLIDAR) <<
"checksum error 3" <<
"previous ok" << ok_count <<
"total r" << total_r;
616 buffer->throw_away_elem();
627 if (start == 1 && new_scan ==
false)
632 else if (start == 1 && new_scan ==
true)
638 double distance = i_distance / 4.0 / 1000;
639 double angle = i_angle / 64.0;
640 angle = (360 - angle) + 90;
641 if (angle >= 360) angle -= 360;
650 distance = std::numeric_limits<double>::infinity();
659 if (distance < min_distance)
660 distance = max_distance;
664 if (distance > max_distance)
666 if (!do_not_clip_infinity_enable && distance <= std::numeric_limits<double>::infinity())
668 distance = max_distance;
673 for (
auto& i : range_skip_vector)
675 if (angle > i.min && angle < i.max)
677 distance = std::numeric_limits<double>::infinity();
704 buffer->throw_away_elems(5);
706 int elem = (int)(angle / resolution);
707 if (elem >= 0 && elem < (
int)laser_data.size())
709 laser_data[elem] = distance;
713 yCDebug(
RPLIDAR) <<
"RpLidar::run() invalid angle: elem" << elem <<
">" <<
"laser_data.size()" << laser_data.size();
716 while (
buffer->size() > packet && isRunning() );
737 std::lock_guard<std::mutex> guard(mutex);