88 while (angle_rad > (
float)(M_PI))
89 angle_rad -= (float)(2.0 * M_PI);
90 while (angle_rad < (
float)(-M_PI))
91 angle_rad += (float)(2.0 * M_PI);
147 #define MsgpackKeyToInt_class 0x10 // sick_scansegment_xd::MsgpackKeyToInt("class")
148 #define MsgpackKeyToInt_data 0x11 // sick_scansegment_xd::MsgpackKeyToInt("data")
149 #define MsgpackKeyToInt_numOfElems 0x12 // sick_scansegment_xd::MsgpackKeyToInt("numOfElems")
150 #define MsgpackKeyToInt_elemSz 0x13 // sick_scansegment_xd::MsgpackKeyToInt("elemSz")
151 #define MsgpackKeyToInt_endian 0x14 // sick_scansegment_xd::MsgpackKeyToInt("endian")
152 #define MsgpackKeyToInt_elemTypes 0x15 // sick_scansegment_xd::MsgpackKeyToInt("elemTypes")
153 #define MsgpackKeyToInt_little 0x30 // sick_scansegment_xd::MsgpackKeyToInt("little")
154 #define MsgpackKeyToInt_float32 0x31 // sick_scansegment_xd::MsgpackKeyToInt("float32")
155 #define MsgpackKeyToInt_uint32 0x32 // sick_scansegment_xd::MsgpackKeyToInt("uint32")
156 #define MsgpackKeyToInt_uint8 0x33 // sick_scansegment_xd::MsgpackKeyToInt("uint8")
157 #define MsgpackKeyToInt_uint16 0x34 // sick_scansegment_xd::MsgpackKeyToInt("uint16")
158 #define MsgpackKeyToInt_ChannelTheta 0x50 // sick_scansegment_xd::MsgpackKeyToInt("ChannelTheta")
159 #define MsgpackKeyToInt_ChannelPhi 0x51 // sick_scansegment_xd::MsgpackKeyToInt("ChannelPhi")
160 #define MsgpackKeyToInt_DistValues 0x52 // sick_scansegment_xd::MsgpackKeyToInt("DistValues")
161 #define MsgpackKeyToInt_RssiValues 0x53 // sick_scansegment_xd::MsgpackKeyToInt("RssiValues")
162 #define MsgpackKeyToInt_PropertiesValues 0x54 // sick_scansegment_xd::MsgpackKeyToInt("PropertiesValues")
163 #define MsgpackKeyToInt_Scan 0x70 // sick_scansegment_xd::MsgpackKeyToInt("Scan")
164 #define MsgpackKeyToInt_TimestampStart 0x71 // sick_scansegment_xd::MsgpackKeyToInt("TimestampStart")
165 #define MsgpackKeyToInt_TimestampStop 0x72 // sick_scansegment_xd::MsgpackKeyToInt("TimestampStop")
166 #define MsgpackKeyToInt_ThetaStart 0x73 // sick_scansegment_xd::MsgpackKeyToInt("ThetaStart")
167 #define MsgpackKeyToInt_ThetaStop 0x74 // sick_scansegment_xd::MsgpackKeyToInt("ThetaStop")
168 #define MsgpackKeyToInt_ScanNumber 0x75 // sick_scansegment_xd::MsgpackKeyToInt("ScanNumber")
169 #define MsgpackKeyToInt_ModuleId 0x76 // sick_scansegment_xd::MsgpackKeyToInt("ModuleId")
170 #define MsgpackKeyToInt_BeamCount 0x77 // sick_scansegment_xd::MsgpackKeyToInt("BeamCount")
171 #define MsgpackKeyToInt_EchoCount 0x78 // sick_scansegment_xd::MsgpackKeyToInt("EchoCount")
172 #define MsgpackKeyToInt_ScanSegment 0x90 // sick_scansegment_xd::MsgpackKeyToInt("ScanSegment")
173 #define MsgpackKeyToInt_SegmentCounter 0x91 // sick_scansegment_xd::MsgpackKeyToInt("SegmentCounter")
174 #define MsgpackKeyToInt_FrameNumber 0x92 // sick_scansegment_xd::MsgpackKeyToInt("FrameNumber")
175 #define MsgpackKeyToInt_Availability 0x93 // sick_scansegment_xd::MsgpackKeyToInt("Availability")
176 #define MsgpackKeyToInt_SenderId 0x94 // sick_scansegment_xd::MsgpackKeyToInt("SenderId")
177 #define MsgpackKeyToInt_SegmentSize 0x95 // sick_scansegment_xd::MsgpackKeyToInt("SegmentSize")
178 #define MsgpackKeyToInt_SegmentData 0x96 // sick_scansegment_xd::MsgpackKeyToInt("SegmentData")
179 #define MsgpackKeyToInt_LayerId 0xA0 // sick_scansegment_xd::MsgpackKeyToInt("LayerId")
180 #define MsgpackKeyToInt_TelegramCounter 0xB0 // sick_scansegment_xd::MsgpackKeyToInt("TelegramCounter")
181 #define MsgpackKeyToInt_TimestampTransmit 0xB1 // sick_scansegment_xd::MsgpackKeyToInt("TimestampTransmit")
182 #define MsgpackKeyToInt_MaxValue 0xB2 // max allowed value of a msgpack key
250 s <<
msg.number_value();
252 s <<
"\"" <<
msg.string_value() <<
"\"";
254 s << (
msg.bool_value() ?
"true" :
"false");
255 if (!
msg.array_items().empty())
258 for (
int n = 0; n <
msg.array_items().size(); n++)
262 if (!
msg.binary_items().empty())
265 for (
int n = 0; n <
msg.binary_items().size(); n++)
269 if (!
msg.object_items().empty())
273 for (msgpack11::MsgPack::object::const_iterator iter_item =
msg.object_items().cbegin(); iter_item !=
msg.object_items().cend(); iter_item++, n++)
317 union FLOAT_4BYTE_UNION
324 union UINT_2BYTE_UNION
340 int binary_size = (int)(binary_items.size());
341 m_data.reserve(binary_size / elem_size);
344 FLOAT_4BYTE_UNION elem_buffer;
345 if (srcIsBigEndian == dstIsBigEndian)
347 for (
int n = 0; n < binary_size; n += 4)
349 elem_buffer.u32_bytes = *((uint32_t*)(&binary_items[n]));
350 m_data.push_back(elem_buffer.value);
355 for (
int n = 0; n < binary_size; n += 4)
357 elem_buffer.u8_bytes[3] = binary_items[n + 0];
358 elem_buffer.u8_bytes[2] = binary_items[n + 1];
359 elem_buffer.u8_bytes[1] = binary_items[n + 2];
360 elem_buffer.u8_bytes[0] = binary_items[n + 3];
361 m_data.push_back(elem_buffer.value);
367 UINT_2BYTE_UNION elem_buffer;
368 if (srcIsBigEndian == dstIsBigEndian)
370 for (
int n = 0; n < binary_size; n += 2)
372 elem_buffer.u16_bytes = *((uint16_t*)(&binary_items[n]));
373 m_data.push_back((
float)elem_buffer.u16_bytes);
378 for (
int n = 0; n < binary_size; n += 2)
380 elem_buffer.u8_bytes[1] = binary_items[n + 0];
381 elem_buffer.u8_bytes[0] = binary_items[n + 1];
382 m_data.push_back((
float)elem_buffer.u16_bytes);
388 std::cerr <<
"## ERROR MsgPackToFloat32VectorConverter: invalid or unsupported elemSz or elemTypes:" << std::endl
401 for(
int n = 1; n <
m_data.size(); n++)
406 float rad2deg(
float angle)
const {
return angle * (float)(180.0 / M_PI); }
413 for(
int n = 1; n <
m_data.size(); n++)
433 std::ifstream file_istream(filepath, std::ios::binary);
434 if (file_istream.is_open())
435 return std::vector<uint8_t>((std::istreambuf_iterator<char>(file_istream)), std::istreambuf_iterator<char>());
436 return std::vector<uint8_t>();
445 std::stringstream msgpack_hexdump;
446 for (
size_t n = 0; n < msgpack_data.size(); n++)
448 msgpack_hexdump << std::setfill(
'0') << std::setw(2) << std::hex << (int)(msgpack_data[n] & 0xFF);
452 msgpack_hexdump << std::endl;
454 msgpack_hexdump <<
" ";
457 return msgpack_hexdump.str();
484 bool msgpack_validator_enabled,
bool discard_msgpacks_not_validated,
485 bool use_software_pll,
bool verbose)
496 std::string msgpack_string((
char*)msgpack_data.data(), msgpack_data.size());
497 std::istringstream msgpack_istream(msgpack_string);
498 return Parse(msgpack_istream, msgpack_timestamp, add_transform_xyz_rpy, result, msgpack_validator_data_collector, msgpack_validator, msgpack_validator_enabled, discard_msgpacks_not_validated, use_software_pll,
verbose);
542 bool msgpack_validator_enabled,
bool discard_msgpacks_not_validated,
543 bool use_software_pll,
bool verbose)
545 int64_t systemtime_nanoseconds = msgpack_timestamp.time_since_epoch().count();
546 uint32_t systemtime_sec = (uint32_t)(systemtime_nanoseconds / 1000000000);
547 uint32_t systemtime_nsec = (uint32_t)(systemtime_nanoseconds % 1000000000);
551 int32_t segment_idx = messageCount++;
552 int32_t telegram_cnt = telegramCount++;
557 std::string msg_parse_error;
559 if (!msg_parse_error.empty())
561 ROS_ERROR_STREAM(
"## ERROR msgpack11::MsgPack::parse(): " << msg_parse_error);
566 catch(
const std::exception & exc)
568 ROS_ERROR_STREAM(
"## ERROR msgpack11::MsgPack::parse(): exception " << exc.what());
583 if (root_data_iter == msg_unpacked.
object_items().end())
585 ROS_WARN_STREAM(
"## ERROR MsgPackParser::Parse(): \"data\" not found");
593 ROS_WARN_STREAM(
"## ERROR MsgPackParser::Parse(): \"SegmentData\" and/or \"TimestampTransmit\" not found");
598 if (use_software_pll && timestamp_data.
is_number())
605 software_pll.
updatePLL(systemtime_sec, systemtime_nsec, curtick);
608 uint32_t pll_sec = 0, pll_nsec = 0;
620 if (segment_counter_iter == root_data.
object_items().end())
622 ROS_WARN_STREAM(
"## ERROR MsgPackParser::Parse(): \"SegmentCounter\" not found");
629 if (telegram_counter_iter != root_data.
object_items().end())
633 telegram_cnt = telegramCount;
639 for (
int groupIdx = 0; groupIdx < group_data.
array_items().size(); groupIdx++)
657 if (echoCountMsg == dataMsg->second.object_items().end() ||
658 channelPhiMsg == dataMsg->second.object_items().end() || channelThetaMsg == dataMsg->second.object_items().end() ||
659 distValuesMsg == dataMsg->second.object_items().end() || rssiValuesMsg == dataMsg->second.object_items().end() ||
660 timestampStartMsg == dataMsg->second.object_items().end() || timestampStopMsg == dataMsg->second.object_items().end())
662 ROS_WARN_STREAM(
"## ERROR MsgPackParser::Parse(): Entries in data segment missing");
665 uint32_t u32TimestampStart = timestampStartMsg->second.uint32_value();
666 uint32_t u32TimestampStop = timestampStopMsg->second.uint32_value();
667 uint32_t u32TimestampStart_sec = 0, u32TimestampStart_nsec = 0;
668 uint32_t u32TimestampStop_sec = 0, u32TimestampStop_nsec = 0;
672 software_pll.
getCorrectedTimeStamp(u32TimestampStart_sec, u32TimestampStart_nsec, u32TimestampStart);
677 MsgPackElement channelPhiMsgElement(channelPhiMsg->second.object_items());
678 MsgPackElement channelThetaMsgElement(channelThetaMsg->second.object_items());
679 std::vector<MsgPackElement> distValuesDataMsg(distValuesMsg->second.array_items().size());
680 std::vector<MsgPackElement> rssiValuesDataMsg(rssiValuesMsg->second.array_items().size());
681 for (
int n = 0; n < distValuesMsg->second.array_items().size(); n++)
682 distValuesDataMsg[n] =
MsgPackElement(distValuesMsg->second.array_items()[n].object_items());
683 for (
int n = 0; n < rssiValuesMsg->second.array_items().size(); n++)
684 rssiValuesDataMsg[n] =
MsgPackElement(rssiValuesMsg->second.array_items()[n].object_items());
687 std::vector<std::vector<uint8_t>> propertyValues;
688 if (propertiesMsg != dataMsg->second.object_items().end())
690 propertyValues = std::vector<std::vector<uint8_t>>(propertiesMsg->second.array_items().size());
691 for (
int n = 0; n < propertiesMsg->second.array_items().size(); n++)
694 propertyValues[n] = std::vector<uint8_t>(propertyMsgPackElement.
data->
binary_items().size(), 0);
697 for(
int m = 0; m < propertyValues[n].size(); m++)
704 ROS_WARN_STREAM(
"## ERROR MsgPackParser::Parse(): invalid property array");
710 int iEchoCount = echoCountMsg->second.int32_value();
713 std::vector<MsgPackToFloat32VectorConverter> distValues(distValuesDataMsg.size());
714 std::vector<MsgPackToFloat32VectorConverter> rssiValues(rssiValuesDataMsg.size());
715 for (
int n = 0; n < distValuesDataMsg.size(); n++)
717 for (
int n = 0; n < rssiValuesDataMsg.size(); n++)
719 assert(channelPhi.
data().size() == 1 && channelTheta.
data().size() > 0 && distValues.size() == iEchoCount && rssiValues.size() == iEchoCount);
722 for (
int n = 0; n < propertyValues.size(); n++)
725 if (propertyValues[n].size() != distValues[n].
data().size())
726 ROS_WARN_STREAM(
"## ERROR MsgPackParser::Parse(): invalid property values");
731 result.
scandata.back().timestampStart_sec = u32TimestampStart_sec;
732 result.
scandata.back().timestampStart_nsec = u32TimestampStart_nsec;
733 result.
scandata.back().timestampStop_sec = u32TimestampStop_sec;
734 result.
scandata.back().timestampStop_nsec = u32TimestampStop_nsec;
735 iEchoCount = std::min((
int)distValuesDataMsg.size(), iEchoCount);
736 iEchoCount = std::min((
int)rssiValuesDataMsg.size(), iEchoCount);
737 std::vector<sick_scansegment_xd::ScanSegmentParserOutput::Scanline>& groupData = result.
scandata.back().scanlines;
738 groupData.reserve(iEchoCount);
739 int iPointCount = (int)channelTheta.
data().size();
741 float elevation = -channelPhi.
data()[0];
742 float cos_elevation = std::cos(elevation);
743 float sin_elevation = std::sin(elevation);
744 std::vector<float> cos_azimuth(iPointCount);
745 std::vector<float> sin_azimuth(iPointCount);
746 std::vector<uint64_t> lut_lidar_timestamp_microsec(iPointCount);
747 for (
int pointIdx = 0; pointIdx < iPointCount; pointIdx++)
749 float azimuth = channelTheta.
data()[pointIdx] + add_transform_xyz_rpy.
azimuthOffset();
750 cos_azimuth[pointIdx] = std::cos(azimuth);
751 sin_azimuth[pointIdx] = std::sin(azimuth);
752 lut_lidar_timestamp_microsec[pointIdx] = ((pointIdx * (u32TimestampStop - u32TimestampStart)) / (iPointCount - 1)) + u32TimestampStart;
756 for (
int echoIdx = 0; echoIdx < iEchoCount; echoIdx++)
758 assert(iPointCount == channelTheta.
data().size() && iPointCount == distValues[echoIdx].data().size() && iPointCount == rssiValues[echoIdx].data().size());
761 scanline.
points.reserve(iPointCount);
762 for (
int pointIdx = 0; pointIdx < iPointCount; pointIdx++)
764 uint8_t reflectorbit = 0;
765 for (
int n = 0; n < propertyValues.size(); n++)
766 if (pointIdx < propertyValues[n].size())
767 reflectorbit |= ((propertyValues[n][pointIdx]) & 0x01);
768 float dist = 0.001f * distValues[echoIdx].data()[pointIdx];
769 float intensity = rssiValues[echoIdx].data()[pointIdx];
770 float x = dist * cos_azimuth[pointIdx] * cos_elevation;
771 float y = dist * sin_azimuth[pointIdx] * cos_elevation;
772 float z = dist * sin_elevation;
774 float azimuth = channelTheta.
data()[pointIdx];
776 if (msgpack_validator_enabled)
778 msgpack_validator_data.
update(echoIdx, segment_idx, azimuth_norm, elevation);
779 msgpack_validator_data_collector.
update(echoIdx, segment_idx, azimuth_norm, elevation);
781 uint64_t lidar_timestamp_microsec = lut_lidar_timestamp_microsec[pointIdx];
782 scanline.
points.push_back(
sick_scansegment_xd::ScanSegmentParserOutput::LidarPoint(x, y, z, intensity, dist, azimuth, elevation, groupIdx, echoIdx, pointIdx, lidar_timestamp_microsec, reflectorbit));
789 ROS_INFO_STREAM((groupIdx + 1) <<
". group: EchoCount = " << iEchoCount);
790 ROS_INFO_STREAM((groupIdx + 1) <<
". group: phi (elevation, rad) = [" << channelPhi.
print() <<
"], " << channelPhi.
data().size() <<
" element");
791 ROS_INFO_STREAM((groupIdx + 1) <<
". group: phi (elevation, deg) = [" << channelPhi.
printRad2Deg() <<
"], " << channelPhi.
data().size() <<
" element");
792 ROS_INFO_STREAM((groupIdx + 1) <<
". group: theta (azimuth, rad) = [" << channelTheta.
print() <<
"], " << channelTheta.
data().size() <<
" elements");
793 ROS_INFO_STREAM((groupIdx + 1) <<
". group: theta (azimuth, deg) = [" << channelTheta.
printRad2Deg() <<
"], " << channelTheta.
data().size() <<
" elements");
796 for (
int n = 0; n < distValues.size(); n++)
797 ROS_INFO_STREAM((groupIdx + 1) <<
". group: dist[" << n <<
"] = [" << distValues[n].
print() <<
"], " << distValues[n].
data().size() <<
" elements");
798 for (
int n = 0; n < rssiValues.size(); n++)
799 ROS_INFO_STREAM((groupIdx + 1) <<
". group: rssi[" << n <<
"] = [" << rssiValues[n].
print() <<
"], " << rssiValues[n].
data().size() <<
" elements");
826 if(msgpack_validator_enabled)
830 std::vector<std::string> messages = msgpack_validator_data.
print();
831 for(
int n = 0; n < messages.size(); n++)
836 if (discard_msgpacks_not_validated)
838 ROS_ERROR_STREAM(
"## ERROR MsgPackParser::Parse(): msgpack out of bounds validation failed, pointcloud discarded");
841 ROS_ERROR_STREAM(
"## ERROR MsgPackParser::Parse(): msgpack out of bounds validation failed");
849 catch (
const std::exception& exc)
851 ROS_ERROR_STREAM(
"## ERROR msgpack11::MsgPack::parse(): exception " << exc.what());
878 bool write_header =
false;
879 std::ios::openmode openmode = std::ios::app;
883 openmode = std::ios::trunc;
885 std::ofstream csv_ostream(csvFile, openmode);
886 if (!csv_ostream.is_open())
888 ROS_ERROR_STREAM(
"## ERRORMsgPackParser::WriteCSV(): can't open output file \"" << csvFile <<
"\" for writing.");
893 csv_ostream <<
"SegmentIndex; Timestamp; GroupIdx; EchoIdx; PointIdx; X; Y; Z; Range; Azimuth; Elevation; Intensity" << std::endl;
895 for (
int msgCnt = 0; msgCnt < results.size(); msgCnt++)
898 for (
int groupIdx = 0; groupIdx < result.
scandata.size(); groupIdx++)
900 for (
int echoIdx = 0; echoIdx < result.
scandata[groupIdx].scanlines.size(); echoIdx++)
902 const std::vector<sick_scansegment_xd::ScanSegmentParserOutput::LidarPoint>& scanline = result.
scandata[groupIdx].scanlines[echoIdx].points;
903 for (
int pointIdx = 0; pointIdx < scanline.size(); pointIdx++)
907 csv_ostream <<
";" << std::setw(24) << result.
timestamp;
908 csv_ostream <<
";" << std::setw(12) << point.
groupIdx;
909 csv_ostream <<
";" << std::setw(12) << point.
echoIdx;
910 csv_ostream <<
";" << std::setw(12) << point.
pointIdx;
911 csv_ostream <<
";" << std::setw(12) << std::fixed << std::setprecision(3) << point.
x;
912 csv_ostream <<
";" << std::setw(12) << std::fixed << std::setprecision(3) << point.
y;
913 csv_ostream <<
";" << std::setw(12) << std::fixed << std::setprecision(3) << point.
z;
914 csv_ostream <<
";" << std::setw(12) << std::fixed << std::setprecision(3) << point.
range;
915 csv_ostream <<
";" << std::setw(12) << std::fixed << std::setprecision(8) << point.
azimuth;
916 csv_ostream <<
";" << std::setw(12) << std::fixed << std::setprecision(8) << point.
elevation;
917 csv_ostream <<
";" << std::setw(12) << std::fixed << std::setprecision(3) << point.
i;
919 csv_ostream << std::endl;
933 bool sick_scansegment_xd::MsgPackParser::ExportXYZI(
const std::vector<ScanSegmentParserOutput>& results, std::vector<float>& x, std::vector<float>& y, std::vector<float>& z, std::vector<float>& i, std::vector<int>& group_idx, std::vector<int>& echo_idx, std::vector<int>& msg_idx)
937 size_t data_length = 0;
938 for (
int groupIdx = 0; groupIdx < results[0].scandata.size(); groupIdx++)
940 for (
int echoIdx = 0; echoIdx < results[0].scandata[groupIdx].scanlines.size(); echoIdx++)
942 data_length += results[0].scandata[groupIdx].scanlines[echoIdx].points.size();
945 x.reserve(data_length);
946 y.reserve(data_length);
947 z.reserve(data_length);
948 i.reserve(data_length);
949 group_idx.reserve(data_length);
950 echo_idx.reserve(data_length);
951 msg_idx.reserve(data_length);
952 for (
int msgCnt = 0; msgCnt < results.size(); msgCnt++)
955 for (
int groupIdx = 0; groupIdx < result.
scandata.size(); groupIdx++)
957 for (
int echoIdx = 0; echoIdx < result.
scandata[groupIdx].scanlines.size(); echoIdx++)
959 const std::vector<sick_scansegment_xd::ScanSegmentParserOutput::LidarPoint>& scanline = result.
scandata[groupIdx].scanlines[echoIdx].points;
960 for (
int pointIdx = 0; pointIdx < scanline.size(); pointIdx++)
963 x.push_back(point.
x);
964 y.push_back(point.
y);
965 z.push_back(point.
z);
966 i.push_back(point.
i);
967 group_idx.push_back(point.
groupIdx);
968 echo_idx.push_back(point.
echoIdx);