62 #define deg2rad_const (0.017453292519943295769236907684886f)
75 ROS_INFO(
"Software PLL locking started, mapping ticks to system time.");
81 if (packets_dropped < packets_expected_to_drop)
83 ROS_INFO_STREAM(
"" << packets_dropped <<
" / " << packets_expected_to_drop <<
" packets dropped. Software PLL not yet locked.");
85 else if (packets_dropped == packets_expected_to_drop)
87 ROS_INFO(
"Software PLL is ready and locked now!");
89 else if (packets_dropped > packets_expected_to_drop && packets_received > 0)
91 double drop_rate = (double)packets_dropped / (
double)packets_received;
93 << std::fixed << std::setprecision(1) << (100*drop_rate) <<
" perc.), maxAbsDeltaTime=" << std::fixed << std::setprecision(3) <<
SoftwarePLL::instance().max_abs_delta_time);
95 "Check the network connection.\n"
96 "Check if the system time has been changed in a leap.\n"
97 "If the problems can persist, disable the software PLL with the option sw_pll_only_publish=False !");
111 bool angle_slightly_modified =
false;
112 float pi_multiplier = *angle_val/M_PI;
116 if (pi_multiplier > 1.1 || pi_multiplier < -1.1)
118 ROS_WARN_STREAM(
"check_near_plus_minus_pi: min or max angle = " << *angle_val * 180 / M_PI <<
" degree, expected angle within -180 to +180 degree, check scan angle shift settings.");
120 else if (pi_multiplier > 1.0 - 10.0 * FLT_EPSILON || pi_multiplier < -1.0 + 10.0 * FLT_EPSILON)
122 float factor = (*angle_val < 0.0) ? (-1.0) : (1.0);
123 *angle_val = factor * (1.0 - FLT_EPSILON) * M_PI;
124 angle_slightly_modified =
true;
128 angle_slightly_modified =
false;
130 return(angle_slightly_modified);
142 int scanFrequencyX100 = 0;
143 double scanFrequency = 0.0;
144 long measurementFrequencyDiv100 = 0;
145 int numOfEncoders = 0;
146 int numberOf16BitChannels = 0;
147 int numberOf8BitChannels = 0;
148 uint32_t SystemCountScan = 0;
149 static uint32_t lastSystemCountScan = 0;
150 uint32_t SystemCountTransmit = 0;
152 memcpy(&elevAngleX200, receiveBuffer + 50, 2);
156 elevationAngleInRad = -elevAngleX200 * elevAngleTelegramValToDeg *
deg2rad_const;
161 memcpy(&SystemCountScan, receiveBuffer + 0x26, 4);
162 swap_endian((
unsigned char *) &SystemCountScan, 4);
165 memcpy(&SystemCountTransmit, receiveBuffer + 0x2A, 4);
166 swap_endian((
unsigned char *) &SystemCountTransmit, 4);
174 double timestampfloat =
sec(recvTimeStamp) +
nsec(recvTimeStamp) * 1e-9;
176 if (SystemCountScan !=
180 SystemCountTransmit);
181 lastSystemCountScan = SystemCountScan;
184 rosTime tmp_time = recvTimeStamp;
185 uint32_t recvTimeStampSec = (uint32_t)
sec(recvTimeStamp), recvTimeStampNsec = (uint32_t)
nsec(recvTimeStamp);
186 uint32_t lidar_ticks = SystemCountScan;
187 if(use_generation_timestamp == 0)
188 lidar_ticks = SystemCountTransmit;
191 recvTimeStamp =
rosTime(recvTimeStampSec, recvTimeStampNsec);
192 double timestampfloat_coor =
sec(recvTimeStamp) +
nsec(recvTimeStamp) * 1e-9;
193 double DeltaTime = timestampfloat - timestampfloat_coor;
197 if (config_sw_pll_only_publish ==
true)
202 #ifdef DEBUG_DUMP_ENABLED
203 double elevationAngleInDeg = elevationAngleInRad /
deg2rad_const;
213 memcpy(&scanFrequencyX100, receiveBuffer + 52, 4);
214 swap_endian((
unsigned char *) &scanFrequencyX100, 4);
216 memcpy(&measurementFrequencyDiv100, receiveBuffer + 56, 4);
217 swap_endian((
unsigned char *) &measurementFrequencyDiv100, 4);
220 msg.scan_time = 1.0 / (scanFrequencyX100 / 100.0);
223 if (measurementFrequencyDiv100 > 10000)
225 measurementFrequencyDiv100 /= 100;
227 if (measurementFrequencyDiv100 != 0)
229 msg.time_increment = 1.0 / (measurementFrequencyDiv100 * 100.0);
233 msg.time_increment = 0;
239 memcpy(&numOfEncoders, receiveBuffer + 60, 2);
242 int encoderDataOffset = 6 * numOfEncoders;
243 int32_t EncoderPosTicks[4] = {0};
244 int16_t EncoderSpeed[4] = {0};
246 if (numOfEncoders > 0 && numOfEncoders < 5)
249 for (
int EncoderNum = 0; EncoderNum < numOfEncoders; EncoderNum++)
251 memcpy(&EncoderPosTicks[EncoderNum], receiveBuffer + 62 + EncoderNum * 6, 4);
252 swap_endian((
unsigned char *) &EncoderPosTicks[EncoderNum], 4);
253 memcpy(&EncoderSpeed[EncoderNum], receiveBuffer + 66 + EncoderNum * 6, 2);
254 swap_endian((
unsigned char *) &EncoderSpeed[EncoderNum], 2);
258 EncoderMsg.enc_position = EncoderPosTicks[0];
259 EncoderMsg.enc_speed = EncoderSpeed[0];
260 memcpy(&numberOf16BitChannels, receiveBuffer + 62 + encoderDataOffset, 2);
261 swap_endian((
unsigned char *) &numberOf16BitChannels, 2);
263 int parseOff = 64 + encoderDataOffset;
266 char szChannel[255] = {0};
267 float scaleFactor = 1.0;
268 float scaleFactorOffset = 0.0;
269 int32_t startAngleDiv10000 = 1;
270 int32_t sizeOfSingleAngularStepDiv10000 = 1;
271 double startAngle = 0.0;
272 double sizeOfSingleAngularStep = 0.0;
273 short numberOfItems = 0;
279 for (
int i = 0; i < numberOf16BitChannels; i++)
281 int numberOfItems = 0x00;
282 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
285 parseOff += numberOfItems * 2;
289 memcpy(&numberOf8BitChannels, receiveBuffer + parseOff, 2);
290 swap_endian((
unsigned char *) &numberOf8BitChannels, 2);
292 parseOff = 64 + encoderDataOffset;
293 enum datagram_parse_task
304 int distChannelCnt = 0;
306 for (
int processLoop = 0; processLoop < 2; processLoop++)
308 int totalChannelCnt = 0;
313 datagram_parse_task task = process_idle;
314 bool parsePacket =
true;
315 parseOff = 64 + encoderDataOffset;
316 bool processData =
false;
318 if (processLoop == 0)
327 if (processLoop == 1)
330 numEchos = distChannelCnt;
331 msg.ranges.resize(numberOfItems * numEchos);
334 msg.intensities.resize(numberOfItems * rssiCnt);
341 vang_vec.resize(numberOfItems * vangleCnt);
349 azimuth_vec.resize(numberOfItems * azimuthCnt);
363 scaleFactorOffset = 0.0;
364 startAngleDiv10000 = 1;
365 sizeOfSingleAngularStepDiv10000 = 1;
367 sizeOfSingleAngularStep = 0.0;
371 #if 1 // prepared for multiecho parsing
379 int processDataLenValuesInBytes = 2;
381 if (totalChannelCnt == numberOf16BitChannels)
386 if (totalChannelCnt >= numberOf16BitChannels)
388 processDataLenValuesInBytes = 1;
391 strcpy(szChannel,
"");
393 if (totalChannelCnt < (numberOf16BitChannels + numberOf8BitChannels))
396 strncpy(szChannel, (
const char *) receiveBuffer + parseOff, 5);
403 if (strstr(szChannel,
"DIST") == szChannel)
409 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
412 if (strstr(szChannel,
"VANG") == szChannel)
418 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
420 vang_vec.resize(numberOfItems);
422 if (strstr(szChannel,
"ANGL") == szChannel)
425 task = process_azimuth;
428 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
430 azimuth_vec.resize(numberOfItems);
432 if (strstr(szChannel,
"RSSI") == szChannel)
439 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
445 scaleFactorOffset = 0.0;
446 startAngleDiv10000 = 0;
447 sizeOfSingleAngularStepDiv10000 = 0;
450 memcpy(&scaleFactor, receiveBuffer + parseOff + 5, 4);
451 memcpy(&scaleFactorOffset, receiveBuffer + parseOff + 9, 4);
452 memcpy(&startAngleDiv10000, receiveBuffer + parseOff + 13, 4);
453 memcpy(&sizeOfSingleAngularStepDiv10000, receiveBuffer + parseOff + 17, 2);
454 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
458 swap_endian((
unsigned char *) &scaleFactorOffset, 4);
459 swap_endian((
unsigned char *) &startAngleDiv10000, 4);
460 swap_endian((
unsigned char *) &sizeOfSingleAngularStepDiv10000, 2);
465 ROS_DEBUG_STREAM(
"LMDscandata: lidar_scan_time=" << SystemCountScan <<
" microsec, lidar_transmit_time=" << SystemCountTransmit <<
" microsec, "
466 <<
"scan_frequency=" << (0.01 * scanFrequencyX100) <<
" Hz, measurement_frequency=" << measurementFrequencyDiv100 <<
" Hz,"
467 <<
"start_angle=" << (0.0001 * startAngleDiv10000) <<
" [deg], angular_step="<< (0.0001 * sizeOfSingleAngularStepDiv10000) <<
" [deg]");
473 unsigned short *
data = (
unsigned short *) (receiveBuffer + parseOff + 21);
475 unsigned char *swapPtr = (
unsigned char *)
data;
478 i < numberOfItems * processDataLenValuesInBytes; i += processDataLenValuesInBytes)
480 if (processDataLenValuesInBytes == 1)
486 tmp = swapPtr[i + 1];
487 swapPtr[i + 1] = swapPtr[i];
498 startAngle = startAngleDiv10000 / 10000.00;
499 sizeOfSingleAngularStep = sizeOfSingleAngularStepDiv10000 / 10000.0;
500 sizeOfSingleAngularStep *= (M_PI / 180.0);
503 msg.angle_increment = sizeOfSingleAngularStep;
504 msg.angle_max =
msg.angle_min + (numberOfItems - 1) *
msg.angle_increment;
506 if(
msg.time_increment == 0)
515 msg.angle_min = (float)(-M_PI);
516 msg.angle_max = (float)(+M_PI);
517 msg.angle_increment *= -1.0;
518 if (
msg.angle_increment < 0.0)
523 msg.angle_min = (float)(+M_PI);
524 msg.angle_max = (float)(-M_PI);
529 msg.angle_min *= -1.0;
530 msg.angle_increment *= -1.0;
531 msg.angle_max *= -1.0;
534 ROS_DEBUG_STREAM(
"process_dist: msg.angle_min=" << (
msg.angle_min*180/M_PI) <<
", msg.angle_max=" << (
msg.angle_max*180/M_PI) <<
", msg.angle_increment=" << (
msg.angle_increment*180/M_PI) <<
", scaleFactor=" << scaleFactor <<
", scaleFactorOffset=" << scaleFactorOffset);
537 bool wrap_avoid =
false;
553 msg.angle_increment = (
msg.angle_max -
msg.angle_min) / (numberOfItems - 1);
555 ROS_DEBUG_STREAM(
"process_dist: msg.angle_min=" << (
msg.angle_min*180/M_PI) <<
", msg.angle_max=" << (
msg.angle_max*180/M_PI) <<
", msg.angle_increment=" << (
msg.angle_increment*180/M_PI) <<
", scaleFactor=" << scaleFactor <<
", scaleFactorOffset=" << scaleFactorOffset <<
", " << (8*processDataLenValuesInBytes) <<
"-bit channel");
557 float *rangePtr =
NULL;
559 if (numberOfItems > 0)
561 rangePtr = &
msg.ranges[0];
563 float scaleFactor_001 = 0.001F * scaleFactor;
564 for (
int i = 0; i < numberOfItems; i++)
566 idx = i + numberOfItems * (distChannelCnt - 1);
567 rangePtr[idx] = (float)
data[i] * scaleFactor_001 + scaleFactorOffset;
568 #ifdef DEBUG_DUMP_ENABLED
569 if (distChannelCnt == 1)
571 if (i == floor(numberOfItems / 2))
573 double curTimeStamp = SystemCountScan + i *
msg.time_increment * 1E6;
587 float *intensityPtr =
NULL;
589 if (numberOfItems > 0)
591 intensityPtr = &
msg.intensities[0];
594 for (
int i = 0; i < numberOfItems; i++)
596 idx = i + numberOfItems * (rssiCnt - 1);
599 if (processDataLenValuesInBytes == 2)
601 rssiVal = (float)
data[i];
605 unsigned char *data8Ptr = (
unsigned char *)
data;
606 rssiVal = (float) data8Ptr[i];
608 intensityPtr[idx] = rssiVal * scaleFactor + scaleFactorOffset;
614 if (numberOfItems > 0)
616 float *vangPtr = &vang_vec[0];
617 for (
int i = 0; i < numberOfItems; i++)
619 vangPtr[i] = (float)
data[i] * scaleFactor + scaleFactorOffset;
624 case process_azimuth:
625 if (numberOfItems > 0)
627 if (std::abs(scaleFactorOffset) <= FLT_EPSILON)
633 ROS_WARN_STREAM(
"## WARNING parseCommonBinaryResultTelegram(): process_azimuth with unexpected scaleFactorOffset=" << scaleFactorOffset <<
", expected value is not 0.0");
634 ROS_WARN_STREAM(
"## WARNING parseCommonBinaryResultTelegram(): set parameter scandatacfg_azimuth_table=0 in the launchfile if the lidar has no calibrated azimuth table.");
637 float angle_inc_rad = (1.0e-4
f * sizeOfSingleAngularStepDiv10000) * M_PI / 180.0;
638 float angle_max_rad = angle_min_rad + (numberOfItems - 1) * angle_inc_rad;
639 ROS_DEBUG_STREAM(
"process_dist: msg.angle_min=" << (
msg.angle_min*180/M_PI) <<
", msg.angle_max=" << (
msg.angle_max*180/M_PI) <<
", msg.angle_increment=" << (
msg.angle_increment*180/M_PI));
640 ROS_DEBUG_STREAM(
"process_azimuth: angle_min=" << (angle_min_rad*180/M_PI) <<
", angle_max=" << (angle_max_rad*180/M_PI) <<
", angle_inc=" << (angle_inc_rad*180/M_PI)
641 <<
", scaleFactor=" << scaleFactor <<
", scaleFactorOffset=" << scaleFactorOffset <<
", " << (8*processDataLenValuesInBytes) <<
"-bit channel");
644 float *azimuthPtr = &azimuth_vec[0];
645 if (processDataLenValuesInBytes == 1)
647 uint8_t* data_ptr = (uint8_t*)
data;
648 for (
int i = 0; i < numberOfItems; i++)
649 azimuthPtr[i] = (angle_min_rad + i * angle_inc_rad + (
float)(1.0e-4 * M_PI / 180.0) * ((float)data_ptr[i] * scaleFactor + scaleFactorOffset));
651 else if (processDataLenValuesInBytes == 2)
653 uint16_t* data_ptr = (uint16_t*)
data;
654 for (
int i = 0; i < numberOfItems; i++)
655 azimuthPtr[i] = (angle_min_rad + i * angle_inc_rad + (
float)(1.0e-4 * M_PI / 180.0) * ((float)data_ptr[i] * scaleFactor + scaleFactorOffset));
665 parseOff += 21 + processDataLenValuesInBytes * numberOfItems;
675 scanFrequency = scanFrequencyX100 / 100.0;