68 : m_nh(nh), m_send_scan_data_rate(send_scan_data_rate), m_send_scan_data(false), m_send_scan_data_cnt(0), m_delta_range_cm(0), m_delta_range_step(1)
81 std::vector<uint8_t> msg_header(24);
82 std::vector<uint8_t> magic_word = { 0xaf, 0xfe, 0xc0, 0xc2 };
83 msg_header[0] = magic_word[0];
84 msg_header[1] = magic_word[1];
85 msg_header[2] = magic_word[2];
86 msg_header[3] = magic_word[3];
87 msg_header[8] = ((payload_length >> 24) & 0xFF);
88 msg_header[9] = ((payload_length >> 16) & 0xFF);
89 msg_header[10] = ((payload_length >> 8) & 0xFF);
90 msg_header[11] = ((payload_length) & 0xFF);
91 msg_header[14] = ((data_type >> 8) & 0xFF);
92 msg_header[15] = ((data_type) & 0xFF);
117 uint8_t magic_word[4] = { 0xaf, 0xfe, 0xc0, 0xc2 };
123 if (memcmp(&
header[0], &magic_word[0], 4) != 0)
125 ROS_ERROR_STREAM(
"## ERROR sick_scan_xd::test::TestServerLDMRSMsg::receiveMessage(): error receiving magic word 0xAFFEC0C2");
130 size_t payload_length = 0;
131 for(
int n = 8; n < 12; n++)
132 payload_length = ((payload_length << 8) | (
header[n] & 0xFF));
135 size_t data_type = 0;
136 for(
int n = 14; n < 16; n++)
137 data_type = ((data_type << 8) | (
header[n] & 0xFF));
140 uint64_t ntp_time = 0;
141 for(
int n = 16; n < 24; n++)
142 ntp_time = ((ntp_time << 8) | (
header[n] & 0xFF));
145 message.resize(24 + payload_length);
147 if (!tcp_client_socket.
read(payload_length,
message.data() + 24))
149 ROS_ERROR_STREAM(
"## ERROR sick_scan_xd::test::TestServerLDMRSMsg::receiveMessage(): error receiving " << payload_length <<
" byte tcp payload");
167 if(message_received.size() < 24)
169 ROS_ERROR_STREAM(
"## ERROR sick_scan_xd::test::TestServerLDMRSMsg::createResponse(): invalid input message");
179 size_t data_type = 0;
180 for(
int n = 14; n < 16; n++)
181 data_type = ((data_type << 8) | (message_received[n] & 0xFF));
182 if(data_type != 0x2010)
187 if(message_received.size() < 26)
189 ROS_ERROR_STREAM(
"## ERROR sick_scan_xd::test::TestServerLDMRSMsg::createResponse(): invalid command message");
192 size_t command_id = (message_received[24] & 0xFF) | (message_received[25] << 8);
193 std::map<int, std::string> command_id_names = {
194 {0x0000,
"\"Reset\""}, {0x0001,
"\"Get Status\""}, {0x0004,
"\"Save Config\""}, {0x0010,
"\"Set Parameter\""}, {0x0011,
"\"Get Parameter\""}, {0x001A,
"\"Reset Default Parameters\""},
195 {0x0020,
"\"Start Measure\""}, {0x0021,
"\"Stop Measure\""}, {0x0030,
"\"Set NTP Timestamp Sec\""}, {0x0031,
"\"Set NTP Timestamp Frac Sec\""}
197 std::map<int, std::string> parameter_id_names = {
198 {0x1000,
"\"IP address\""}, {0x1001,
"\"TCP Port\""}, {0x1002,
"\"Subnet Mask\""}, {0x1003,
"\"Standard gateway\""}, {0x1010,
"\"CAN Base ID\""}, {0x1011,
"\"CAN Baud Rate\""},
199 {0x1012,
"\"Data Output Flag\""}, {0x1013,
"\"maxObjectsViaCAN\""}, {0x1014,
"\"ContourPointDensity\""}, {0x1016,
"\"CAN object data options\""}, {0x1017,
"\"Minimum Object Age\""},
200 {0x1100,
"\"Start angle\""}, {0x1101,
"\"End angle\""}, {0x1102,
"\"Scan frequency\""}, {0x1103,
"\"Sync angle offset\""}, {0x1104,
"\"angular resolution type\""}, {0x1105,
"\"angleTicksPerRotation\""},
201 {0x1108,
"\"RangeReduction\""}, {0x1109,
"\"Upside down mode\""}, {0x110A,
"\"Ignore near range\""}, {0x110B,
"\"Sensitivity control active\""}, {0x1200,
"\"SensorMounting_X\""}, {0x1201,
"\"SensorMounting_Y\""},
202 {0x1202,
"\"SensorMounting_Z\""}, {0x1203,
"\"SensorMounting_Yaw\""}, {0x1204,
"\"SensorMounting_Pitch\""}, {0x1205,
"\"SensorMounting_Roll\""}, {0x1206,
"\"VehicleFrontToFrontAxle\""},
203 {0x1207,
"\"FrontAxleToRearAxle\""}, {0x1208,
"\"RearAxleToVehicleRear\""}, {0x120A,
"\"SteerRatioType\""}, {0x120C,
"\"SteerRatioPoly0\""}, {0x120D,
"\"SteerRatioPoly1\""}, {0x120E,
"\"SteerRatioPoly2\""},
204 {0x120F,
"\"SteerRatioPoly3\""}, {0x1210,
"\"Vehicle Motion Data Flags\""}, {0x2208,
"\"EnableSensorInfo\""}, {0x3302,
"\"BeamTilt\""}, {0x3500,
"\"Timemeter\""}, {0x3600,
"\"Enable APD control\""},
205 {0x4000,
"\"NumSectors\""}, {0x4001,
"\"StartAngle, Sector 1\""}, {0x4002,
"\"StartAngle, Sector 2\""}, {0x4003,
"\"StartAngle, Sector 3\""}, {0x4004,
"\"StartAngle, Sector 4\""}, {0x4005,
"\"StartAngle, Sector 5\""},
206 {0x4006,
"\"StartAngle, Sector 6\""}, {0x4007,
"\"StartAngle, Sector 7\""}, {0x4008,
"\"StartAngle, Sector 8\""}, {0x4009,
"\"Angular resolution, Sector 1\""}, {0x400A,
"\"Angular resolution, Sector 2\""},
207 {0x400B,
"\"Angular resolution, Sector 3\""}, {0x400C,
"\"Angular resolution, Sector 4\""}, {0x400D,
"\"Angular resolution, Sector 5\""}, {0x400E,
"\"Angular resolution, Sector 6\""}, {0x400F,
"\"Angular resolution, Sector 7\""},
208 {0x4010,
"\"Angular resolution, Sector 8\""}, {0x7000,
"\"Detailed error code for FlexRes\""}
212 if(command_id == 0x0000)
217 else if(command_id == 0x0001)
251 else if(command_id == 0x0010)
253 size_t parameter_id = (message_received.size() >= 29) ? ((message_received[28] & 0xFF) | (message_received[29] << 8)) : 0;
254 uint32_t parameter_value = (message_received.size() >= 33) ? ((message_received[30] & 0xFF) | (message_received[31] << 8) | (message_received[32] << 16) | (message_received[33] << 24)) : 0;
257 ROS_INFO_STREAM(
"sick_scan_xd::test::TestServerLDMRSMsg::createResponse(): command id 0x10 \"Set Parameter\", parameter id 0x"
258 << std::hex << parameter_id <<
" " << parameter_id_names[parameter_id] <<
", parameter value 0x" << std::hex << parameter_value);
261 else if(command_id == 0x0011)
263 size_t parameter_id = (message_received.size() >= 29) ? ((message_received[28] & 0xFF) | (message_received[29] << 8)) : 0;
264 uint32_t parameter_value = (message_received.size() >= 33) ? ((message_received[30] & 0xFF) | (message_received[31] << 8) | (message_received[32] << 16) | (message_received[33] << 24)) : 0;
267 payload[2] = message_received[28];
268 payload[3] = message_received[29];
269 ROS_INFO_STREAM(
"sick_scan_xd::test::TestServerLDMRSMsg::createResponse(): command id 0x11 \"Get Parameter\", parameter id 0x"
270 << std::hex << parameter_id << parameter_id_names[parameter_id] <<
", parameter value 0x" << std::hex << parameter_value);
273 else if(command_id == 0x0020)
275 m_send_scan_data =
true;
279 ROS_INFO_STREAM(
"sick_scan_xd::test::TestServerLDMRSMsg::createResponse(): command id 0x20 -> start scanning in 5 seconds");
282 else if(command_id == 0x0021)
284 m_send_scan_data =
false;
287 ROS_INFO_STREAM(
"sick_scan_xd::test::TestServerLDMRSMsg::createResponse(): command id 0x21 -> stop scanning");
293 payload[0] = (command_id & 0xFF);
294 payload[1] = ((command_id >> 8) & 0xFF);
298 std::vector<uint8_t> msg_header = createMessageHeader(0x2020,
payload.size());
304 ROS_INFO_STREAM(
"sick_scan_xd::test::TestServerLDMRSMsg::createResponse(): command id 0x" << std::hex << command_id <<
" " << command_id_names[command_id]
305 <<
", " << std::dec <<
response.size() <<
" byte response");
328 std::vector<uint8_t>
payload = m_scan_data_payload;
329 for(
size_t range_offset = 48; range_offset + 10 <
payload.size(); range_offset += 10)
331 size_t range_cm = (
payload[range_offset] & 0xFF) | (
payload[range_offset + 1] << 8);
332 range_cm += m_delta_range_cm;
333 payload[range_offset] = (range_cm & 0xFF);
334 payload[range_offset + 1] = ((range_cm >> 8) & 0xFF);
338 std::vector<uint8_t> msg_header = createMessageHeader(0x2202,
payload.size());
339 scandata.reserve(msg_header.size() +
payload.size());
340 scandata.insert(scandata.end(), msg_header.begin(), msg_header.end());
345 m_send_scan_data_cnt += 1;
346 m_delta_range_cm += m_delta_range_step;
347 if(m_delta_range_cm > 500 && m_delta_range_step > 0)
349 m_delta_range_cm = 500;
350 m_delta_range_step = -m_delta_range_step;
352 if(m_delta_range_cm < 0 && m_delta_range_step < 0)
354 m_delta_range_cm = 0;
355 m_delta_range_step = -m_delta_range_step;
357 ROS_INFO_STREAM(
"sick_scan_xd::test::TestServerLDMRSMsg::createScandata(" << m_send_scan_data_cnt <<
"): " << scandata.size() <<
" byte scan data generated");
358 if(m_send_scan_data_cnt <= 1)
359 ROS_INFO_STREAM(
"sick_scan_xd::test::TestServerLDMRSMsg::createScandata(): Generating " << scandata.size() <<
" byte scan data with " << m_send_scan_data_rate <<
" Hz");