sick_generic_radar.cpp
Go to the documentation of this file.
1 
60 #ifdef _MSC_VER
61 //#define _WIN32_WINNT 0x0501
62 #pragma warning(disable: 4996)
63 #pragma warning(disable: 4267)
64 #endif
65 
67 
72 //#include <sick_scan/RadarScan.h> // generated by msg-generator
73 
74 #define _USE_MATH_DEFINES
75 
76 #include <math.h>
77 #include "string"
78 #include <stdio.h>
79 #include <stdlib.h>
80 
81 namespace sick_scan_xd
82 {
83 
84 
85 /* Null, because instance will be initialized on demand. */
86  SickScanRadarSingleton *SickScanRadarSingleton::instance = 0;
87 
89  {
90  if (instance == 0)
91  {
93  }
94 
95  return instance;
96  }
97 
99  {
100  std::string nodename;
101  rosDeclareParam(nh, "nodename", nodename);
102  rosGetParam(nh, "nodename", nodename);
103 
104  // publish radar targets and objects
105  cloud_radar_rawtarget_pub_ = rosAdvertise<ros_sensor_msgs::PointCloud2>(nh, nodename + "/cloud_radar_rawtarget", 100);
106  cloud_radar_track_pub_ = rosAdvertise<ros_sensor_msgs::PointCloud2>(nh, nodename + "/cloud_radar_track", 100);
107 
108  radarScan_pub_ = rosAdvertise<sick_scan_msg::RadarScan>(nh, nodename + "/radar", 100);
109 
110  m_add_transform_xyz_rpy = sick_scan_xd::SickCloudTransform(nh, true); // Apply an additional transform to the cartesian pointcloud, default: "0,0,0,0,0,0" (i.e. no transform)
111 
112  float range_min = 0, range_max = 100;
113  int range_filter_handling = 0;
114  rosDeclareParam(nh, "range_min", range_min);
115  rosGetParam(nh, "range_min", range_min);
116  rosDeclareParam(nh, "range_max", range_max);
117  rosGetParam(nh, "range_max", range_max);
118  rosDeclareParam(nh, "range_filter_handling", range_filter_handling);
119  rosGetParam(nh, "range_filter_handling", range_filter_handling);
121  ROS_INFO_STREAM("Range filter configuration for SickScanRadar: range_min=" << range_min << ", range_max=" << range_max << ", range_filter_handling=" << range_filter_handling);
122 
123  }
124 
125 
126  int16_t getShortValue(std::string str)
127  {
128  int val = 0;
129  if (1 == sscanf(str.c_str(), "%x", &val))
130  {
131 
132  }
133  else
134  {
135  ROS_WARN_STREAM("Problems parsing " << str << "\n");
136  }
137  return (val);
138 
139  }
140 
141  // Convert a hex string to 32 bit signed integer
142  static int getHexValue_32_signed(std::string str)
143  {
144  int val = 0;
145  if (1 == sscanf(str.c_str(), "%x", &val))
146  {
147 
148  }
149  else
150  {
151  ROS_WARN_STREAM("Problems parsing " << str << "\n");
152  }
153  return (val);
154 
155  }
156 
158  {
159  unsigned int u32_val;
160  int8_t i8_val[4];
161  int16_t i16_val[2];
162  int32_t i32_val[1];
163  };
164 
165  // Convert a hex string to 32, 16 or 8 bit signed integer (2er compliment)
166  static int getHexValue_32_16_8_signed(std::string str)
167  {
168  INT_4BYTE_UNION conv;
169  conv.u32_val = 0;
170  if (1 == sscanf(str.c_str(), "%x", &conv.u32_val))
171  {
172  if (str.size() <= 2)
173  return conv.i8_val[0];
174  else if (str.size() <= 4)
175  return conv.i16_val[0];
176  else
177  return conv.i32_val[0];
178  }
179  else
180  {
181  ROS_WARN_STREAM("getHexValue(): Problems parsing " << str << "\n");
182  }
183  return 0;
184  }
185 
186  // Convert a hex string to 32 or 16 bit signed integer (2er compliment)
187  static int getHexValue_32_16_signed(std::string str)
188  {
189  INT_4BYTE_UNION conv;
190  conv.u32_val = 0;
191  if (1 == sscanf(str.c_str(), "%x", &conv.u32_val))
192  {
193  if (str.size() <= 4)
194  return conv.i16_val[0];
195  else
196  return conv.i32_val[0];
197  }
198  else
199  {
200  ROS_WARN_STREAM("getHexValue(): Problems parsing " << str << "\n");
201  }
202  return 0;
203  }
204 
205  int getHexValue(std::string str)
206  {
207  // Hexvalues < 0x8000 are always positiv (unsigned), but hexvalues >= 0x8000 are interpreted as signed values (2er compliment)
208  return getHexValue_32_16_signed(str);
209  // return getHexValue_32_16_8_signed(str);
210  // return getHexValue_32_signed(str);
211  }
212 
213 #if 0 // Basic unittests, disabled by default
214  // Basic unittest for hex string to signed integer conversion (8, 16 or 32 bit signed values in 2er compliment).
215  static void unittestHex2Int_32_16_8_signed(const char* hexstr, int value)
216  {
217  int val = getHexValue_32_16_8_signed(hexstr);
218  if (val == value)
219  std::cout << hexstr << " = " << val << " OK" << std::endl;
220  else
221  std::cerr << "## ERROR: " << hexstr << " = " << val << ", expected " << value << std::endl;
222  }
223  // Basic unittest for hex string to signed integer conversion (16 or 32 bit signed values in 2er compliment).
224  static void unittestHex2Int_32_16_signed(const char* hexstr, int value)
225  {
226  int val = getHexValue_32_16_signed(hexstr);
227  if (val == value)
228  std::cout << hexstr << " = " << val << " OK" << std::endl;
229  else
230  std::cerr << "## ERROR: " << hexstr << " = " << val << ", expected " << value << std::endl;
231  }
232  // Some basic unittests for hex string to signed integer conversion (8, 16 or 32 bit signed values in 2er compliment).
233  // See online converter e.g. https://www.rapidtables.com/convert/number/hex-to-decimal.html
234  static void unittestsHex2Int()
235  {
236  unittestHex2Int_32_16_8_signed("B", 11);
237  unittestHex2Int_32_16_8_signed("0B", 11);
238  unittestHex2Int_32_16_8_signed("7B", 123);
239  unittestHex2Int_32_16_8_signed("A1", -95);
240  unittestHex2Int_32_16_8_signed("123", 291);
241  unittestHex2Int_32_16_8_signed("0123", 291);
242  unittestHex2Int_32_16_8_signed("7123", 28963);
243  unittestHex2Int_32_16_8_signed("9123", -28381);
244  unittestHex2Int_32_16_8_signed("71235", 463413);
245  unittestHex2Int_32_16_8_signed("A1235", 660021);
246  unittestHex2Int_32_16_8_signed("AB1235", 11211317);
247  unittestHex2Int_32_16_8_signed("7AB1235", 128651829);
248  unittestHex2Int_32_16_8_signed("AAB1235", 178983477);
249  unittestHex2Int_32_16_8_signed("1AAB1235", 447418933);
250  unittestHex2Int_32_16_8_signed("7AAB1235", 2058031669);
251  unittestHex2Int_32_16_8_signed("8AAB1235", -1968500171);
252  unittestHex2Int_32_16_8_signed("AAAB1235", -1431629259);
253  unittestHex2Int_32_16_signed("B", 11);
254  unittestHex2Int_32_16_signed("0B", 11);
255  unittestHex2Int_32_16_signed("7B", 123);
256  unittestHex2Int_32_16_signed("A1", 161);
257  unittestHex2Int_32_16_signed("123", 291);
258  unittestHex2Int_32_16_signed("0123", 291);
259  unittestHex2Int_32_16_signed("7123", 28963);
260  unittestHex2Int_32_16_signed("7FFF", 32767);
261  unittestHex2Int_32_16_signed("8000", -32768);
262  unittestHex2Int_32_16_signed("9123", -28381);
263  unittestHex2Int_32_16_signed("71235", 463413);
264  unittestHex2Int_32_16_signed("A1235", 660021);
265  unittestHex2Int_32_16_signed("AB1235", 11211317);
266  unittestHex2Int_32_16_signed("7AB1235", 128651829);
267  unittestHex2Int_32_16_signed("AAB1235", 178983477);
268  unittestHex2Int_32_16_signed("1AAB1235", 447418933);
269  unittestHex2Int_32_16_signed("7AAB1235", 2058031669);
270  unittestHex2Int_32_16_signed("8AAB1235", -1968500171);
271  unittestHex2Int_32_16_signed("AAAB1235", -1431629259);
272  }
273 #endif // Basic unittests, disabled by default
274 
275  float convertScaledIntValue(int value, float scale, float offset)
276  {
277  float val = 0;
278  val = (float) (value * scale + offset);
279  return (val);
280  }
281 
282  float getFloatValue(std::string str)
283  {
284  float tmpVal = 0.0;
285  unsigned char *ptr;
286  ptr = (unsigned char *) (&tmpVal);
287  int strLen = str.length();
288  if (strLen < 8)
289  {
290  }
291  else
292  {
293  for (int i = 0; i < 4; i++)
294  {
295  std::string dummyStr = "";
296  dummyStr += str[i * 2];
297  dummyStr += str[i * 2 + 1];
298  int val = getHexValue(dummyStr);
299  unsigned char ch = (0xFF & val);
300  ptr[3 - i] = ch;
301  }
302  }
303  return (tmpVal);
304  }
305 
307  {
308  emul = _emul;
309  }
310 
312  {
313  return (emul);
314  }
315 
317  {
318  public:
319  RadarDatagramField(char* _data = 0, size_t _len = 0) : data(_data), len(_len) {}
320  char* data;
321  size_t len;
322  template<typename T> bool toInteger(T &value) const
323  {
324  if(len == sizeof(value))
325  {
326  memcpy(&value, data, len);
327  swap_endian((unsigned char *)&value, len);
328  return true;
329  }
330  return false;
331  }
332  };
333 
334  static uint32_t radarFieldToUint32(const RadarDatagramField& field, bool useBinaryProtocol)
335  {
336  uint32_t u32_value = 0;
337  if(useBinaryProtocol)
338  {
339  bool success = false;
340  uint8_t u8_value = 0;
341  uint16_t u16_value = 0;
342  switch (field.len)
343  {
344  case 1:
345  success = field.toInteger(u8_value);
346  u32_value = u8_value;
347  break;
348  case 2:
349  success = field.toInteger(u16_value);
350  u32_value = u16_value;
351  break;
352  case 4:
353  success = field.toInteger(u32_value);
354  break;
355  default:
356  break;
357  }
358  if(!success)
359  ROS_WARN_STREAM("radarFieldToUint32() failed (field.len=" << field.len << ")");
360  }
361  else
362  {
363  u32_value = strtoul(field.data, NULL, 16);
364  }
365  return u32_value;
366  }
367 
368  static int32_t radarFieldToInt32(const RadarDatagramField& field, bool useBinaryProtocol)
369  {
370  // unittestsHex2Int(); // Basic unittests, disabled by default
371  int32_t i32_value = 0;
372  if(useBinaryProtocol)
373  {
374  bool success = false;
375  int8_t i8_value = 0;
376  int16_t i16_value = 0;
377  switch (field.len)
378  {
379  case 1:
380  success = field.toInteger(i8_value);
381  i32_value = i8_value;
382  break;
383  case 2:
384  success = field.toInteger(i16_value);
385  i32_value = i16_value;
386  break;
387  case 4:
388  success = field.toInteger(i32_value);
389  break;
390  default:
391  break;
392  }
393  if(!success)
394  ROS_WARN_STREAM("radarFieldToInt32() failed");
395  }
396  else
397  {
398  i32_value = getHexValue(field.data);
399  }
400  return i32_value;
401  }
402 
403  static float radarFieldToFloat(const RadarDatagramField& field, bool useBinaryProtocol)
404  {
405  float value = 0;
406  if(useBinaryProtocol)
407  {
408  if(field.len == sizeof(value))
409  {
410  memcpy(&value, field.data, field.len);
411  swap_endian((unsigned char *)&value, sizeof(value));
412  }
413  else
414  {
415  ROS_WARN_STREAM("radarFieldToFloat(): field.len=" << field.len << ", expected 4 byte");
416  }
417  }
418  else
419  {
420  std::string token(field.data);
421  value = getFloatValue(token);
422  }
423  return value;
424  }
425 
426 
427  static std::string radarFieldToString(const RadarDatagramField& field, bool useBinaryProtocol)
428  {
429  return std::string(field.data, field.len);
430  }
431 
432  typedef char* char_ptr;
433 
434  static bool appendRadarDatagramField(char_ptr & datagram, size_t & datagram_length, size_t field_length, std::vector<RadarDatagramField> & fields)
435  {
436  if(datagram_length >= field_length)
437  {
438  fields.push_back(RadarDatagramField(datagram, field_length));
439  datagram += field_length;
440  datagram_length -= field_length;
441  return true;
442  }
443  return false;
444  }
445 
446 
447  static std::vector<RadarDatagramField> splitBinaryRadarDatagramToFields(char* datagram, size_t datagram_length, int verboseLevel)
448  {
449  bool success = true;
450  std::vector<RadarDatagramField> fields;
451  fields.reserve(datagram_length); // max. <datagram_length> fields in binary mode
452  // Command type, 3 byte + space
453  if(datagram_length >= 4 && memcmp(datagram, "sSN ", 4) == 0)
454  {
455  fields.push_back(RadarDatagramField(datagram, 3));
456  datagram += 4;
457  datagram_length -= 4;
458  }
459  else
460  {
461  return std::vector<RadarDatagramField>(); // unrecoverable parse error
462  }
463  // Command, 12 byte + space
464  if(datagram_length >= 4 && memcmp(datagram, "LMDradardata ", 13) == 0)
465  {
466  fields.push_back(RadarDatagramField(datagram, 12));
467  datagram += 13;
468  datagram_length -= 13;
469  }
470  else
471  {
472  return std::vector<RadarDatagramField>(); // unrecoverable parse error
473  }
474  // Append radar datagram fields
475  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Version number
476  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Device number
477  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Serial number
478  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 2 x 1 byte Device status
479  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 2 x 1 byte Device status
480  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Telegram counter
481  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Scan counter
482  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Time since start up in microsec
483  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Time of transmission in microsec
484  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 2 x 1 byte Status of digital inputs
485  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 2 x 1 byte Status of digital inputs
486  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 2 x 1 byte Status of digital outputs
487  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 2 x 1 byte Status of digital outputs
488  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte CycleDuration
489  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte reserved
490  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Amount of encoder
491  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Encoder position
492  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Encoder speed
493  // Append 16 bit channels
494  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Amount of 16 bit channels
495  uint16_t num_16_bit_channels = 0;
496  fields.back().toInteger(num_16_bit_channels);
497  // if(num_16_bit_channels > 4) // max 4 16-bit channel in case of RMSxxxx
498  // {
499  // return std::vector<RadarDatagramField>(); // unrecoverable parse error
500  // }
501  for(int channel_idx = 0; channel_idx < num_16_bit_channels; channel_idx++)
502  {
503  success = success && appendRadarDatagramField(datagram, datagram_length, 5, fields); // 5 byte Content string (identifier)
504  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte scale factor (float)
505  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte scale factor offset (float)
506  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Amount of data
507  uint16_t amount_of_data = 0;
508  fields.back().toInteger(amount_of_data);
509  for(int data_field_idx = 0; data_field_idx < amount_of_data; data_field_idx++)
510  {
511  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte output data
512  }
513  }
514  // Append 8 bit channels
515  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Amount of 8 bit channels
516  uint16_t num_8_bit_channels = 0;
517  fields.back().toInteger(num_8_bit_channels);
518  if(num_8_bit_channels > 4) // max 4 8-bit channel
519  {
520  return std::vector<RadarDatagramField>(); // unrecoverable parse error
521  }
522  for(int channel_idx = 0; channel_idx < num_8_bit_channels; channel_idx++)
523  {
524  success = success && appendRadarDatagramField(datagram, datagram_length, 5, fields); // 5 byte Content string (identifier)
525  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte scale factor (float)
526  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte scale factor offset (float)
527  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Amount of data
528  uint16_t amount_of_data = 0;
529  fields.back().toInteger(amount_of_data);
530  for(int data_field_idx = 0; data_field_idx < amount_of_data; data_field_idx++)
531  {
532  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte output data
533  }
534  }
535  // Append position
536  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Output of position data
537  uint16_t position_data_available = 0;
538  fields.back().toInteger(position_data_available);
539  if(position_data_available)
540  {
541  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte X-coordinate (float)
542  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Y-coordinate (float)
543  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Z-coordinate (float)
544  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte X-rotation (float)
545  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Y-rotation (float)
546  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Z-rotation (float)
547  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte rotation type
548  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte device name
549  }
550  // Append device name
551  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte name is transmitted
552  uint16_t device_name_available = 0;
553  fields.back().toInteger(device_name_available);
554  if(device_name_available)
555  {
556  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte length of name
557  success = success && appendRadarDatagramField(datagram, datagram_length, 16, fields); // 16 byte device name
558  }
559  // Append comment
560  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte comment is transmitted
561  uint16_t comment_available = 0;
562  fields.back().toInteger(comment_available);
563  if(comment_available)
564  {
565  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte length of comment
566  success = success && appendRadarDatagramField(datagram, datagram_length, 16, fields); // 16 byte comment
567  }
568  // Append timestamp
569  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte timestamp is transmitted
570  uint16_t timestamp_available = 0;
571  fields.back().toInteger(timestamp_available);
572  if(timestamp_available)
573  {
574  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte Year
575  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte Month
576  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte Day
577  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte Hour
578  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte Minutes
579  success = success && appendRadarDatagramField(datagram, datagram_length, 1, fields); // 1 byte Seconds
580  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte Microseconds
581  }
582  // Append eventinfo
583  success = success && appendRadarDatagramField(datagram, datagram_length, 2, fields); // 2 byte eventinfo is transmitted
584  uint16_t eventinfo_available = 0;
585  fields.back().toInteger(eventinfo_available);
586  if(eventinfo_available)
587  {
588  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte type (string)
589  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte encoder position
590  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte time of event in microseconds
591  success = success && appendRadarDatagramField(datagram, datagram_length, 4, fields); // 4 byte angle of event
592  }
593  // Return radar fields
594  if(verboseLevel > 0)
595  {
596  ROS_INFO_STREAM("splitBinaryRadarDatagramToFields(): " << fields.size() << " fields, " << num_16_bit_channels << " 16-bit channels, " << num_8_bit_channels << " 8-bit channels, success=" << success);
597  }
598  return fields;
599  }
600 
601 
612  int SickScanRadarSingleton::parseRadarDatagram(char* datagram, size_t datagram_length, bool useBinaryProtocol,
613  sick_scan_msg::RadarScan *msgPtr,
614  std::vector<SickScanRadarObject> &objectList,
615  std::vector<SickScanRadarRawTarget> &rawTargetList,
616  int verboseLevel)
617  {
618  int exitCode = ExitSuccess;
619  bool dumpData = false;
620 
621  // !!!!!
622  // verboseLevel = 1;
623  int HEADER_FIELDS = 32;
624 
625  // Reserve sufficient space
626  std::vector<RadarDatagramField> fields;
627 
628  // ----- only for debug output
629  std::vector<char> datagram_copy_vec;
630  datagram_copy_vec.resize(datagram_length + 1); // to avoid using malloc. destructor frees allocated mem.
631  char *datagram_copy = &(datagram_copy_vec[0]);
632 
633  if (verboseLevel > 0)
634  {
635  sick_scan_xd::SickScanCommon::dumpDatagramForDebugging((unsigned char *)datagram, datagram_length, useBinaryProtocol);
636  }
637 
638  strncpy(datagram_copy, datagram, datagram_length); // datagram will be changed by strtok
639  datagram_copy[datagram_length] = 0;
640 
641  // ----- tokenize
642  if(useBinaryProtocol)
643  {
644  fields = splitBinaryRadarDatagramToFields(datagram, datagram_length, verboseLevel);
645  }
646  else
647  {
648  fields.reserve(datagram_length / 2); // max. datagram_length/2 in ascii mode
649  char* cur_field = strtok(datagram, " ");
650  while (cur_field != NULL)
651  {
652  fields.push_back(RadarDatagramField(cur_field, strlen(cur_field)));
653  //std::cout << cur_field << std::endl;
654  cur_field = strtok(NULL, " ");
655  }
656  }
657 
658  //std::cout << fields[27] << std::endl;
659  size_t count = fields.size();
660 
661  if (verboseLevel > 0 && !useBinaryProtocol)
662  {
663  std::vector<unsigned char> raw_fields;
664  for (int i = 0; i < count; i++)
665  {
666  for(int j = 0; j < fields[i].len; j++)
667  raw_fields.push_back(fields[i].data[j]);
668  raw_fields.push_back(' ');
669  }
670  sick_scan_xd::SickScanCommon::dumpDatagramForDebugging(raw_fields.data(), raw_fields.size(), useBinaryProtocol);
671  }
672 
673 
674  enum PREHEADER_TOKEN_SEQ
675  {
676  PREHEADER_TOKEN_SSN, // 0: sSN
677  PREHEADER_TOKEN_LMDRADARDATA, // 1: LMDradardata
678  PREHEADER_TOKEN_UI_VERSION_NO,
679  PREHEADER_TOKEN_UI_IDENT,
680  PREHEADER_TOKEN_UDI_SERIAL_NO,
681  PREHEADER_TOKEN_XB_STATE_0,
682  PREHEADER_TOKEN_XB_STATE_1,
683  PREHEADER_TOKEN_TELEGRAM_COUNT, // 7
684  PREHEADER_TOKEN_CYCLE_COUNT,
685  PREHEADER_TOKEN_SYSTEM_COUNT_SCAN,
686  PREHEADER_TOKEN_SYSTEM_COUNT_TRANSMIT,
687  PREHEADER_TOKEN_XB_INPUTS_0,
688  PREHEADER_TOKEN_XB_INPUTS_1,
689  PREHEADER_TOKEN_XB_OUTPUTS_0, // 13
690  PREHEADER_TOKEN_XB_OUTPUTS_1, // 14
691  PREHEADER_TOKEN_CYCLE_DURATION, // 15
692  PREHEADER_TOKEN_NOISE_LEVEL, // 16
693  PREHEADER_NUM_ENCODER_BLOCKS, // 17
694  PREHADERR_TOKEN_FIX_NUM
695  };
696 /*
697 
698  StatusBlock
699  ===========
700  7: BCC uitelegramcount
701  8: DC0C uicyclecount
702  9: 730E9D16 udisystemcountscan
703  10: 730EA06D udisystemcounttransmit
704  11: 0 xbInputs[0]
705  12: 0 xbInputs[1]
706  13: 0 xbOutputs[0]
707  14: 0 xbOutputs[1]
708 
709  MeasurementParam1Block
710  ======================
711  15: 0 MeasurementParam1Block.uicycleduration
712  16: 0 MeasurementParam1Block.uinoiselevel
713 
714  aEncoderBlock
715  =============
716  17: 1 Number of aEncoderBlocks
717 
718 
719  18: 0 aEncoderBlock[0].udiencoderpos
720  19: 0 aEncoderBlock[0].iencoderspeed
721 
722 
723  PREHADERR_TOKEN_FIX_NUM}; // Number of fix token (excluding aEncoderBlock)
724 */
725  /*
726  * To read a single unsigned byte, use the %hhx modifier.
727  * %hx is for an unsigned short,
728  * %x is for an unsigned int,
729  * %lx is for an unsigned long,
730  * and %llx is for an `unsigned long long.
731  *
732  */
733  if (count < PREHADERR_TOKEN_FIX_NUM)
734  {
735  ROS_WARN_STREAM("parseRadarDatagram: " << count << " fields in datagram, at least " << PREHADERR_TOKEN_FIX_NUM << " fields required");
736  return ExitError;
737  }
738  for (int i = 0; i < PREHADERR_TOKEN_FIX_NUM; i++)
739  {
740  if(i == PREHEADER_TOKEN_SSN || i == PREHEADER_TOKEN_LMDRADARDATA) // skip "sSN LMDradardata"
741  continue;
742  UINT16 uiValue = 0x00;
743  UINT32 udiValue = 0x00;
744  unsigned long int uliDummy;
745  uliDummy = radarFieldToUint32(fields[i], useBinaryProtocol); // strtoul(fields[i].data, NULL, 16);
746  switch (i)
747  {
748  case PREHEADER_TOKEN_UI_VERSION_NO:
749  msgPtr->radarpreheader.uiversionno = (UINT16) (uliDummy & 0xFFFF);
750  break;
751  case PREHEADER_TOKEN_UI_IDENT:
752  msgPtr->radarpreheader.radarpreheaderdeviceblock.uiident = (UINT16) (uliDummy & 0xFFFF);
753  break;
754  case PREHEADER_TOKEN_UDI_SERIAL_NO:
755  msgPtr->radarpreheader.radarpreheaderdeviceblock.udiserialno = (UINT32) (uliDummy & 0xFFFFFFFF);
756  break;
757  case PREHEADER_TOKEN_XB_STATE_0:
758  for (int j = 0; j < 3; j++)
759  {
760  bool flag = false;
761  if (0 != (uliDummy & (1 << j)))
762  {
763  flag = true;
764  }
765  switch (j)
766  {
767  case 0:
768  msgPtr->radarpreheader.radarpreheaderdeviceblock.bdeviceerror = flag;
769  break;
770  case 1:
771  msgPtr->radarpreheader.radarpreheaderdeviceblock.bcontaminationwarning = flag;
772  break;
773  case 2:
774  msgPtr->radarpreheader.radarpreheaderdeviceblock.bcontaminationerror = flag;
775  break;
776  default:
777  ROS_WARN("Flag parsing for this PREHEADER-Flag not implemented");
778  }
779  }
780  break;
781  case PREHEADER_TOKEN_XB_STATE_1:
782  // reserved - do nothing
783  break;
784  case PREHEADER_TOKEN_TELEGRAM_COUNT: // 7
785  msgPtr->radarpreheader.radarpreheaderstatusblock.uitelegramcount = (UINT16) (uliDummy & 0xFFFF);
786  break;
787  case PREHEADER_TOKEN_CYCLE_COUNT:
788  uiValue = radarFieldToUint32(fields[i], useBinaryProtocol); // sscanf(fields[i].data, "%hu", &uiValue);
789  msgPtr->radarpreheader.radarpreheaderstatusblock.uicyclecount = (UINT16) (uliDummy & 0xFFFF);
790  break;
791  case PREHEADER_TOKEN_SYSTEM_COUNT_SCAN:
792  msgPtr->radarpreheader.radarpreheaderstatusblock.udisystemcountscan = (UINT32) (uliDummy & 0xFFFFFFFF);
793  break;
794  case PREHEADER_TOKEN_SYSTEM_COUNT_TRANSMIT:
795  msgPtr->radarpreheader.radarpreheaderstatusblock.udisystemcounttransmit = (UINT32) (uliDummy & 0xFFFFFFFF);
796  break;
797  case PREHEADER_TOKEN_XB_INPUTS_0:
798  msgPtr->radarpreheader.radarpreheaderstatusblock.uiinputs = (UINT8) (uliDummy & 0xFF);;
799  msgPtr->radarpreheader.radarpreheaderstatusblock.uiinputs <<= 8;
800  break;
801  case PREHEADER_TOKEN_XB_INPUTS_1:
802  msgPtr->radarpreheader.radarpreheaderstatusblock.uiinputs |= (UINT8) (uliDummy & 0xFF);;
803  break;
804  case PREHEADER_TOKEN_XB_OUTPUTS_0:
805  msgPtr->radarpreheader.radarpreheaderstatusblock.uioutputs = (UINT8) (uliDummy & 0xFF);;
806  msgPtr->radarpreheader.radarpreheaderstatusblock.uioutputs <<= 8;
807  break;
808  case PREHEADER_TOKEN_XB_OUTPUTS_1:
809  msgPtr->radarpreheader.radarpreheaderstatusblock.uioutputs |= (UINT8) (uliDummy & 0xFF);;
810  break;
811  case PREHEADER_TOKEN_CYCLE_DURATION:
812  msgPtr->radarpreheader.radarpreheadermeasurementparam1block.uicycleduration = (UINT16) (uliDummy & 0xFFFF);
813  break;
814  case PREHEADER_TOKEN_NOISE_LEVEL:
815  msgPtr->radarpreheader.radarpreheadermeasurementparam1block.uinoiselevel = (UINT16) (uliDummy & 0xFFFF);
816  break;
817  case PREHEADER_NUM_ENCODER_BLOCKS:
818  {
819  UINT16 u16NumberOfBlock = (UINT16) (uliDummy & 0xFFFF);
820 
821  if (u16NumberOfBlock > 0)
822  {
823  msgPtr->radarpreheader.radarpreheaderarrayencoderblock.resize(u16NumberOfBlock);
824 
825  for (int j = 0; j < u16NumberOfBlock; j++)
826  {
827  INT16 iencoderspeed;
828  int rowIndex = PREHEADER_NUM_ENCODER_BLOCKS + j * 2 + 1;
829  udiValue = radarFieldToUint32(fields[rowIndex], useBinaryProtocol); // strtoul(fields[rowIndex].data, NULL, 16);
830  msgPtr->radarpreheader.radarpreheaderarrayencoderblock[j].udiencoderpos = udiValue;
831  udiValue = radarFieldToUint32(fields[rowIndex + 1], useBinaryProtocol); // strtoul(fields[rowIndex + 1].data, NULL, 16);
832  iencoderspeed = (int) udiValue;
833  msgPtr->radarpreheader.radarpreheaderarrayencoderblock[j].iencoderspeed = iencoderspeed;
834 
835  }
836  }
837  }
838  break;
839  }
840  }
841 /*
842  MeasurementData
843  ===============
844  2: 1 MeasurementData.uiversionno : Version Information for this while structureValue
845  Value Range: 0 ... 65535
846  };
847 
848 */
849  std::vector<std::string> keyWordList;
850 #define DIST1_KEYWORD "DIST1"
851 #define AZMT1_KEYWORD "AZMT1"
852 #define VRAD1_KEYWORD "VRAD1"
853 #define AMPL1_KEYWORD "AMPL1"
854 #define MODE1_KEYWORD "MODE1"
855 
856 #define P3DX1_KEYWORD "P3DX1"
857 #define P3DY1_KEYWORD "P3DY1"
858 #define V3DX1_KEYWORD "V3DX1"
859 #define V3DY1_KEYWORD "V3DY1"
860 #define OBJLEN_KEYWORD "OBLE1"
861 #define OBJID_KEYWORD "OBID1"
862 
863  const int RAWTARGET_LOOP = 0;
864  const int OBJECT_LOOP = 1;
865 
866  for (int iLoop = 0; iLoop < 2; iLoop++)
867  {
868  keyWordList.clear();
869  switch (iLoop)
870  {
871  case RAWTARGET_LOOP:
872  keyWordList.push_back(DIST1_KEYWORD);
873  keyWordList.push_back(AZMT1_KEYWORD);
874  keyWordList.push_back(VRAD1_KEYWORD);
875  keyWordList.push_back(AMPL1_KEYWORD);
876  keyWordList.push_back(MODE1_KEYWORD);
877  break;
878  case OBJECT_LOOP:
879  switch(this->radarType)
880  {
881  case RADAR_1D:
882  keyWordList.push_back(P3DX1_KEYWORD);
883  keyWordList.push_back(V3DX1_KEYWORD);
884  keyWordList.push_back(OBJLEN_KEYWORD);
885  keyWordList.push_back(OBJID_KEYWORD);
886  break;
887  case RADAR_3D:
888  keyWordList.push_back(P3DX1_KEYWORD);
889  keyWordList.push_back(P3DY1_KEYWORD);
890  keyWordList.push_back(V3DX1_KEYWORD);
891  keyWordList.push_back(V3DY1_KEYWORD);
892  keyWordList.push_back(OBJLEN_KEYWORD);
893  keyWordList.push_back(OBJID_KEYWORD);
894  break;
895  default: // unsupported
896  assert(0);
897  break;
898  }
899 
900  break;
901  }
902  std::vector<int> keyWordPos;
903  std::vector<float> keyWordScale;
904  std::vector<float> keyWordScaleOffset;
905  keyWordPos.resize(keyWordList.size());
906  keyWordScale.resize(keyWordList.size());
907  keyWordScaleOffset.resize(keyWordList.size());
908  for (int i = 0; i < keyWordPos.size(); i++)
909  {
910  keyWordPos[i] = -1;
911  }
912  int numKeyWords = keyWordPos.size();
913  for (int i = 0; i < fields.size(); i++)
914  {
915  for (int j = 0; j < keyWordList.size(); j++)
916  {
917  if (fields[i].len == keyWordList[j].length() && strncmp(fields[i].data, keyWordList[j].c_str(), fields[i].len) == 0)
918  {
919  keyWordPos[j] = i;
920  }
921  }
922  }
923 
924  bool entriesNumOk = true;
925  bool allow_missing_keywords = false;
926  int entriesNum = 0;
927  if (keyWordPos[0] == -1)
928  {
929  entriesNumOk = false;
930  }
931  else
932  {
933 
934  entriesNum = (int)radarFieldToInt32(fields[keyWordPos[0] + 3], useBinaryProtocol); // getHexValue(fields[keyWordPos[0] + 3].data);
935  for (int i = 0; i < numKeyWords; i++)
936  {
937  if (keyWordPos[i] == -1)
938  {
939  entriesNumOk = false;
940  ROS_WARN_STREAM("parseRadarDatagram(): " << (i + 1) << ". keyword " << keyWordList[i] << " missing, but first keyword " << keyWordList[0] << " found, value set to 0.0");
941  entriesNumOk = false;
942  allow_missing_keywords = true; // P3DY1 and V3DY1 set to 0 if missing
943  }
944  else
945  {
946  int entriesNumTmp = (int)radarFieldToInt32(fields[keyWordPos[i] + 3], useBinaryProtocol); // getHexValue(fields[keyWordPos[i] + 3].data);
947  if (entriesNumTmp != entriesNum)
948  {
949  ROS_WARN_STREAM("parseRadarDatagram(): Number of items for keyword " << keyWordList[i] << " differs from number of items for " << keyWordList[0]);
950  entriesNumOk = false;
951  }
952  }
953  }
954  }
955 
956  if (true == entriesNumOk || true == allow_missing_keywords)
957  {
958 
959 
960  for (int i = 0; i < numKeyWords; i++)
961  {
962  if (true == allow_missing_keywords && keyWordPos[i] == -1)
963  {
964  continue; // keyword is missing
965  }
966  int scaleLineIdx = keyWordPos[i] + 1;
967  int scaleOffsetLineIdx = keyWordPos[i] + 2;
968  // std::string token = radarFieldToString(fields[scaleLineIdx], useBinaryProtocol); // fields[scaleLineIdx].data;
969  keyWordScale[i] = radarFieldToFloat(fields[scaleLineIdx], useBinaryProtocol); // getFloatValue(token);
970  // token = fields[scaleOffsetLineIdx].data;
971  keyWordScaleOffset[i] = radarFieldToFloat(fields[scaleOffsetLineIdx], useBinaryProtocol); // getFloatValue(token);
972  // printf("Keyword: %-6s %8.3lf %8.3lf\n", keyWordList[i].c_str(), keyWordScale[i], keyWordScaleOffset[i]);
973  }
974 
975  switch (iLoop)
976  {
977  case RAWTARGET_LOOP:
978  {
979  rawTargetList.resize(entriesNum);
980  break;
981  }
982  case OBJECT_LOOP:
983  {
984  objectList.resize(entriesNum);
985  break;
986  }
987  }
988  for (int i = 0; i < entriesNum; i++)
989  {
990  switch (iLoop)
991  {
992  case RAWTARGET_LOOP:
993  {
994  float dist = 0.0;
995  float azimuth = 0.0;
996  float ampl = 0.0;
997  float vrad = 0.0;
998  int mode = 0;
999  for (int j = 0; j < numKeyWords; j++)
1000  {
1001  if (true == allow_missing_keywords && keyWordPos[j] == -1)
1002  {
1003  continue; // keyword is missing
1004  }
1005  int dataRowIdx = keyWordPos[j] + 4 + i;
1006  std::string token = keyWordList[j];
1007  if (token.compare(DIST1_KEYWORD) == 0)
1008  {
1009  int distRaw = (int)radarFieldToInt32(fields[dataRowIdx], useBinaryProtocol); // getHexValue(fields[dataRowIdx].data);
1010  dist = convertScaledIntValue(distRaw, keyWordScale[j], keyWordScaleOffset[j]) * 0.001f;
1011  }
1012  if (token.compare(AZMT1_KEYWORD) == 0)
1013  {
1014  int azimuthRaw = (int)radarFieldToInt32(fields[dataRowIdx], useBinaryProtocol); // getShortValue(fields[dataRowIdx].data);
1015  azimuth = (float) convertScaledIntValue(azimuthRaw, keyWordScale[j], keyWordScaleOffset[j]);
1016  }
1017  if (token.compare(VRAD1_KEYWORD) == 0)
1018  {
1019  int vradRaw = (int)radarFieldToInt32(fields[dataRowIdx], useBinaryProtocol); // getShortValue(fields[dataRowIdx].data);
1020  vrad = (float) convertScaledIntValue(vradRaw, keyWordScale[j], keyWordScaleOffset[j]);
1021  }
1022  if (token.compare(MODE1_KEYWORD) == 0)
1023  {
1024  int modeRaw = (int)radarFieldToInt32(fields[dataRowIdx], useBinaryProtocol); // getHexValue(fields[dataRowIdx].data);
1025  mode = (int) (convertScaledIntValue(modeRaw, keyWordScale[j], keyWordScaleOffset[j]) + 0.5);
1026  }
1027  if (token.compare(AMPL1_KEYWORD) == 0)
1028  {
1029  int amplRaw = (int)radarFieldToInt32(fields[dataRowIdx], useBinaryProtocol); // getShortValue(fields[dataRowIdx].data);
1030  ampl = (int) (convertScaledIntValue(amplRaw, keyWordScale[j], keyWordScaleOffset[j]) + 0.5);
1031  }
1032  }
1033  rawTargetList[i].Dist(dist);
1034  rawTargetList[i].Ampl(ampl);
1035  rawTargetList[i].Azimuth(azimuth);
1036  rawTargetList[i].Mode(mode);
1037  rawTargetList[i].Vrad(vrad);
1038 
1039  }
1040  break;
1041  case OBJECT_LOOP:
1042  {
1043  float px = 0.0;
1044  float py = 0.0;
1045  float vx = 0.0;
1046  float vy = 0.0;
1047  float objLen = 0.0;
1048  int objId = 0;
1049 
1050  for (int j = 0; j < numKeyWords; j++)
1051  {
1052  if (true == allow_missing_keywords && keyWordPos[j] == -1)
1053  {
1054  continue; // keyword is missing
1055  }
1056  int dataRowIdx = keyWordPos[j] + 4 + i;
1057  std::string token = keyWordList[j];
1058  int intVal = (int)radarFieldToInt32(fields[dataRowIdx], useBinaryProtocol); // getShortValue(fields[dataRowIdx].data);
1059  float val = convertScaledIntValue(intVal, keyWordScale[j], keyWordScaleOffset[j]);
1060 
1061  if (token.compare(P3DX1_KEYWORD) == 0)
1062  {
1063  px = val * 0.001f;
1064  }
1065  if (token.compare(P3DY1_KEYWORD) == 0)
1066  {
1067  py = val * 0.001f;
1068  }
1069  if (token.compare(V3DX1_KEYWORD) == 0)
1070  {
1071  vx = val;
1072  }
1073  if (token.compare(V3DY1_KEYWORD) == 0)
1074  {
1075  vy = val;
1076 
1077  }
1078  if (token.compare(OBJLEN_KEYWORD) == 0)
1079  {
1080  objLen = val;
1081  }
1082  if (token.compare(OBJID_KEYWORD) == 0)
1083  {
1084  int objIdRaw = (int)radarFieldToInt32(fields[dataRowIdx], useBinaryProtocol); // getHexValue(fields[dataRowIdx].data);
1085  objId = (int) (objIdRaw * keyWordScale[j] + 0.5);
1086  }
1087  }
1088 
1089  objectList[i].ObjId(objId);
1090  objectList[i].ObjLength(objLen);
1091  objectList[i].P3Dx(px);
1092  objectList[i].P3Dy(py);
1093  objectList[i].V3Dx(vx);
1094  objectList[i].V3Dy(vy);
1095  }
1096  break;
1097  }
1098  }
1099  }
1100  // Now parsing the entries
1101  }
1102 
1103  return (exitCode);
1104  }
1105 
1106  void SickScanRadarSingleton::simulateAsciiDatagram(unsigned char *receiveBuffer, int *actual_length)
1107  {
1108  static int callCnt = 0;
1109 
1110  callCnt++;
1111 
1112  // end
1113  std::string header = "\x2sSN LMDradardata 1 1 112F6E9 0 0 DFB6 B055 6E596002 6E5AE0E5 0 0 0 0 0 0 1 0 0 ";
1114  // std::string header = "\x2sSN LMDradardata 10 20 30 5 6 40 50 60 70 90 A0 B0 C0 D0 E0 1 A000 FFFFFF00 ";
1115  int channel16BitCnt = 4;
1116  // Faktoren fuer Rohziele: 40.0 0.16 0.04 1.00 1.00
1117  float rawTargetFactorList[] = {40.0f, 0.16f, 0.04f, 1.00f, 1.00f};
1118  float objectFactorList[] = {64.0f, 64.0f, 0.1f, 0.1f, 0.75f, 1.0f};
1119 
1120  std::string dist1_intro = "DIST1 42200000 00000000";
1121  std::string azmt1_intro = "AZMT1 3E23D70A 00000000";
1122  std::string vrad1_intro = "VRAD1 3D23D70A 00000000";
1123  std::string ampl1_intro = "AMPL1 3F800000 00000000";
1124 
1125  std::string pdx1_intro = "P3DX1 42800000 00000000";
1126  std::string pdy1_intro = "P3DY1 42800000 00000000";
1127  std::string v3dx_intro = "V3DX1 3DCCCCCD 00000000";
1128  std::string v3dy_intro = "V3DY1 3DCCCCCD 00000000";
1129  std::string oblen_intro = "OBLE1 3F400000 00000000";
1130 
1131  int rawTargetChannel16BitCnt = 4;
1132  int rawTargetChannel8BitCnt = 1;
1133  std::string mode1_intro = "MODE1 3F800000 00000000";
1134 
1135  std::string obid_intro = "OBID1 3F800000 00000000";
1136 
1137 
1138  std::string trailer = "0 0 0 0 0 0\x3";
1139 
1140  std::vector<std::string> channel16BitID;
1141  std::vector<std::string> channel8BitID;
1142  channel16BitID.push_back(dist1_intro);
1143  channel16BitID.push_back(azmt1_intro);
1144  channel16BitID.push_back(vrad1_intro);
1145  channel16BitID.push_back(ampl1_intro);
1146 
1147  channel16BitID.push_back(pdx1_intro);
1148  channel16BitID.push_back(pdy1_intro);
1149  channel16BitID.push_back(v3dx_intro);
1150  channel16BitID.push_back(v3dy_intro);
1151  channel16BitID.push_back(oblen_intro);
1152 
1153 
1154  channel8BitID.push_back(mode1_intro);
1155  channel8BitID.push_back(obid_intro);
1156 
1157  int channel8BitCnt = channel8BitID.size();
1158  int objectChannel16BitCnt = 5;
1159  channel16BitCnt = channel16BitID.size();
1160  //float x = 20.0;
1161  //float speed = 50.0; // [m/s]
1162  std::vector<SickScanRadarRawTarget> rawTargetList;
1163 
1164 #if 0 // simulate railway crossing
1165  for (float y = -20; y <= 20.0; y += 2.0)
1166  {
1167  SickScanRadarRawTarget rawTarget;
1168  float azimuth = atan2(y, x);
1169  float dist = sqrt(x*x + y*y);
1170  float vrad = speed * sin(azimuth); // speed in y direction
1171  float mode = 0;
1172  float ampl = 50.0 + y; // between 30 and 70
1173  rawTarget.Ampl(ampl);
1174  rawTarget.Mode(mode);
1175  rawTarget.Dist(dist);
1176  rawTarget.Azimuth(azimuth);
1177  rawTarget.Vrad(vrad);
1178  rawTargetList.push_back(rawTarget);
1179  }
1180 #endif
1181 
1182  std::vector<SickScanRadarObject> objectList;
1183 
1184  int objId = 0;
1185  for (float x = 20; x <= 100.0; x += 50.0)
1186  {
1187  SickScanRadarObject vehicle;
1188  float y = 0.0;
1189  for (int iY = -1; iY <= 1; iY += 2)
1190  {
1191  float xp[2] = {0}; // for raw target
1192  float yp[2] = {0};
1193  float vehicleWidth = 1.8f;
1194  y = iY * 2.0;
1195  float speed = y * 10.0f; // [m/s]
1196  vehicle.V3Dx(speed); // +/- 20 m/s
1197  vehicle.V3Dy(0.1f); // just for testing
1198 
1199  float xOff = 20.0;
1200  if (speed < 0.0)
1201  {
1202  xOff = 100.0;
1203  }
1204  vehicle.P3Dx((xOff + 0.1 * speed * (callCnt % 20)) * 1000.0);
1205  vehicle.P3Dy(y * 1000.0);
1206  float objLen = 6.0f + y;
1207  vehicle.ObjLength(objLen);
1208 
1209  vehicle.ObjId(objId++);
1210  objectList.push_back(vehicle);
1211 
1212  for (int i = 0; i < 2; i++)
1213  {
1214  SickScanRadarRawTarget rawTarget;
1215 
1216  xp[i] = vehicle.P3Dx() * 0.001;
1217  yp[i] = vehicle.P3Dy() * 0.001;
1218 
1219  if (i == 0)
1220  {
1221  yp[i] -= vehicleWidth / 2.0;
1222  }
1223  else
1224  {
1225  yp[i] += vehicleWidth / 2.0;
1226  }
1227  if (speed < 0.0) // oncoming
1228  {
1229  xp[i] -= objLen * 0.5;
1230  }
1231  else
1232  {
1233  xp[i] += objLen * 0.5;
1234  }
1235 
1236  float azimuth = atan2(yp[i], xp[i]);
1237  float dist = sqrt(xp[i] * xp[i] + yp[i] * yp[i]);
1238  float vrad = speed * cos(azimuth); // speed in y direction
1239  float mode = 0;
1240  float ampl = 50.0; // between 30 and 70
1241 
1242  rawTarget.Ampl(ampl);
1243  rawTarget.Mode(mode);
1244  rawTarget.Dist(dist);
1245  rawTarget.Azimuth(azimuth);
1246  rawTarget.Vrad(vrad);
1247  rawTargetList.push_back(rawTarget);
1248 
1249  }
1250 
1251  }
1252 
1253 
1254  }
1255 
1256  char szDummy[255] = {0};
1257  std::string resultStr;
1258  resultStr += header;
1259  sprintf(szDummy, "%x ", channel16BitCnt);
1260  resultStr += szDummy;
1261  for (int i = 0; i < channel16BitCnt; i++)
1262  {
1263  resultStr += channel16BitID[i];
1264  int valNum = rawTargetList.size();
1265  bool processRawTarget = true;
1266  if (i < rawTargetChannel16BitCnt)
1267  {
1268  valNum = rawTargetList.size();
1269  }
1270  else
1271  {
1272  processRawTarget = false;
1273  valNum = objectList.size();
1274  }
1275 
1276  sprintf(szDummy, " %x ", valNum);
1277  resultStr += szDummy;
1278  float val = 0.0;
1279  for (int j = 0; j < valNum; j++)
1280  {
1281  switch (i)
1282  {
1283  case 0:
1284  val = 1000.0 * rawTargetList[j].Dist();
1285  break;
1286  case 1:
1287  val = 1.0 / deg2rad * rawTargetList[j].Azimuth();
1288  break;
1289  case 2:
1290  val = rawTargetList[j].Vrad();
1291  break;
1292  case 3:
1293  val = rawTargetList[j].Ampl();
1294  break;
1295  case 4:
1296  val = objectList[j].P3Dx();
1297  break;
1298  case 5:
1299  val = objectList[j].P3Dy();
1300  break;
1301  case 6:
1302  val = objectList[j].V3Dx();
1303  break;
1304  case 7:
1305  val = objectList[j].V3Dy();
1306  break;
1307  case 8:
1308  val = objectList[j].ObjLength();
1309  break;
1310  }
1311 
1312 
1313  if (processRawTarget)
1314  {
1315  val /= rawTargetFactorList[i];
1316  }
1317  else
1318  {
1319  int idx = i - rawTargetChannel16BitCnt;
1320  val /= objectFactorList[idx];
1321  }
1322 
1323  if (val > 0.0)
1324  {
1325  val += 0.5;
1326  }
1327  else
1328  {
1329  val -= 0.5;
1330  }
1331  int16_t shortVal = (int16_t) (val);
1332 
1333  sprintf(szDummy, "%08x", shortVal);
1334  strcpy(szDummy, szDummy + 4); // remove first 4 digits due to integer / short
1335  resultStr += szDummy;
1336  resultStr += " ";
1337  }
1338  }
1339 
1340  sprintf(szDummy, "%x ", channel8BitCnt);
1341  resultStr += szDummy;
1342  int valNum = rawTargetList.size();
1343  for (int i = 0; i < channel8BitCnt; i++)
1344  {
1345  resultStr += channel8BitID[i];
1346  float val = 0.0;
1347  bool processRawTarget = true;
1348  if (i < rawTargetChannel8BitCnt)
1349  {
1350  valNum = rawTargetList.size();
1351  }
1352  else
1353  {
1354  processRawTarget = false;
1355  valNum = objectList.size();
1356  }
1357  sprintf(szDummy, " %x ", valNum);
1358  resultStr += szDummy;
1359  for (int j = 0; j < valNum; j++)
1360  {
1361  switch (i)
1362  {
1363  case 0:
1364  val = rawTargetList[j].Mode();
1365  break;
1366  case 1:
1367  val = objectList[j].ObjId();
1368  break;
1369  }
1370 
1371  int offset = 0;
1372  if (processRawTarget)
1373  {
1374  offset = rawTargetChannel16BitCnt;
1375  val /= rawTargetFactorList[i + offset];
1376  }
1377  else
1378  {
1379  offset = objectChannel16BitCnt;
1380  int idx = i - rawTargetChannel8BitCnt;
1381  val /= objectFactorList[idx + offset];
1382  }
1383  if (val > 0.0)
1384  {
1385  val += 0.5;
1386  }
1387  else
1388  {
1389  val -= 0.5;
1390  }
1391  int8_t shortVal = (int16_t) (val);
1392 
1393  sprintf(szDummy, "%08x", shortVal);
1394  strcpy(szDummy, szDummy + 6); // remove first 6 digits due to integer / short
1395  resultStr += szDummy;
1396  resultStr += " ";
1397  }
1398  }
1399 
1400  resultStr += trailer;
1401 
1402  *actual_length = resultStr.length();
1403  strcpy((char *) receiveBuffer, resultStr.c_str());
1404  }
1405 
1406  void SickScanRadarSingleton::simulateAsciiDatagramFromFile(unsigned char *receiveBuffer, int *pActual_length,
1407  std::string filePattern)
1408  {
1409  static int callCnt = 0;
1410  FILE *fin;
1411  char szLine[1024] = {0};
1412  char szDummyWord[1024] = {0};
1413  int actual_length = 0;
1414  int cnt = 0;
1415  char szFileName[1024] = {0};
1416 
1417  receiveBuffer[0] = '\x02';
1418  actual_length++;
1419 
1420  for (int iLoop = 0; iLoop < 2; iLoop++)
1421  {
1422  sprintf(szFileName, filePattern.c_str(), callCnt);
1423  callCnt++;
1424  fin = fopen(szFileName, "r");
1425 
1426  if ((fin == NULL) && (iLoop == 0))
1427  {
1428  callCnt = 0; // reset to 0. This enables a loop over recorded raw data
1429  }
1430  else
1431  {
1432  break;
1433  }
1434 
1435  if ((iLoop == 1) && (fin == NULL))
1436  {
1437  ROS_ERROR_STREAM("Can not find simulation file corresponding to pattern " << filePattern);
1438  }
1439  }
1440 
1441  while (fgets(szLine, 1024, fin) != NULL)
1442  {
1443  char *ptr = strchr(szLine, '\n');;
1444  if (ptr != NULL)
1445  {
1446  *ptr = '\0';
1447  }
1448 
1449  ptr = strchr(szLine, ':');
1450  if (ptr != NULL)
1451  {
1452  if (1 == sscanf(ptr + 2, "%s", szDummyWord))
1453  {
1454  if (cnt > 0)
1455  {
1456  receiveBuffer[actual_length++] = ' ';
1457  }
1458  strcpy((char *) receiveBuffer + actual_length, szDummyWord);
1459  actual_length += strlen(szDummyWord);
1460  }
1461  cnt++;
1462  }
1463  }
1464  receiveBuffer[actual_length] = (char) '\x03';
1465  actual_length++;
1466  receiveBuffer[actual_length] = (char) '\x00';
1467  actual_length++;
1468  *pActual_length = actual_length;
1469  fclose(fin);
1470  }
1471 
1472  int SickScanRadarSingleton::parseDatagram(rosTime timeStamp, unsigned char *receiveBuffer, int actual_length,
1473  bool useBinaryProtocol)
1474  {
1475  int exitCode = ExitSuccess;
1476 
1477  enum enumSimulationMode
1478  {
1479  EMULATE_OFF, EMULATE_SYN, EMULATE_FROM_FILE_TRAIN, EMULATE_FROM_FILE_CAR
1480  };
1481 
1482  int simulationMode = EMULATE_OFF;
1483 
1484  if (this->getEmulation())
1485  {
1486  simulationMode = EMULATE_SYN;
1487 
1488  }
1489  switch (simulationMode)
1490  {
1491  case EMULATE_OFF: // do nothing - use real data
1492  break;
1493  case EMULATE_SYN:
1494  simulateAsciiDatagram(receiveBuffer, &actual_length);
1495  break;
1496  case EMULATE_FROM_FILE_TRAIN:
1497  simulateAsciiDatagramFromFile(receiveBuffer, &actual_length,
1498  "/mnt/hgfs/development/ros/bags/raw/trainSeq/tmp%06d.txt");
1499  break;
1500  case EMULATE_FROM_FILE_CAR:
1501  simulateAsciiDatagramFromFile(receiveBuffer, &actual_length,
1502  "/mnt/hgfs/development/ros/bags/raw/carSeq/tmp%06d.txt");
1503  break;
1504 
1505  default:
1506  printf("Simulation Mode unknown\n");
1507 
1508  }
1509 
1511  sick_scan_msg::RadarScan radarMsg_;
1512 
1513  std::vector<SickScanRadarObject> objectList;
1514  std::vector<SickScanRadarRawTarget> rawTargetList;
1515 
1516  if (useBinaryProtocol && getNameOfRadar() == SICK_SCANNER_RMS_XXXX_NAME)
1517  {
1518  throw std::logic_error("Binary protocol for RMSxxxx currently not supported. Please use <param name=\"use_binary_protocol\" type=\"bool\" value=\"false\"/> in your launchfile.");
1519  }
1520  else
1521  {
1522  bool dataToProcess = false;
1523  char *buffer_pos = (char *) receiveBuffer;
1524  char *dstart = NULL;
1525  char *dend = NULL;
1526  int32_t dlength = 0;
1527 
1528  if (useBinaryProtocol)
1529  {
1530  // Decode binary: {4 byte STX} + {4 byte payload length} + {binary payload} + {1 byte CRC}
1531  uint32_t binary_stx = 0x02020202;
1532  dstart = strchr(buffer_pos, 0x02);
1533  if(dstart != 0 && memcmp(dstart, &binary_stx, sizeof(binary_stx)) == 0)
1534  {
1535  dstart += 4; // {4 byte STX}
1536  memcpy(&dlength, dstart, 4); // read length indicator
1537  swap_endian((unsigned char *) &dlength, 4);
1538  dstart += 4; // {4 byte payload length}
1539  dataToProcess = true; // continue parsing
1540  }
1541  }
1542  else
1543  {
1544  dstart = strchr(buffer_pos, 0x02);
1545  if (dstart != NULL)
1546  {
1547  dend = strchr(dstart + 1, 0x03);
1548  }
1549  if ((dstart != NULL) && (dend != NULL))
1550  {
1551  dataToProcess = true; // continue parsing
1552  dlength = dend - dstart;
1553  *dend = '\0';
1554  dstart++;
1555  }
1556  }
1557  if(dataToProcess && dstart != 0 && dlength > 0 && dstart + dlength <= (char*)receiveBuffer + actual_length)
1558  {
1559  if (parseRadarDatagram(dstart, dlength, useBinaryProtocol, &radarMsg_, objectList, rawTargetList) != ExitSuccess)
1560  {
1561  dataToProcess = false;
1562  }
1563  }
1564  else
1565  {
1566  dataToProcess = false;
1567  }
1568 
1569  enum RADAR_PROC_LIST
1570  {
1571  RADAR_PROC_RAW_TARGET, RADAR_PROC_TRACK, RADAR_PROC_NUM
1572  };
1573  //
1574  // First loop: looking for raw targets
1575  // Second loop: looking for tracking objects
1576  for (int iLoop = 0; iLoop < RADAR_PROC_NUM; iLoop++)
1577  {
1578  int numTargets = 0;
1579  if (dataToProcess)
1580  {
1581  std::string channelRawTargetId[] = {"x", "y", "z", "vrad", "amplitude"};
1582  std::string channelObjectId[] = {"x", "y", "z", "vx", "vy", "vz", "objLen", "objId"};
1583  std::vector<std::string> channelList;
1584  std::string frameId = "radar"; //this->commonPtr->getConfigPtr()->frame_id;;
1585  switch (iLoop)
1586  {
1587  case RADAR_PROC_RAW_TARGET:
1588  numTargets = rawTargetList.size();
1589  for (int i = 0; i < sizeof(channelRawTargetId) / sizeof(channelRawTargetId[0]); i++)
1590  {
1591  channelList.push_back(channelRawTargetId[i]);
1592  }
1593  frameId = "radar"; // TODO - move to param list
1594  break;
1595  case RADAR_PROC_TRACK:
1596  numTargets = objectList.size();
1597  for (int i = 0; i < sizeof(channelObjectId) / sizeof(channelObjectId[0]); i++)
1598  {
1599  channelList.push_back(channelObjectId[i]);
1600  }
1601  frameId = "radar"; // TODO - move to param list
1602  break;
1603  }
1604  if (numTargets == 0)
1605  {
1606  continue;
1607  }
1608  int numChannels = channelList.size();
1609 
1610  std::vector<float> valSingle;
1611  valSingle.resize(numChannels);
1612  cloud_.header.stamp = timeStamp;
1613  cloud_.header.frame_id = frameId;
1614  ROS_HEADER_SEQ(cloud_.header, 0);
1615  cloud_.height = 1; // due to multi echo multiplied by num. of layers
1616  cloud_.width = numTargets;
1617  cloud_.is_bigendian = false;
1618  cloud_.is_dense = true;
1619  cloud_.point_step = numChannels * sizeof(float);
1620  cloud_.row_step = cloud_.point_step * cloud_.width;
1621  cloud_.fields.resize(numChannels);
1622  for (int i = 0; i < numChannels; i++)
1623  {
1624  cloud_.fields[i].name = channelList[i];
1625  cloud_.fields[i].offset = i * sizeof(float);
1626  cloud_.fields[i].count = 1;
1627  cloud_.fields[i].datatype = ros_sensor_msgs::PointField::FLOAT32;
1628  }
1629 
1630  cloud_.data.resize(cloud_.row_step * cloud_.height, 0);
1631  float *valPtr = (float *) (&(cloud_.data[0]));
1632  int off = 0;
1633  size_t numFilteredTargets = 0;
1634  for (int i = 0; i < numTargets; i++)
1635  {
1636  bool tgt_valid = true, range_modified = false;
1637  switch (iLoop)
1638  {
1639  case 0:
1640  {
1641  float angle = deg2rad * rawTargetList[i].Azimuth();
1642  float range = rawTargetList[i].Dist();
1643  tgt_valid = m_range_filter.apply(range, range_modified);
1644  if (tgt_valid)
1645  {
1646  valSingle[0] = range * cos(angle);
1647  valSingle[1] = range * sin(angle);
1648  valSingle[2] = 0.0;
1649  valSingle[3] = rawTargetList[i].Vrad();
1650  valSingle[4] = rawTargetList[i].Ampl();
1651  }
1652  }
1653  break;
1654 
1655  case 1:
1656  valSingle[0] = objectList[i].P3Dx();
1657  valSingle[1] = objectList[i].P3Dy();
1658  valSingle[2] = 0.0;
1659  valSingle[3] = objectList[i].V3Dx();
1660  valSingle[4] = objectList[i].V3Dy();
1661  valSingle[5] = 0.0;
1662  valSingle[6] = objectList[i].ObjLength();
1663  valSingle[7] = objectList[i].ObjId();
1664  break;
1665  }
1666  if (!tgt_valid)
1667  continue;
1668  numFilteredTargets++;
1669  m_add_transform_xyz_rpy.applyTransform(valSingle[0], valSingle[1], valSingle[2]); // apply optional transform to (x, y, z)
1670 
1671  for (int j = 0; j < numChannels; j++)
1672  {
1673  valPtr[off] = valSingle[j];
1674  off++;
1675  }
1676  if (iLoop == RADAR_PROC_RAW_TARGET)
1677  {
1678  // is this a deep copy ???
1679  radarMsg_.targets = cloud_;
1680  }
1681  }
1682  if (numFilteredTargets < numTargets)
1683  m_range_filter.resizePointCloud(numFilteredTargets, cloud_); // targets dropped by range filter, resize pointcloud
1684 #ifndef ROSSIMU
1685  sick_scan_xd::PointCloud2withEcho sick_cloud_msg(&cloud_, 1, 0, "radar");
1686  switch (iLoop)
1687  {
1688  case RADAR_PROC_RAW_TARGET:
1689  notifyCartesianPointcloudListener(node, &sick_cloud_msg);
1691  break;
1692  case RADAR_PROC_TRACK:
1693  notifyCartesianPointcloudListener(node, &sick_cloud_msg);
1695  break;
1696  }
1697 #endif
1698 
1699  }
1700  }
1701  // Publishing radar messages
1702  // ...
1703  radarMsg_.header.stamp = timeStamp;
1704  radarMsg_.header.frame_id = "radar";
1705  ROS_HEADER_SEQ(radarMsg_.header, 0);
1706 
1707  radarMsg_.objects.resize(objectList.size());
1708  for (int i = 0; i < radarMsg_.objects.size(); i++)
1709  {
1710  float vx = objectList[i].V3Dx();
1711  float vy = objectList[i].V3Dy();
1712  float v = sqrt(vx * vx + vy * vy);
1713  float heading = atan2(objectList[i].V3Dy(), objectList[i].V3Dx());
1714 
1715  radarMsg_.objects[i].id = objectList[i].ObjId();
1716  radarMsg_.objects[i].tracking_time = timeStamp;
1717 
1718  radarMsg_.objects[i].velocity.twist.linear.x = objectList[i].V3Dx();
1719  radarMsg_.objects[i].velocity.twist.linear.y = objectList[i].V3Dy();
1720  radarMsg_.objects[i].velocity.twist.linear.z = 0.0;
1721 
1722  radarMsg_.objects[i].bounding_box_center.position.x = objectList[i].P3Dx();
1723  radarMsg_.objects[i].bounding_box_center.position.y = objectList[i].P3Dy();
1724  radarMsg_.objects[i].bounding_box_center.position.z = 0.0;
1725 
1726  float heading2 = heading / 2.0;
1727  // (n_x, n_y, n_z) = (0, 0, 1), so (x, y, z, w) = (0, 0, sin(theta/2), cos(theta/2))
1729  // see also this beautiful website: https://quaternions.online/
1730  radarMsg_.objects[i].bounding_box_center.orientation.x = 0.0;
1731  radarMsg_.objects[i].bounding_box_center.orientation.y = 0.0;
1732  radarMsg_.objects[i].bounding_box_center.orientation.z = sin(heading2);
1733  radarMsg_.objects[i].bounding_box_center.orientation.w = cos(heading2);
1734 
1735 
1736  radarMsg_.objects[i].bounding_box_size.x = objectList[i].ObjLength();
1737  radarMsg_.objects[i].bounding_box_size.y = 1.7;
1738  radarMsg_.objects[i].bounding_box_size.z = 1.7;
1739  for (int ii = 0; ii < 6; ii++)
1740  {
1741  int mainDiagOffset = ii * 6 + ii; // build eye-matrix
1742  radarMsg_.objects[i].object_box_center.covariance[mainDiagOffset] = 1.0; // it is a little bit hacky ...
1743  radarMsg_.objects[i].velocity.covariance[mainDiagOffset] = 1.0;
1744  }
1745  radarMsg_.objects[i].object_box_center.pose = radarMsg_.objects[i].bounding_box_center;
1746  radarMsg_.objects[i].object_box_size = radarMsg_.objects[i].bounding_box_size;
1747 
1748 
1749  }
1750 
1751  notifyRadarScanListener(node, &radarMsg_);
1752  rosPublish(radarScan_pub_, radarMsg_);
1753 
1754 
1755  }
1756  return (exitCode);
1757  }
1758 
1759 }
UINT16
uint16_t UINT16
Definition: BasicDatatypes.hpp:73
UINT8
uint8_t UINT8
Definition: BasicDatatypes.hpp:75
sick_scan_xd::getFloatValue
float getFloatValue(std::string str)
Definition: sick_generic_radar.cpp:282
sick_scan_xd::SickScanRadarSingleton::m_range_filter
sick_scan_xd::SickRangeFilter m_range_filter
Definition: sick_generic_radar.h:192
sick_scan_xd::RADAR_3D
@ RADAR_3D
Definition: sick_generic_parser.h:106
sick_scan_xd::SickScanRadarRawTarget::Azimuth
float Azimuth() const
Definition: sick_generic_radar.h:89
sick_scan_xd::SickScanRadarSingleton::emul
bool emul
Definition: sick_generic_radar.h:181
NULL
#define NULL
sick_scan_xd::SickScanRadarSingleton::radarScan_pub_
rosPublisher< sick_scan_msg::RadarScan > radarScan_pub_
Definition: sick_generic_radar.h:189
sick_scan_xd::INT_4BYTE_UNION::u32_val
unsigned int u32_val
Definition: sick_generic_radar.cpp:159
sick_scan_xd::SickScanRadarObject
Definition: sick_generic_radar.h:121
sick_scan_xd::getHexValue_32_16_signed
static int getHexValue_32_16_signed(std::string str)
Definition: sick_generic_radar.cpp:187
swap_endian
void swap_endian(unsigned char *ptr, int numBytes)
Universal swapping function.
Definition: sick_scan_common.cpp:125
sick_scan_xd::SickScanRadarSingleton::node
rosNodePtr node
Definition: sick_generic_radar.h:185
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
sick_scan_xd::SickCloudTransform
Definition: sick_cloud_transform.h:85
INT16
int16_t INT16
Definition: BasicDatatypes.hpp:74
roswrap::message_traits::frameId
std::string * frameId(M &m)
returns FrameId<M>::pointer(m);
Definition: message_traits.h:299
sick_generic_radar.h
OBJID_KEYWORD
#define OBJID_KEYWORD
sensor_msgs::PointCloud2
::sensor_msgs::PointCloud2_< std::allocator< void > > PointCloud2
Definition: PointCloud2.h:90
sick_scan_xd::SickScanRadarObject::P3Dy
float P3Dy() const
Definition: sick_generic_radar.h:130
sick_scan_xd::SickScanRadarRawTarget::Vrad
float Vrad() const
Definition: sick_generic_radar.h:95
sick_scan_xd::getHexValue_32_signed
static int getHexValue_32_signed(std::string str)
Definition: sick_generic_radar.cpp:142
sick_scan_xd::RadarDatagramField
Definition: sick_generic_radar.cpp:316
ROS_WARN
#define ROS_WARN(...)
Definition: sick_scan_logging.h:122
sick_scan_xd::SickScanRadarSingleton::instance
static SickScanRadarSingleton * instance
Definition: sick_generic_radar.h:174
AMPL1_KEYWORD
#define AMPL1_KEYWORD
sick_scan_xd::PointCloud2withEcho
Definition: sick_generic_callback.h:76
sick_generic_callback.h
sick_scan_xd::SickScanRadarObject::ObjId
int ObjId() const
Definition: sick_generic_radar.h:154
sick_scan_xd::INT_4BYTE_UNION::i32_val
int32_t i32_val[1]
Definition: sick_generic_radar.cpp:162
sick_scan_xd
Definition: abstract_parser.cpp:65
data
data
f
f
sick_ros_wrapper.h
sick_scan_xd::SickScanRadarSingleton::getEmulation
bool getEmulation(void)
Definition: sick_generic_radar.cpp:311
P3DY1_KEYWORD
#define P3DY1_KEYWORD
sick_scan_xd::INT_4BYTE_UNION::i8_val
int8_t i8_val[4]
Definition: sick_generic_radar.cpp:160
deg2rad
#define deg2rad
Definition: BasicDatatypes.hpp:83
ROS_HEADER_SEQ
#define ROS_HEADER_SEQ(msgheader, value)
Definition: sick_ros_wrapper.h:162
sick_scan_xd::SickScanRadarRawTarget::Ampl
float Ampl() const
Definition: sick_generic_radar.h:101
sick_scan_xd::SickScanRadarSingleton::cloud_radar_rawtarget_pub_
rosPublisher< ros_sensor_msgs::PointCloud2 > cloud_radar_rawtarget_pub_
Definition: sick_generic_radar.h:187
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
Definition: sick_scan_logging.h:123
sick_scan_xd::getHexValue_32_16_8_signed
static int getHexValue_32_16_8_signed(std::string str)
Definition: sick_generic_radar.cpp:166
MODE1_KEYWORD
#define MODE1_KEYWORD
ROS_INFO_STREAM
#define ROS_INFO_STREAM(...)
Definition: sick_scan_ros2_example.cpp:71
sick_scan_xd::RadarDatagramField::toInteger
bool toInteger(T &value) const
Definition: sick_generic_radar.cpp:322
sick_scan_xd::SickScanRadarSingleton::parseRadarDatagram
int parseRadarDatagram(char *datagram, size_t datagram_length, bool useBinaryProtocol, sick_scan_msg::RadarScan *msgPtr, std::vector< SickScanRadarObject > &objectList, std::vector< SickScanRadarRawTarget > &rawTargetList, int verboseLevel=0)
Parsing Ascii datagram.
Definition: sick_generic_radar.cpp:612
sick_scan_xd::INT_4BYTE_UNION
Definition: sick_generic_radar.cpp:157
sick_scan_xd::appendRadarDatagramField
static bool appendRadarDatagramField(char_ptr &datagram, size_t &datagram_length, size_t field_length, std::vector< RadarDatagramField > &fields)
Definition: sick_generic_radar.cpp:434
sick_generic_parser.h
sick_scan_xd::convertScaledIntValue
float convertScaledIntValue(int value, float scale, float offset)
Definition: sick_generic_radar.cpp:275
polar_to_cartesian_pointcloud_ros1.node
node
Definition: polar_to_cartesian_pointcloud_ros1.py:81
sick_scan_common_tcp.h
AZMT1_KEYWORD
#define AZMT1_KEYWORD
sick_scan_xd::SickScanRadarRawTarget::Dist
float Dist() const
Definition: sick_generic_radar.h:83
sick_scan_xd::SickScanRadarSingleton::parseDatagram
int parseDatagram(rosTime timeStamp, unsigned char *receiveBuffer, int actual_length, bool useBinaryProtocol)
Definition: sick_generic_radar.cpp:1472
range_max
float range_max
Definition: sick_scan_test.cpp:529
P3DX1_KEYWORD
#define P3DX1_KEYWORD
rosPublish
void rosPublish(rosPublisher< T > &publisher, const T &msg)
Definition: sick_ros_wrapper.h:203
multiscan_receiver.mode
string mode
Definition: multiscan_receiver.py:348
sick_scan_xd::SickScanCommon::dumpDatagramForDebugging
static bool dumpDatagramForDebugging(unsigned char *buffer, int bufLen, bool isBinary=true)
Definition: sick_scan_common.cpp:4233
sick_scan_xd::ExitSuccess
@ ExitSuccess
Definition: abstract_parser.h:46
sick_scan_xd::SickScanRadarObject::P3Dx
float P3Dx() const
Definition: sick_generic_radar.h:124
sick_scan_xd::SickScanRadarSingleton::m_add_transform_xyz_rpy
sick_scan_xd::SickCloudTransform m_add_transform_xyz_rpy
Definition: sick_generic_radar.h:191
ros::NodeHandle
sick_scan_xd::radarFieldToInt32
static int32_t radarFieldToInt32(const RadarDatagramField &field, bool useBinaryProtocol)
Definition: sick_generic_radar.cpp:368
rosGetParam
bool rosGetParam(rosNodePtr nh, const std::string &param_name, T &param_value)
Definition: sick_ros_wrapper.h:167
sick_scan_xd::SickScanRadarSingleton::getInstance
static SickScanRadarSingleton * getInstance(rosNodePtr nh)
Definition: sick_generic_radar.cpp:88
sick_scan_xd::INT_4BYTE_UNION::i16_val
int16_t i16_val[2]
Definition: sick_generic_radar.cpp:161
sick_scan_xd::RadarDatagramField::RadarDatagramField
RadarDatagramField(char *_data=0, size_t _len=0)
Definition: sick_generic_radar.cpp:319
sick_scan_xd::radarFieldToFloat
static float radarFieldToFloat(const RadarDatagramField &field, bool useBinaryProtocol)
Definition: sick_generic_radar.cpp:403
sick_scan_xd::SickScanRadarSingleton::getNameOfRadar
std::string getNameOfRadar()
Definition: sick_generic_radar.h:216
sick_scan_xd::SickScanRadarObject::ObjLength
float ObjLength() const
Definition: sick_generic_radar.h:148
range_min
float range_min
Definition: sick_scan_test.cpp:528
sick_scan_xd::radarFieldToUint32
static uint32_t radarFieldToUint32(const RadarDatagramField &field, bool useBinaryProtocol)
Definition: sick_generic_radar.cpp:334
ros::Time
sick_scan_xd::getShortValue
int16_t getShortValue(std::string str)
Definition: sick_generic_radar.cpp:126
sick_scan_xd::RADAR_1D
@ RADAR_1D
Definition: sick_generic_parser.h:105
sick_scan_xd::RadarDatagramField::len
size_t len
Definition: sick_generic_radar.cpp:321
sick_scan_xd::notifyRadarScanListener
void notifyRadarScanListener(rosNodePtr handle, const sick_scan_msg::RadarScan *msg)
Definition: sick_generic_callback.cpp:194
sick_scan_xd::SickScanRadarSingleton::simulateAsciiDatagram
void simulateAsciiDatagram(unsigned char *receiveBuffer, int *actual_length)
Definition: sick_generic_radar.cpp:1106
sick_scan_xd::SickRangeFilter::apply
bool apply(float &range, bool &range_modified) const
Definition: sick_range_filter.h:107
sick_scan_xd::SickScanRadarSingleton::simulateAsciiDatagramFromFile
void simulateAsciiDatagramFromFile(unsigned char *receiveBuffer, int *actual_length, std::string filePattern)
Definition: sick_generic_radar.cpp:1406
OBJLEN_KEYWORD
#define OBJLEN_KEYWORD
length
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
sick_scan_xd::SickRangeFilter::resizePointCloud
void resizePointCloud(size_t rangeNum, ros_sensor_msgs::PointCloud2 &cloud)
Definition: sick_range_filter.h:182
sick_scan_xd::RadarDatagramField::data
char * data
Definition: sick_generic_radar.cpp:320
sick_scan_xd::SickScanRadarObject::V3Dy
float V3Dy() const
Definition: sick_generic_radar.h:142
sick_scan_xd::SickScanRadarRawTarget
Definition: sick_generic_radar.h:80
sick_scan_xd::SickScanRadarSingleton::setEmulation
void setEmulation(bool _emul)
Definition: sick_generic_radar.cpp:306
V3DY1_KEYWORD
#define V3DY1_KEYWORD
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(...)
Definition: sick_scan_ros2_example.cpp:72
sick_scan_xd::SickCloudTransform::applyTransform
void applyTransform(float_type &x, float_type &y, float_type &z)
Definition: sick_cloud_transform.h:100
UINT32
uint32_t UINT32
Definition: BasicDatatypes.hpp:72
V3DX1_KEYWORD
#define V3DX1_KEYWORD
sick_scan_xd::RadarScan
::sick_scan_xd::RadarScan_< std::allocator< void > > RadarScan
Definition: RadarScan.h:68
roswrap::message_traits::timeStamp
ros::Time * timeStamp(M &m)
returns TimeStamp<M>::pointer(m);
Definition: message_traits.h:317
sick_scan_xd::SickScanRadarSingleton::radarType
RADAR_TYPE_ENUM radarType
Definition: sick_generic_radar.h:184
roswrap::message_traits::header
std_msgs::Header * header(M &m)
returns Header<M>::pointer(m);
Definition: message_traits.h:281
sick_scan_xd::notifyCartesianPointcloudListener
void notifyCartesianPointcloudListener(rosNodePtr handle, const sick_scan_xd::PointCloud2withEcho *msg)
Definition: sick_generic_callback.cpp:74
sick_scan_xd::RangeFilterResultHandling
enum sick_scan_xd::RangeFilterResultHandlingEnum RangeFilterResultHandling
DIST1_KEYWORD
#define DIST1_KEYWORD
sick_scan_xd::SickScanRadarRawTarget::Mode
int Mode() const
Definition: sick_generic_radar.h:107
sick_scan_xd::radarFieldToString
static std::string radarFieldToString(const RadarDatagramField &field, bool useBinaryProtocol)
Definition: sick_generic_radar.cpp:427
sick_scan_xd::SickScanRadarSingleton::SickScanRadarSingleton
SickScanRadarSingleton(rosNodePtr nh)
Definition: sick_generic_radar.cpp:98
sick_scan_xd::SickScanRadarSingleton::cloud_radar_track_pub_
rosPublisher< ros_sensor_msgs::PointCloud2 > cloud_radar_track_pub_
Definition: sick_generic_radar.h:188
rosDeclareParam
void rosDeclareParam(rosNodePtr nh, const std::string &param_name, const T &param_value)
Definition: sick_ros_wrapper.h:166
sick_scan_xd::getHexValue
int getHexValue(std::string str)
Definition: sick_generic_radar.cpp:205
SICK_SCANNER_RMS_XXXX_NAME
#define SICK_SCANNER_RMS_XXXX_NAME
Definition: sick_generic_parser.h:73
VRAD1_KEYWORD
#define VRAD1_KEYWORD
sick_scan_xd::splitBinaryRadarDatagramToFields
static std::vector< RadarDatagramField > splitBinaryRadarDatagramToFields(char *datagram, size_t datagram_length, int verboseLevel)
Definition: sick_generic_radar.cpp:447
sick_scan_xd::ExitError
@ ExitError
Definition: abstract_parser.h:47
sick_scan_xd::char_ptr
char * char_ptr
Definition: sick_generic_radar.cpp:432
sick_scan_xd::SickScanRadarSingleton
Definition: sick_generic_radar.h:170
sick_scan_xd::SickScanRadarObject::V3Dx
float V3Dx() const
Definition: sick_generic_radar.h:136
sick_scan_xd::SickRangeFilter
Definition: sick_range_filter.h:85


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:10