84 template <
typename T>
static inline T
readUnsigned(
const uint8_t* scandata, uint32_t* byte_cnt)
86 #if TARGET_IS_LITTLE_ENDIAN // src and dst have identical endianess
87 *byte_cnt +=
sizeof(T);
88 return (*((T*)scandata));
89 #else // src and dst have different endianess: reorder bytes
92 for (
int n = 0, m =
sizeof(T) - 1; n <
sizeof(T); n++,m--)
96 *byte_cnt +=
sizeof(T);
101 static inline float readFloat32(
const uint8_t* scandata, uint32_t* byte_cnt)
103 #if TARGET_IS_LITTLE_ENDIAN // src and dst have identical endianess
104 *byte_cnt +=
sizeof(float);
105 return (*((
float*)scandata));
106 #else // src and dst have different endianess: reorder bytes
109 for (
int n = 0, m =
sizeof(
float) - 1; n <
sizeof(float); n++,m--)
118 static inline bool endOfBuffer(uint32_t byte_cnt,
size_t bytes_to_read, uint32_t num_bytes)
120 return ((byte_cnt) + (bytes_to_read) > (num_bytes));
123 static void print_error(
const std::string& err_msg,
int line_number,
double print_rate = 1)
125 static std::map<int, std::chrono::system_clock::time_point> last_error_printed;
126 static std::map<int, size_t> error_cnt;
127 if (error_cnt[line_number] == 0 || std::chrono::duration<double>(
std::chrono::system_clock::now() - last_error_printed[line_number]).count() > 1/print_rate)
129 if (error_cnt[line_number] <= 1)
132 ROS_ERROR_STREAM(err_msg <<
" (error repeated " << error_cnt[line_number] <<
" times)");
134 error_cnt[line_number] = 0;
136 error_cnt[line_number] += 1;
139 #define CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt, bytes_to_read, module_size, name, line_number) \
140 if (((byte_required) = (byte_cnt) + (bytes_to_read)) > (module_size)) \
142 std::stringstream err_msg; \
143 err_msg << "## ERROR CompactDataParser::ParseModuleMetaData(): module_size=" << (module_size) << ", " \
144 << (byte_required) << " bytes required to read " << (name); \
145 print_error(err_msg.str(), line_number); \
175 description <<
", telegramVersion:" << telegramVersion;
176 description <<
", timeStampTransmit:" << timeStampTransmit;
183 description <<
", telegramCounter:" << telegramCounter;
193 description <<
"SegmentCounter:" << SegmentCounter;
196 description <<
", NumberOfLinesInModule:" << NumberOfLinesInModule;
197 description <<
", NumberOfBeamsPerScan:" << NumberOfBeamsPerScan;
198 description <<
", NumberOfEchosPerBeam:" << NumberOfEchosPerBeam;
200 for(
int n = 0; n < TimeStampStart.size(); n++)
203 for(
int n = 0; n < TimeStampStop.size(); n++)
206 for(
int n = 0; n < Phi.size(); n++)
209 for(
int n = 0; n < ThetaStart.size(); n++)
212 for(
int n = 0; n < ThetaStop.size(); n++)
214 description <<
"], DistanceScalingFactor:" << DistanceScalingFactor;
215 description <<
", NextModuleSize:" << NextModuleSize;
216 description <<
", Availability:" << (int)Availability;
217 description <<
", DataContentEchos:" << (int)DataContentEchos;
218 description <<
", DataContentBeams:" << (int)DataContentBeams;
227 for(
int group_idx = 0; group_idx < scandata.size(); group_idx++)
229 description << (group_idx > 0 ?
"," :
"") <<
"scandata[" << group_idx <<
"]=[";
230 const std::vector<ScanSegmentParserOutput::Scanline>& scanlines = scandata[group_idx].scanlines;
231 for(
int line_idx = 0; line_idx < scanlines.size(); line_idx++)
233 description << (line_idx > 0 ?
"," :
"") <<
"scanline[" << line_idx <<
"]=[";
234 for(
int point_idx = 0; point_idx < scanlines[line_idx].points.size(); point_idx++)
238 description << point.
x <<
"," << point.
y <<
"," << point.
z <<
"," << point.
i <<
",";
242 description <<
"]" << (scanlines.size() > 1 ?
"\n":
"");
244 description <<
"]" << (scandata.size() > 1 ?
"\n":
"");
256 uint32_t byte_cnt = 0;
258 header.commandId = readUnsigned<uint32_t>(scandata + byte_cnt, &byte_cnt);
259 if (
header.commandId == 1)
261 header.telegramCounter = readUnsigned<uint64_t>(scandata + byte_cnt, &byte_cnt);
262 header.timeStampTransmit = readUnsigned<uint64_t>(scandata + byte_cnt, &byte_cnt);
263 header.telegramVersion = readUnsigned<uint32_t>(scandata + byte_cnt, &byte_cnt);
264 header.sizeModule0 = readUnsigned<uint32_t>(scandata + byte_cnt, &byte_cnt);
266 else if (
header.commandId == 2)
268 header.telegramCounter = 0;
270 header.telegramVersion = readUnsigned<uint32_t>(scandata + byte_cnt, &byte_cnt);
281 header.timeStampTransmit = readUnsigned<uint64_t>(scandata + byte_cnt, &byte_cnt);
282 header.imudata.valid =
true;
286 ROS_WARN_STREAM(
"CompactDataParser::ParseHeader: header.commandId = " <<
header.commandId <<
" not supported");
322 uint32_t byte_cnt = 0, byte_required = 0;
325 module_metadata_size = 0;
327 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint64_t), module_size,
"SegmentCounter", __LINE__);
328 metadata.
SegmentCounter = readUnsigned<uint64_t>(scandata + byte_cnt, &byte_cnt);
330 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint64_t), module_size,
"FrameNumber", __LINE__);
331 metadata.
FrameNumber = readUnsigned<uint64_t>(scandata + byte_cnt, &byte_cnt);
333 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint32_t), module_size,
"SenderId", __LINE__);
334 metadata.
SenderId = readUnsigned<uint32_t>(scandata + byte_cnt, &byte_cnt);
336 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint32_t), module_size,
"NumberOfLinesInModule", __LINE__);
340 std::stringstream err_msg;
341 err_msg <<
"## ERROR CompactDataParser::ParseModuleMetaData(): unexpected NumberOfLinesInModule=" << metadata.
NumberOfLinesInModule;
345 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint32_t), module_size,
"NumberOfBeamsPerScan", __LINE__);
348 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint32_t), module_size,
"NumberOfEchosPerBeam", __LINE__);
355 metadata.
TimeStampStart.push_back(readUnsigned<uint64_t>(scandata + byte_cnt, &byte_cnt));
362 metadata.
TimeStampStop.push_back(readUnsigned<uint64_t>(scandata + byte_cnt, &byte_cnt));
369 float val =
readFloat32(scandata + byte_cnt, &byte_cnt);
370 metadata.
Phi.push_back(val);
377 float val =
readFloat32(scandata + byte_cnt, &byte_cnt);
385 float val =
readFloat32(scandata + byte_cnt, &byte_cnt);
389 if (telegramVersion == 3)
393 else if (telegramVersion == 4)
395 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(
float), module_size,
"DistanceScalingFactor", __LINE__);
400 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::ParseModuleMetaData(): telegramVersion=" << telegramVersion <<
" not supported");
404 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint32_t), module_size,
"NextModuleSize", __LINE__);
405 metadata.
NextModuleSize = readUnsigned<uint32_t>(scandata + byte_cnt, &byte_cnt);
407 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint8_t), module_size,
"Availability", __LINE__);
408 metadata.
Availability = readUnsigned<uint8_t>(scandata + byte_cnt, &byte_cnt);
410 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint8_t), module_size,
"DataContentEchos", __LINE__);
411 metadata.
DataContentEchos = readUnsigned<uint8_t>(scandata + byte_cnt, &byte_cnt);
413 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint8_t), module_size,
"DataContentBeams", __LINE__);
414 metadata.
DataContentBeams = readUnsigned<uint8_t>(scandata + byte_cnt, &byte_cnt);
416 CHECK_MODULE_SIZE(metadata, byte_required, byte_cnt,
sizeof(uint8_t), module_size,
"reserved", __LINE__);
417 metadata.
reserved = readUnsigned<uint8_t>(scandata + byte_cnt, &byte_cnt);
419 metadata.
valid =
true;
420 module_metadata_size = byte_cnt;
444 int layer_elevation_mdeg = (int)std::lround(layer_elevation_rad * 180000 / M_PI);
452 if (elevation_dist > dist)
454 elevation_dist = dist;
466 static std::map<int,int> elevation_layerid_map;
467 if (elevation_layerid_map.find(layer_elevation_mdeg) == elevation_layerid_map.end())
469 elevation_layerid_map[layer_elevation_mdeg] = elevation_layerid_map.size() + 1;
471 for(std::map<int,int>::iterator iter_layerid_map = elevation_layerid_map.begin(); iter_layerid_map != elevation_layerid_map.end(); iter_layerid_map++)
472 iter_layerid_map->second = layerid++;
474 return elevation_layerid_map[layer_elevation_mdeg];
505 measurement_data.
valid =
false;
510 ROS_ERROR_STREAM(
"CompactDataParser::ParseModuleMeasurementData(): invalid meta_data: { " << meta_data.
to_string() <<
" }");
521 measurement_data.
scandata = std::vector<ScanSegmentParserOutput::Scangroup>(num_layers);
523 ROS_DEBUG_STREAM(
"CompactDataParser::ParseModuleMeasurementData(): num_bytes=" << num_bytes <<
", num_layers=" << num_layers
525 <<
", rssi_available=" << rssi_available <<
", beam_prop_available=" << beam_prop_available
526 <<
", beam_azim_available=" << beam_azim_available);
528 std::vector<float> lut_layer_elevation(num_layers);
529 std::vector<float> lut_layer_azimuth_start(num_layers);
530 std::vector<float> lut_layer_azimuth_stop(num_layers);
531 std::vector<float> lut_layer_azimuth_delta(num_layers);
532 std::vector<uint64_t> lut_layer_lidar_timestamp_microsec_start(num_layers);
533 std::vector<uint64_t> lut_layer_lidar_timestamp_microsec_stop(num_layers);
534 std::vector<float> lut_sin_elevation(num_layers);
535 std::vector<float> lut_cos_elevation(num_layers);
536 std::vector<int> lut_groupIdx(num_layers);
538 for (uint32_t layer_idx = 0; layer_idx < num_layers; layer_idx++)
540 uint32_t layer_timeStamp_start_sec = (meta_data.
TimeStampStart[layer_idx] / 1000000);
541 uint32_t layer_timeStamp_start_nsec = 1000 * (meta_data.
TimeStampStart[layer_idx] % 1000000);
542 uint32_t layer_timeStamp_stop_sec = (meta_data.
TimeStampStop[layer_idx] / 1000000);
543 uint32_t layer_timeStamp_stop_nsec = 1000 * (meta_data.
TimeStampStop[layer_idx] % 1000000);
544 measurement_data.
scandata[layer_idx].timestampStart_sec = layer_timeStamp_start_sec;
545 measurement_data.
scandata[layer_idx].timestampStart_nsec = layer_timeStamp_start_nsec;
546 measurement_data.
scandata[layer_idx].timestampStop_sec = layer_timeStamp_stop_sec;
547 measurement_data.
scandata[layer_idx].timestampStop_nsec = layer_timeStamp_stop_nsec;
548 measurement_data.
scandata[layer_idx].scanlines = std::vector<ScanSegmentParserOutput::Scanline>(
num_echos);
549 for (uint32_t echo_idx = 0; echo_idx <
num_echos; echo_idx++)
551 measurement_data.
scandata[layer_idx].scanlines[echo_idx].points = std::vector<ScanSegmentParserOutput::LidarPoint>(meta_data.
NumberOfBeamsPerScan);
553 lut_layer_elevation[layer_idx] = -meta_data.
Phi[layer_idx];
554 lut_layer_azimuth_start[layer_idx] = meta_data.
ThetaStart[layer_idx];
555 lut_layer_azimuth_stop[layer_idx] = meta_data.
ThetaStop[layer_idx];
556 lut_layer_azimuth_delta[layer_idx] = (lut_layer_azimuth_stop[layer_idx] - lut_layer_azimuth_start[layer_idx]) / (
float)(std::max(1, (
int)meta_data.
NumberOfBeamsPerScan - 1));
557 lut_layer_lidar_timestamp_microsec_start[layer_idx] = meta_data.
TimeStampStart[layer_idx];
558 lut_layer_lidar_timestamp_microsec_stop[layer_idx] = meta_data.
TimeStampStop[layer_idx];
559 lut_sin_elevation[layer_idx] = std::sin(lut_layer_elevation[layer_idx]);
560 lut_cos_elevation[layer_idx] = std::cos(lut_layer_elevation[layer_idx]);
561 lut_groupIdx[layer_idx] = GetLayerIDfromElevation(meta_data.
Phi[layer_idx]);
564 uint32_t byte_cnt = 0;
567 for (uint32_t layer_idx = 0; layer_idx < num_layers; layer_idx++)
569 float layer_elevation = lut_layer_elevation[layer_idx];
570 float layer_azimuth_start = lut_layer_azimuth_start[layer_idx];
571 float layer_azimuth_stop = lut_layer_azimuth_stop[layer_idx];
572 float layer_azimuth_delta = lut_layer_azimuth_delta[layer_idx];
573 uint64_t lidar_timestamp_microsec_start = lut_layer_lidar_timestamp_microsec_start[layer_idx];
574 uint64_t lidar_timestamp_microsec_stop = lut_layer_lidar_timestamp_microsec_stop[layer_idx];
575 uint64_t lidar_timestamp_microsec = ((point_idx * (lidar_timestamp_microsec_stop - lidar_timestamp_microsec_start)) / (meta_data.
NumberOfBeamsPerScan - 1)) + lidar_timestamp_microsec_start;
576 float sin_elevation = lut_sin_elevation[layer_idx];
577 float cos_elevation = lut_cos_elevation[layer_idx];
578 int groupIdx = lut_groupIdx[layer_idx];
579 std::vector<ScanSegmentParserOutput::LidarPoint> points(
num_echos);
580 uint8_t beam_property = 0;
582 for (uint32_t echo_idx = 0; echo_idx <
num_echos; echo_idx++)
586 if (
endOfBuffer(byte_cnt,
sizeof(uint16_t), num_bytes))
588 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::ParseModuleMeasurementData(" << __LINE__ <<
"): byte_cnt=" << byte_cnt <<
", num_bytes=" << num_bytes <<
", layer " << layer_idx <<
" of " << num_layers
592 points[echo_idx].range = (dist_scale_factor * (float)readUnsigned<uint16_t>(
payload + byte_cnt, &byte_cnt)) / 1000.0
f;
596 if (
endOfBuffer(byte_cnt,
sizeof(uint16_t), num_bytes))
598 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::ParseModuleMeasurementData(" << __LINE__ <<
"): byte_cnt=" << byte_cnt <<
", num_bytes=" << num_bytes <<
", layer " << layer_idx <<
" of " << num_layers
602 points[echo_idx].i = (float)readUnsigned<uint16_t>(
payload + byte_cnt, &byte_cnt);
605 std::vector<ReadBeamAzimOrderEnum> azim_prop_order;
616 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::ParseModuleMeasurementData(" << __LINE__ <<
"): telegramVersion=" << compact_header.
telegramVersion <<
" not supported");
619 for (
int azim_prop_cnt = 0; azim_prop_cnt < 2; azim_prop_cnt++)
623 if (beam_azim_available)
625 if (
endOfBuffer(byte_cnt,
sizeof(uint16_t), num_bytes))
627 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::ParseModuleMeasurementData(" << __LINE__ <<
"): byte_cnt=" << byte_cnt <<
", num_bytes=" << num_bytes <<
", layer " << layer_idx <<
" of " << num_layers
631 azimuth = ((float)readUnsigned<uint16_t>(
payload + byte_cnt, &byte_cnt) - 16384.0f) / 5215.0
f + azimuth_offset;
635 azimuth = layer_azimuth_start + point_idx * layer_azimuth_delta + azimuth_offset;
640 if (beam_prop_available)
642 if (byte_cnt +
sizeof(uint8_t) > num_bytes)
644 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::ParseModuleMeasurementData(" << __LINE__ <<
"): byte_cnt=" << byte_cnt <<
", num_bytes=" << num_bytes <<
", layer " << layer_idx <<
" of " << num_layers
648 beam_property = readUnsigned<uint8_t>(
payload + byte_cnt, &byte_cnt);
652 float sin_azimuth = std::sin(azimuth);
653 float cos_azimuth = std::cos(azimuth);
660 for (uint32_t echo_idx = 0; echo_idx <
num_echos; echo_idx++)
662 points[echo_idx].azimuth = azimuth;
663 points[echo_idx].elevation = layer_elevation;
664 points[echo_idx].x = points[echo_idx].range * cos_azimuth * cos_elevation;
665 points[echo_idx].y = points[echo_idx].range * sin_azimuth * cos_elevation;
666 points[echo_idx].z = points[echo_idx].range * sin_elevation;
667 points[echo_idx].echoIdx = echo_idx;
668 points[echo_idx].groupIdx = groupIdx;
669 points[echo_idx].pointIdx = point_idx;
670 points[echo_idx].lidar_timestamp_microsec = lidar_timestamp_microsec;
671 points[echo_idx].reflectorbit |= (beam_property & 0x01);
672 measurement_data.
scandata[layer_idx].scanlines[echo_idx].points[point_idx] = points[echo_idx];
676 if (byte_cnt != num_bytes)
678 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::ParseModuleMeasurementData(" << __LINE__ <<
"): byte_cnt=" << byte_cnt <<
", num_bytes=" << num_bytes);
681 measurement_data.
valid =
true;
682 return measurement_data.
valid;
696 uint32_t& payload_length_bytes, uint32_t& num_bytes_required ,
float azimuth_offset,
int verbose)
699 const uint32_t header_size_bytes = 32;
700 const std::vector<uint8_t> msg_start_seq = { 0x02, 0x02, 0x02, 0x02 };
702 if(bytes_received >= 32)
714 ROS_INFO_STREAM(
"CompactDataParser::ParseSegment(): " << bytes_received <<
" bytes received (compact), at least " << (msg_start_seq.size() + 32) <<
" bytes required for compact data header");
716 payload_length_bytes = 0;
717 num_bytes_required = msg_start_seq.size() + 32;
727 payload_length_bytes = 60;
728 num_bytes_required = 64;
733 uint32_t module_offset = header_size_bytes;
734 payload_length_bytes = header_size_bytes;
735 num_bytes_required = header_size_bytes;
737 while (module_size > 0)
739 if (module_offset + module_size > bytes_received)
743 ROS_INFO_STREAM(
"CompactDataParser::ParseSegment(): " << bytes_received <<
" bytes received (compact), at least " << (module_offset + module_size) <<
" bytes required for module meta data");
745 payload_length_bytes = 0;
746 num_bytes_required = module_offset + module_size;
749 uint32_t module_metadata_size = 0;
753 ROS_INFO_STREAM(
"CompactDataParser::ParseSegment(): module meta data = { " << module_meta_data.
to_string() <<
" }");
755 if (module_meta_data.
valid !=
true || module_size < module_metadata_size)
757 std::stringstream err_msg;
758 err_msg <<
"## ERROR CompactDataParser::ParseSegment(): " << bytes_received <<
" bytes received (compact), CompactDataParser::ParseModuleMetaData() failed";
760 payload_length_bytes = 0;
761 num_bytes_required = module_offset + module_size;
783 module_offset += module_size;
784 payload_length_bytes += module_size;
785 num_bytes_required = payload_length_bytes;
788 if (segment_data &&
verbose > 0)
791 for(
int module_idx = 0; module_idx < segment_data->
segmentModules.size(); module_idx++)
793 const std::vector<ScanSegmentParserOutput::Scangroup>& scandata = segment_data->
segmentModules[module_idx].moduleMeasurement.scandata;
794 ROS_INFO_STREAM(
" CompactDataParser (module " << module_idx <<
"): " << scandata.size() <<
" groups");
795 for(
int group_idx = 0; group_idx < scandata.size(); group_idx++)
797 ROS_INFO_STREAM(
" CompactDataParser (module " << module_idx <<
", group " << group_idx <<
"): " << scandata[group_idx].scanlines.size() <<
" lines");
798 for(
int line_idx = 0; line_idx < scandata[group_idx].scanlines.size(); line_idx++)
800 const std::vector<ScanSegmentParserOutput::LidarPoint>& points = scandata[group_idx].scanlines[line_idx].points;
801 ROS_INFO_STREAM(
" CompactDataParser (module " << module_idx <<
", group " << group_idx <<
", line " << line_idx <<
"): " << points.size() <<
" points");
802 for(
int point_idx = 0; point_idx < points.size(); point_idx++)
804 ROS_INFO_STREAM(
" [" << points[point_idx].x <<
"," << points[point_idx].y <<
"," << points[point_idx].z <<
"," << points[point_idx].range <<
"," << points[point_idx].azimuth <<
"," << points[point_idx].elevation <<
"," << points[point_idx].groupIdx <<
"," << points[point_idx].pointIdx <<
"]");
813 #define EXPORT_MEASUREMENT_AZIMUTH_ACCELERATION_CSV 0 // Measurement of IMU latency (development only): Export ticks (imu resp. lidar timestamp in micro seconds), imu acceleration and lidar max azimuth of board cube
814 #if EXPORT_MEASUREMENT_AZIMUTH_ACCELERATION_CSV
819 static bool getMaxAzimuthApertureWithinCube(
const std::vector<sick_scansegment_xd::ScanSegmentParserOutput::Scangroup>& scandata,
820 float x_min,
float x_max,
float y_min,
float y_max,
float z_min,
float z_max,
float azimuth_min,
float azimuth_max,
821 double& azimuth_aperture, uint64_t& timestamp_microsec)
823 bool success =
false;
824 azimuth_aperture = 0;
825 timestamp_microsec = 0;
826 for(
int group_idx = 0; group_idx < scandata.size(); group_idx++)
828 for(
int line_idx = 0; line_idx < scandata[group_idx].scanlines.size(); line_idx++)
830 uint64_t timestampStart_microsec = (uint64_t)scandata[group_idx].timestampStart_sec * 1000000UL + (uint64_t)scandata[group_idx].timestampStart_nsec / 1000;
831 uint64_t timestampStop_microsec = (uint64_t)scandata[group_idx].timestampStop_sec * 1000000UL + (uint64_t)scandata[group_idx].timestampStop_nsec / 1000;
832 double point_azi_min = FLT_MAX, point_azi_max = -FLT_MAX;
833 for(
int point_idx = 0; point_idx < scandata[group_idx].scanlines[line_idx].points.size(); point_idx++)
836 if (p.
x >= x_min && p.
x <= x_max && p.
y >= y_min && p.
y <= y_max && p.
z >= z_min && p.
z<= z_max && p.
azimuth >= azimuth_min && p.
azimuth <= azimuth_max)
838 point_azi_min = std::min(point_azi_min, (
double)p.
azimuth);
839 point_azi_max = std::max(point_azi_max, (
double)p.
azimuth);
842 if (point_azi_max > point_azi_min && azimuth_aperture < point_azi_max)
844 azimuth_aperture = point_azi_max;
845 timestamp_microsec = timestampStart_microsec;
852 #endif // EXPORT_MEASUREMENT_AZIMUTH_ACCELERATION_CSV
869 uint32_t payload_length_bytes = 0, num_bytes_required = 0;
881 for (
int module_idx = 0; module_idx < segment_data.
segmentModules.size(); module_idx++)
885 if (!moduleMeasurement.
valid)
887 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::Parse(): invalid moduleMeasurement (ignored)");
890 for (
int measurement_idx = 0; measurement_idx < moduleMeasurement.
scandata.size(); measurement_idx++)
894 for(
int line_idx = 0; line_idx < scandata.
scanlines.size(); line_idx++)
896 std::vector<ScanSegmentParserOutput::LidarPoint>& points_in = scandata.
scanlines[line_idx].points;
897 std::vector<ScanSegmentParserOutput::LidarPoint> points_out;
898 points_out.reserve(points_in.size());
899 for(
int point_idx = 0; point_idx < points_in.size(); point_idx++)
901 add_transform_xyz_rpy.
applyTransform(points_in[point_idx].x, points_in[point_idx].y, points_in[point_idx].z);
902 points_out.push_back(points_in[point_idx]);
904 scandata.
scanlines[line_idx].points = points_out;
909 for(
int line_idx = 0; line_idx < scandata.
scanlines.size(); line_idx++)
911 std::vector<ScanSegmentParserOutput::LidarPoint>& points = scandata.
scanlines[line_idx].points;
912 for(
int point_idx = 0; point_idx < points.size(); point_idx++)
917 while(result.
scandata.size() <= groupIdx)
921 if (result.
scandata[groupIdx].scanlines.empty())
928 while(result.
scandata[groupIdx].scanlines.size() <= echoIdx)
932 if (result.
scandata[groupIdx].scanlines[echoIdx].points.empty())
934 result.
scandata[groupIdx].scanlines[echoIdx].points.reserve(points.size());
936 result.
scandata[groupIdx].scanlines[echoIdx].points.push_back(point);
946 ROS_WARN_STREAM(
"## WARNING CompactDataParser::Parse(): different SegmentCounter in module 0 and module " << module_idx <<
" currently not supported,"
952 ROS_ERROR_STREAM(
"## ERROR CompactDataParser::Parse(): CompactDataParser::ParseSegment() failed (no scandata found)");
960 sensor_timeStamp = (uint64_t)result.
scandata[0].timestampStart_sec * 1000000UL + (uint64_t)result.
scandata[0].timestampStart_nsec / 1000;
963 if (use_software_pll)
966 int64_t systemtime_nanoseconds = system_timestamp.time_since_epoch().count();
967 uint32_t systemtime_sec = (uint32_t)(systemtime_nanoseconds / 1000000000);
968 uint32_t systemtime_nsec = (uint32_t)(systemtime_nanoseconds % 1000000000);
969 software_pll.
updatePLL(systemtime_sec, systemtime_nsec, sensor_timeStamp);
972 uint32_t pll_sec = 0, pll_nsec = 0;
980 #if EXPORT_MEASUREMENT_AZIMUTH_ACCELERATION_CSV // Measurement of IMU latency (development only): Export ticks (imu resp. lidar timestamp in micro seconds), imu acceleration and lidar max azimuth of board cube
984 std::ofstream csv_ostream(
"/tmp/imu_latency.csv", std::ios::app);
989 uint64_t timestamp_microsec_azi = 0;
990 double azimuth_aperture = 0;
991 if (getMaxAzimuthApertureWithinCube(result.
scandata, 0.5f, 1.5f, -1.0f, +1.0f, -1.0f, +1.0f, -M_PI, +M_PI, azimuth_aperture, timestamp_microsec_azi))
993 std::ofstream csv_ostream(
"/tmp/imu_latency.csv", std::ios::app);
994 csv_ostream << timestamp_microsec_azi <<
";" << std::fixed << std::setprecision(3) << (azimuth_aperture * 180 / M_PI) <<
";" <<
"\n";
997 #endif // EXPORT_MEASUREMENT_AZIMUTH_ACCELERATION_CSV