rawdata.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007 Austin Robot Technology, Patrick Beeson
3  * Copyright (C) 2009, 2010, 2012 Austin Robot Technology, Jack O'Quin
4  * Copyright (C) 2017 Robosense, Tony Zhang
5  *
6  *
7 
8  Copyright (C) 2010-2013 Austin Robot Technology, and others
9  All rights reserved.
10 
11 
12 Modified BSD License:
13 --------------------
14 
15  Redistribution and use in source and binary forms, with or without
16  modification, are permitted provided that the following conditions
17  are met:
18 
19  * Redistributions of source code must retain the above copyright
20  notice, this list of conditions and the following disclaimer.
21 
22  * Redistributions in binary form must reproduce the above
23  copyright notice, this list of conditions and the following
24  disclaimer in the documentation and/or other materials provided
25  with the distribution.
26 
27  * Neither the names of the University of Texas at Austin, nor
28  Austin Robot Technology, nor the names of other contributors may
29  be used to endorse or promote products derived from this
30  software without specific prior written permission.
31 
32  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
36  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
37  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
38  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
42  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 POSSIBILITY OF SUCH DAMAGE.
44  */
45 
55 #include "rawdata.h"
56 
57 namespace rslidar_rawdata
58 {
60 {
61  this->is_init_angle_ = false;
62  this->is_init_curve_ = false;
63  this->is_init_top_fw_ = false;
64 }
65 
67 {
68  std::string anglePath, curvesPath, channelPath, curvesRatePath;
69  std::string model;
70 
71  private_nh.param("curves_path", curvesPath, std::string(""));
72  private_nh.param("angle_path", anglePath, std::string(""));
73  private_nh.param("channel_path", channelPath, std::string(""));
74  private_nh.param("curves_rate_path", curvesRatePath, std::string(""));
75 
76  private_nh.param("max_distance", max_distance, 200.0f);
77  private_nh.param("min_distance", min_distance, 0.2f);
78 
79  ROS_INFO_STREAM("distance threshlod, max: " << max_distance << ", min: " << min_distance);
80 
81  private_nh.param("model", model, std::string("RS16"));
82  if (model == "RS16")
83  {
84  numOfLasers = 16;
85  }
86  else if (model == "RS32")
87  {
88  numOfLasers = 32;
89  TEMPERATURE_RANGE = 50;
90  }
91 
92  intensityFactor = 51;
93  intensity_mode_ = 1;
94 
96  FILE* f_inten = fopen(curvesPath.c_str(), "r");
97  int loopi = 0;
98  int loopj = 0;
99  int loop_num;
100  if (!f_inten)
101  {
102  ROS_ERROR_STREAM("curves_path: '" << curvesPath << "' does not exist");
103  }
104  else
105  {
106  fseek(f_inten, 0, SEEK_END); //定位到文件末
107  int size = ftell(f_inten); //文件长度
108 
109  if (size > 10000) //老版的curve
110  {
111  Curvesis_new = false;
112  loop_num = 1600;
113  }
114  else
115  {
116  Curvesis_new = true;
117  loop_num = 7;
118  }
119  fseek(f_inten, 0, SEEK_SET);
120  while (!feof(f_inten))
121  {
122  float a[32];
123  loopi++;
124 
125  if (loopi > loop_num)
126  break;
127  if (numOfLasers == 16)
128  {
129  int tmp = fscanf(f_inten, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n", &a[0], &a[1], &a[2], &a[3],
130  &a[4], &a[5], &a[6], &a[7], &a[8], &a[9], &a[10], &a[11], &a[12], &a[13], &a[14], &a[15]);
131  }
132  else if (numOfLasers == 32)
133  {
134  int tmp = fscanf(f_inten, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,"
135  "%f,%f,%f,%f\n",
136  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9], &a[10], &a[11], &a[12],
137  &a[13], &a[14], &a[15], &a[16], &a[17], &a[18], &a[19], &a[20], &a[21], &a[22], &a[23], &a[24],
138  &a[25], &a[26], &a[27], &a[28], &a[29], &a[30], &a[31]);
139  }
140  if (Curvesis_new)
141  {
142  for (loopj = 0; loopj < numOfLasers; loopj++)
143  {
144  aIntensityCal[loopi - 1][loopj] = a[loopj];
145  }
146  }
147  else
148  {
149  for (loopj = 0; loopj < numOfLasers; loopj++)
150  {
151  aIntensityCal_old[loopi - 1][loopj] = a[loopj];
152  }
153  }
154  // ROS_INFO_STREAM("new is " << a[0]);
155  }
156  fclose(f_inten);
157  }
158  //=============================================================
159  FILE* f_angle = fopen(anglePath.c_str(), "r");
160  if (!f_angle)
161  {
162  ROS_ERROR_STREAM("angle_path: '" << anglePath << "' does not exist");
163  }
164  else
165  {
166  float b[32], d[32];
167  int loopk = 0;
168  int loopn = 0;
169  while (!feof(f_angle))
170  {
171  int tmp = fscanf(f_angle, "%f,%f\n", &b[loopk], &d[loopk]);
172  loopk++;
173  if (loopk > (numOfLasers - 1))
174  break;
175  }
176  for (loopn = 0; loopn < numOfLasers; loopn++)
177  {
178  VERT_ANGLE[loopn] = b[loopn] / 180 * M_PI;
179  HORI_ANGLE[loopn] = d[loopn] * 100;
180  }
181  fclose(f_angle);
182  }
183 
184  //=============================================================
185  FILE* f_channel = fopen(channelPath.c_str(), "r");
186  if (!f_channel)
187  {
188  ROS_ERROR_STREAM("channel_path: '" << channelPath << "' does not exist");
189  }
190  else
191  {
192  int loopl = 0;
193  int loopm = 0;
194  int c[51];
195  int tempMode = 1;
196  while (!feof(f_channel))
197  {
198  if (numOfLasers == 16)
199  {
200  int tmp = fscanf(f_channel,
201  "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%"
202  "d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
203  &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12],
204  &c[13], &c[14], &c[15], &c[16], &c[17], &c[18], &c[19], &c[20], &c[21], &c[22], &c[23], &c[24],
205  &c[25], &c[26], &c[27], &c[28], &c[29], &c[30], &c[31], &c[32], &c[33], &c[34], &c[35], &c[36],
206  &c[37], &c[38], &c[39], &c[40]);
207  }
208  else
209  {
210  int tmp = fscanf(
211  f_channel, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%"
212  "d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
213  &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13],
214  &c[14], &c[15], &c[16], &c[17], &c[18], &c[19], &c[20], &c[21], &c[22], &c[23], &c[24], &c[25], &c[26],
215  &c[27], &c[28], &c[29], &c[30], &c[31], &c[32], &c[33], &c[34], &c[35], &c[36], &c[37], &c[38], &c[39],
216  &c[40], &c[41], &c[42], &c[43], &c[44], &c[45], &c[46], &c[47], &c[48], &c[49], &c[50]);
217  }
218  // if (c[1] < 100 || c[1] > 3000)
219  // {
220  // tempMode = 0;
221  // }
222  for (loopl = 0; loopl < TEMPERATURE_RANGE + 1; loopl++)
223  {
224  g_ChannelNum[loopm][loopl] = c[tempMode * loopl];
225  }
226  loopm++;
227  if (loopm > (numOfLasers - 1))
228  {
229  break;
230  }
231  }
232  fclose(f_channel);
233  }
234 
235  if (numOfLasers == 32)
236  {
237  FILE* f_curvesRate = fopen(curvesRatePath.c_str(), "r");
238  if (!f_curvesRate)
239  {
240  ROS_ERROR_STREAM("curves_path: '" << curvesRatePath << "' does not exist");
241  for (int i = 0; i < 32; ++i)
242  {
243  CurvesRate[i] = 1.0;
244  }
245  }
246  else
247  {
248  int loopk = 0;
249  while (!feof(f_curvesRate))
250  {
251  int tmp = fscanf(f_curvesRate, "%f\n", &CurvesRate[loopk]);
252  loopk++;
253  if (loopk > (numOfLasers - 1))
254  break;
255  }
256  fclose(f_curvesRate);
257  }
258  }
259 
260  // receive difop data
261  // subscribe to difop rslidar packets, if not right correct data in difop, it will not revise the correct data in the
262  // VERT_ANGLE, HORI_ANGLE etc.
263  difop_sub_ = node.subscribe("rslidar_packets_difop", 10, &RawData::processDifop, (RawData*)this);
264 }
265 
266 void RawData::processDifop(const rslidar_msgs::rslidarPacket::ConstPtr& difop_msg)
267 {
268  // std::cout << "Enter difop callback!" << std::endl;
269  const uint8_t* data = &difop_msg->data[0];
270 
271  if (!this->is_init_top_fw_)
272  {
273  if ((data[41] == 0x00 && data[42] == 0x00 && data[43] == 0x00) ||
274  (data[41] == 0xff && data[42] == 0xff && data[43] == 0xff) ||
275  (data[41] == 0x55 && data[42] == 0xaa && data[43] == 0x5a))
276  {
277  dis_resolution_mode = 1; // 1cm resolution
278  std::cout << "The distance resolution is 1cm" << std::endl;
279  }
280  else
281  {
282  dis_resolution_mode = 0; // 0.5cm resolution
283  std::cout << "The distance resolution is 0.5cm" << std::endl;
284  }
285  this->is_init_top_fw_ = true;
286  }
287 
288  if (!this->is_init_curve_)
289  {
290  // check header
291  if (data[0] == 0xa5 && data[1] == 0xff && data[2] == 0x00 && data[3] == 0x5a)
292  {
293  bool curve_flag = true;
294  // check difop reigon has beed flashed the right data
295  if ((data[50] == 0x00 || data[50] == 0xff) && (data[51] == 0x00 || data[51] == 0xff) &&
296  (data[52] == 0x00 || data[52] == 0xff) && (data[53] == 0x00 || data[53] == 0xff))
297  {
298  curve_flag = false;
299  }
300 
301  // TODO check why rsview here no 32 laser, be more careful the new, old version
302  // Init curves
303  if (curve_flag)
304  {
305  unsigned char checkbit;
306  int bit1, bit2;
307  for (int loopn = 0; loopn < numOfLasers; ++loopn)
308  {
309  // check the curves' parameter in difop
310  checkbit = *(data + 50 + loopn * 15) ^ *(data + 50 + loopn * 15 + 1);
311  for (int loopm = 1; loopm < 7; ++loopm)
312  {
313  checkbit = checkbit ^ (*(data + 50 + loopn * 15 + loopm * 2)) ^ (*(data + 50 + loopn * 15 + loopm * 2 + 1));
314  }
315  if (checkbit != *(data + 50 + loopn * 15 + 14))
316  {
317  return;
318  }
319  }
320  for (int loopn = 0; loopn < numOfLasers; ++loopn)
321  {
322  // calculate curves' parameters
323  bit1 = static_cast<int>(*(data + 50 + loopn * 15));
324  bit2 = static_cast<int>(*(data + 50 + loopn * 15 + 1));
325  aIntensityCal[0][loopn] = (bit1 * 256 + bit2) * 0.001;
326  bit1 = static_cast<int>(*(data + 50 + loopn * 15 + 2));
327  bit2 = static_cast<int>(*(data + 50 + loopn * 15 + 3));
328  aIntensityCal[1][loopn] = (bit1 * 256 + bit2) * 0.001;
329  bit1 = static_cast<int>(*(data + 50 + loopn * 15 + 4));
330  bit2 = static_cast<int>(*(data + 50 + loopn * 15 + 5));
331  aIntensityCal[2][loopn] = (bit1 * 256 + bit2) * 0.001;
332  bit1 = static_cast<int>(*(data + 50 + loopn * 15 + 6));
333  bit2 = static_cast<int>(*(data + 50 + loopn * 15 + 7));
334  aIntensityCal[3][loopn] = (bit1 * 256 + bit2) * 0.001;
335  bit1 = static_cast<int>(*(data + 50 + loopn * 15 + 8));
336  bit2 = static_cast<int>(*(data + 50 + loopn * 15 + 9));
337  aIntensityCal[4][loopn] = (bit1 * 256 + bit2) * 0.00001;
338  bit1 = static_cast<int>(*(data + 50 + loopn * 15 + 10));
339  bit2 = static_cast<int>(*(data + 50 + loopn * 15 + 11));
340  aIntensityCal[5][loopn] = -(bit1 * 256 + bit2) * 0.0001;
341  bit1 = static_cast<int>(*(data + 50 + loopn * 15 + 12));
342  bit2 = static_cast<int>(*(data + 50 + loopn * 15 + 13));
343  aIntensityCal[6][loopn] = (bit1 * 256 + bit2) * 0.001;
344  }
345  this->is_init_curve_ = true;
346  std::cout << "this->is_init_curve_ = "
347  << "true!" << std::endl;
348  Curvesis_new = true;
349  }
350 
351  if ((data[290] != 0x00) && (data[290] != 0xff))
352  {
353  intensityFactor = static_cast<int>(*(data + 290)); // intensity factor introduced since than 20181115
354  // std::cout << intensityFactor << std::endl;
355  }
356 
357  if ((data[291] == 0x00) || (data[291] == 0xff) || (data[291] == 0xa1))
358  {
359  intensity_mode_ = 1; // mode for the top firmware lower than T6R23V8(16) or T9R23V6(32)
360  // std::cout << "intensity mode is 1" << std::endl;
361  }
362  else if (data[291] == 0xb1)
363  {
364  intensity_mode_ = 2; // mode for the top firmware higher than T6R23V8(16) or T9R23V6(32)
365  // std::cout << "intensity mode is 2" << std::endl;
366  }
367  }
368  }
369 
370  if (!this->is_init_angle_)
371  {
372  // check header
373  if (data[0] == 0xa5 && data[1] == 0xff && data[2] == 0x00 && data[3] == 0x5a)
374  {
375  bool angle_flag = true;
376  // check difop reigon has beed flashed the right data
377  if ((data[1165] == 0x00 || data[1165] == 0xff) && (data[1166] == 0x00 || data[1166] == 0xff) &&
378  (data[1167] == 0x00 || data[1167] == 0xff) && (data[1168] == 0x00 || data[1168] == 0xff))
379  {
380  angle_flag = false;
381  }
382  // angle
383  if (angle_flag)
384  {
385  // TODO check the HORI_ANGLE
386  int bit1, bit2, bit3, symbolbit;
387  for (int loopn = 0; loopn < numOfLasers; ++loopn)
388  {
389  if (loopn < 8 && numOfLasers == 16)
390  {
391  symbolbit = -1;
392  }
393  else
394  {
395  symbolbit = 1;
396  }
397  bit1 = static_cast<int>(*(data + 1165 + loopn * 3));
398  bit2 = static_cast<int>(*(data + 1165 + loopn * 3 + 1));
399  bit3 = static_cast<int>(*(data + 1165 + loopn * 3 + 2));
400  VERT_ANGLE[loopn] = (bit1 * 256 * 256 + bit2 * 256 + bit3) * symbolbit * 0.0001f / 180 * M_PI;
401  // std::cout << VERT_ANGLE[loopn] << std::endl;
402  // TODO
403  HORI_ANGLE[loopn] = 0;
404  }
405  this->is_init_angle_ = true;
406  std::cout << "this->is_init_angle_ = "
407  << "true!" << std::endl;
408  }
409  }
410  }
411  // std::cout << "DIFOP data! +++++++++++++" << std::endl;
412 }
413 
414 float RawData::pixelToDistance(int pixelValue, int passageway)
415 {
416  float DistanceValue;
417  int indexTemper = estimateTemperature(temper) - TEMPERATURE_MIN;
418  if (pixelValue <= g_ChannelNum[passageway][indexTemper])
419  {
420  DistanceValue = 0.0;
421  }
422  else
423  {
424  DistanceValue = (float)(pixelValue - g_ChannelNum[passageway][indexTemper]);
425  }
426  return DistanceValue;
427 }
428 
429 int RawData::correctAzimuth(float azimuth_f, int passageway)
430 {
431  int azimuth;
432  if (azimuth_f > 0.0 && azimuth_f < 3000.0)
433  {
434  azimuth_f = azimuth_f + HORI_ANGLE[passageway] + 36000.0f;
435  }
436  else
437  {
438  azimuth_f = azimuth_f + HORI_ANGLE[passageway];
439  }
440  azimuth = (int)azimuth_f;
441  azimuth %= 36000;
442 
443  return azimuth;
444 }
445 
446 //------------------------------------------------------------
447 //校准反射强度值
448 float RawData::calibrateIntensity(float intensity, int calIdx, int distance)
449 {
450  int algDist;
451  int sDist;
452  int uplimitDist;
453  float realPwr;
454  float refPwr;
455  float tempInten;
456  float distance_f;
457  float endOfSection1, endOfSection2;
458 
459  int temp = estimateTemperature(temper);
460 
461  realPwr = std::max((float)(intensity / (1 + (temp - TEMPERATURE_MIN) / 24.0f)), 1.0f);
462  // realPwr = intensity;
463 
464  if (intensity_mode_ == 1)
465  {
466  // transform the one byte intensity value to two byte
467  if ((int)realPwr < 126)
468  realPwr = realPwr * 4.0f;
469  else if ((int)realPwr >= 126 && (int)realPwr < 226)
470  realPwr = (realPwr - 125.0f) * 16.0f + 500.0f;
471  else
472  realPwr = (realPwr - 225.0f) * 256.0f + 2100.0f;
473  }
474  else if (intensity_mode_ == 2)
475  {
476  // the caculation for the firmware after T6R23V8(16) and T9R23V6(32)
477  if ((int)realPwr < 64)
478  realPwr = realPwr;
479  else if ((int)realPwr >= 64 && (int)realPwr < 176)
480  realPwr = (realPwr - 64.0f) * 4.0f + 64.0f;
481  else
482  realPwr = (realPwr - 176.0f) * 16.0f + 512.0f;
483  }
484  else
485  {
486  std::cout << "The intensity mode is not right" << std::endl;
487  }
488 
489  int indexTemper = estimateTemperature(temper) - TEMPERATURE_MIN;
490  uplimitDist = g_ChannelNum[calIdx][indexTemper] + DISTANCE_MAX_UNITS;
491  // limit sDist
492  sDist = (distance > g_ChannelNum[calIdx][indexTemper]) ? distance : g_ChannelNum[calIdx][indexTemper];
493  sDist = (sDist < uplimitDist) ? sDist : uplimitDist;
494  // minus the static offset (this data is For the intensity cal useage only)
495  algDist = sDist - g_ChannelNum[calIdx][indexTemper];
496 
497  // calculate intensity ref curves
498  float refPwr_temp = 0.0f;
499  int order = 3;
500  endOfSection1 = 5.0f;
501  endOfSection2 = 40.0;
502 
503  if (dis_resolution_mode == 0)
504  {
505  distance_f = (float)algDist * DISTANCE_RESOLUTION_NEW;
506  }
507  else
508  {
509  distance_f = (float)algDist * DISTANCE_RESOLUTION;
510  }
511 
512  if (intensity_mode_ == 1)
513  {
514  if (distance_f <= endOfSection1)
515  {
516  refPwr_temp = aIntensityCal[0][calIdx] * exp(aIntensityCal[1][calIdx] - aIntensityCal[2][calIdx] * distance_f) +
517  aIntensityCal[3][calIdx];
518  // printf("a-calIdx=%d,distance_f=%f,refPwr=%f\n",calIdx,distance_f,refPwr_temp);
519  }
520  else
521  {
522  for (int i = 0; i < order; i++)
523  {
524  refPwr_temp += aIntensityCal[i + 4][calIdx] * (pow(distance_f, order - 1 - i));
525  }
526  // printf("b-calIdx=%d,distance_f=%f,refPwr=%f\n",calIdx,distance_f,refPwr_temp);
527  }
528  }
529  else if (intensity_mode_ == 2)
530  {
531  if (distance_f <= endOfSection1)
532  {
533  refPwr_temp = aIntensityCal[0][calIdx] * exp(aIntensityCal[1][calIdx] - aIntensityCal[2][calIdx] * distance_f) +
534  aIntensityCal[3][calIdx];
535  // printf("a-calIdx=%d,distance_f=%f,refPwr=%f\n",calIdx,distance_f,refPwr_temp);
536  }
537  else if (distance_f > endOfSection1 && distance_f <= endOfSection2)
538  {
539  for (int i = 0; i < order; i++)
540  {
541  refPwr_temp += aIntensityCal[i + 4][calIdx] * (pow(distance_f, order - 1 - i));
542  }
543  // printf("b-calIdx=%d,distance_f=%f,refPwr=%f\n",calIdx,distance_f,refPwr_temp);
544  }
545  else
546  {
547  float refPwr_temp0 = 0.0f;
548  float refPwr_temp1 = 0.0f;
549  for (int i = 0; i < order; i++)
550  {
551  refPwr_temp0 += aIntensityCal[i + 4][calIdx] * (pow(40.0f, order - 1 - i));
552  refPwr_temp1 += aIntensityCal[i + 4][calIdx] * (pow(39.0f, order - 1 - i));
553  }
554  refPwr_temp = 0.3f * (refPwr_temp0 - refPwr_temp1) * distance_f + refPwr_temp0;
555  }
556  }
557  else
558  {
559  std::cout << "Invalid intensity mode selected" << std::endl;
560  }
561 
562  refPwr = std::max(std::min(refPwr_temp, 500.0f), 4.0f);
563 
564  tempInten = (intensityFactor * refPwr) / realPwr;
565  if (numOfLasers == 32)
566  {
567  tempInten = tempInten * CurvesRate[calIdx];
568  }
569  tempInten = (int)tempInten > 255 ? 255.0f : tempInten;
570  return tempInten;
571 }
572 
573 //------------------------------------------------------------
574 //校准反射强度值 old
575 float RawData::calibrateIntensity_old(float intensity, int calIdx, int distance)
576 {
577  int algDist;
578  int sDist;
579  int uplimitDist;
580  float realPwr;
581  float refPwr;
582  float tempInten;
583 
584  int temp = estimateTemperature(temper);
585  realPwr = std::max((float)(intensity / (1 + (temp - TEMPERATURE_MIN) / 24.0f)), 1.0f);
586  // realPwr = intensity;
587 
588  if ((int)realPwr < 126)
589  realPwr = realPwr * 4.0f;
590  else if ((int)realPwr >= 126 && (int)realPwr < 226)
591  realPwr = (realPwr - 125.0f) * 16.0f + 500.0f;
592  else
593  realPwr = (realPwr - 225.0f) * 256.0f + 2100.0f;
594 
595  int indexTemper = estimateTemperature(temper) - TEMPERATURE_MIN;
596  uplimitDist = g_ChannelNum[calIdx][indexTemper] + 1400;
597  sDist = (distance > g_ChannelNum[calIdx][indexTemper]) ? distance : g_ChannelNum[calIdx][indexTemper];
598  sDist = (sDist < uplimitDist) ? sDist : uplimitDist;
599  // minus the static offset (this data is For the intensity cal useage only)
600  algDist = sDist - g_ChannelNum[calIdx][indexTemper];
601  // algDist = algDist < 1400? algDist : 1399;
602  refPwr = aIntensityCal_old[algDist][calIdx];
603 
604  tempInten = (51 * refPwr) / realPwr;
605  if (numOfLasers == 32)
606  {
607  tempInten = tempInten * CurvesRate[calIdx];
608  }
609  tempInten = (int)tempInten > 255 ? 255.0f : tempInten;
610  return tempInten;
611 }
612 
613 //------------------------------------------------------------
614 int RawData::isABPacket(int distance)
615 {
616  int ABflag = 0;
617  if ((distance & 32768) != 0)
618  {
619  ABflag = 1; // B
620  }
621  else
622  {
623  ABflag = 0; // A
624  }
625  return ABflag;
626 }
627 
628 //------------------------------------------------------------
629 float RawData::computeTemperature(unsigned char bit1, unsigned char bit2)
630 {
631  float Temp;
632  float bitneg = bit2 & 128; // 10000000
633  float highbit = bit2 & 127; // 01111111
634  float lowbit = bit1 >> 3;
635  if (bitneg == 128)
636  {
637  Temp = -1 * (highbit * 32 + lowbit) * 0.0625f;
638  }
639  else
640  {
641  Temp = (highbit * 32 + lowbit) * 0.0625f;
642  }
643 
644  return Temp;
645 }
646 
647 //------------------------------------------------------------
649 {
650  int temp = (int)floor(Temper + 0.5);
651  if (temp < TEMPERATURE_MIN)
652  {
653  temp = TEMPERATURE_MIN;
654  }
655  else if (temp > TEMPERATURE_MIN + TEMPERATURE_RANGE)
656  {
658  }
659 
660  return temp;
661 }
662 //------------------------------------------------------------
663 
669 void RawData::unpack(const rslidar_msgs::rslidarPacket& pkt, pcl::PointCloud<pcl::PointXYZI>::Ptr pointcloud)
670 {
671  if (numOfLasers == 32)
672  {
673  unpack_RS32(pkt, pointcloud);
674  return;
675  }
676  float azimuth; // 0.01 dgree
677  float intensity;
678  float azimuth_diff;
679  float azimuth_corrected_f;
680  int azimuth_corrected;
681 
682  const raw_packet_t* raw = (const raw_packet_t*)&pkt.data[42];
683 
684  for (int block = 0; block < BLOCKS_PER_PACKET; block++, this->block_num++) // 1 packet:12 data blocks
685  {
686  if (UPPER_BANK != raw->blocks[block].header)
687  {
688  ROS_INFO_STREAM_THROTTLE(180, "skipping RSLIDAR DIFOP packet");
689  break;
690  }
691 
692  if (tempPacketNum < 20000 && tempPacketNum > 0) // update temperature information per 20000 packets
693  {
694  tempPacketNum++;
695  }
696  else
697  {
698  temper = computeTemperature(pkt.data[38], pkt.data[39]);
699  // ROS_INFO_STREAM("Temp is: " << temper);
700  tempPacketNum = 1;
701  }
702 
703  azimuth = (float)(256 * raw->blocks[block].rotation_1 + raw->blocks[block].rotation_2);
704 
705  if (block < (BLOCKS_PER_PACKET - 1)) // 12
706  {
707  int azi1, azi2;
708  azi1 = 256 * raw->blocks[block + 1].rotation_1 + raw->blocks[block + 1].rotation_2;
709  azi2 = 256 * raw->blocks[block].rotation_1 + raw->blocks[block].rotation_2;
710  azimuth_diff = (float)((36000 + azi1 - azi2) % 36000);
711 
712  // Ingnore the block if the azimuth change abnormal
713  if (azimuth_diff <= 0.0 || azimuth_diff > 75.0)
714  {
715  continue;
716  }
717  }
718  else
719  {
720  int azi1, azi2;
721  azi1 = 256 * raw->blocks[block].rotation_1 + raw->blocks[block].rotation_2;
722  azi2 = 256 * raw->blocks[block - 1].rotation_1 + raw->blocks[block - 1].rotation_2;
723  azimuth_diff = (float)((36000 + azi1 - azi2) % 36000);
724 
725  // Ingnore the block if the azimuth change abnormal
726  if (azimuth_diff <= 0.0 || azimuth_diff > 75.0)
727  {
728  continue;
729  }
730  }
731 
732  for (int firing = 0, k = 0; firing < RS16_FIRINGS_PER_BLOCK; firing++) // 2
733  {
734  for (int dsr = 0; dsr < RS16_SCANS_PER_FIRING; dsr++, k += RAW_SCAN_SIZE) // 16 3
735  {
736  azimuth_corrected_f = azimuth + (azimuth_diff * ((dsr * RS16_DSR_TOFFSET) + (firing * RS16_FIRING_TOFFSET)) /
738  azimuth_corrected = ((int)round(azimuth_corrected_f)) % 36000; // convert to integral value...
739 
740  union two_bytes tmp;
741  tmp.bytes[1] = raw->blocks[block].data[k];
742  tmp.bytes[0] = raw->blocks[block].data[k + 1];
743  int distance = tmp.uint;
744 
745  // read intensity
746  intensity = raw->blocks[block].data[k + 2];
747  if (Curvesis_new)
748  intensity = calibrateIntensity(intensity, dsr, distance);
749  else
750  intensity = calibrateIntensity_old(intensity, dsr, distance);
751 
752  float distance2 = pixelToDistance(distance, dsr);
753  if (dis_resolution_mode == 0) // distance resolution is 0.5cm
754  {
755  distance2 = distance2 * DISTANCE_RESOLUTION_NEW;
756  }
757  else
758  {
759  distance2 = distance2 * DISTANCE_RESOLUTION;
760  }
761 
762  float arg_horiz = (float)azimuth_corrected / 18000.0f * M_PI;
763  float arg_vert = VERT_ANGLE[dsr];
764  pcl::PointXYZI point;
765 
766  if (distance2 > max_distance || distance2 < min_distance) // invalid distance
767  {
768  point.x = NAN;
769  point.y = NAN;
770  point.z = NAN;
771  point.intensity = 0;
772  pointcloud->at(2 * this->block_num + firing, dsr) = point;
773  }
774  else
775  {
776  // If you want to fix the rslidar Y aixs to the front side of the cable, please use the two line below
777  // point.x = dis * cos(arg_vert) * sin(arg_horiz);
778  // point.y = dis * cos(arg_vert) * cos(arg_horiz);
779 
780  // If you want to fix the rslidar X aixs to the front side of the cable, please use the two line below
781  point.y = -distance2 * cos(arg_vert) * sin(arg_horiz);
782  point.x = distance2 * cos(arg_vert) * cos(arg_horiz);
783  point.z = distance2 * sin(arg_vert);
784  point.intensity = intensity;
785  pointcloud->at(2 * this->block_num + firing, dsr) = point;
786  }
787  }
788  }
789  }
790 }
791 
792 void RawData::unpack_RS32(const rslidar_msgs::rslidarPacket& pkt, pcl::PointCloud<pcl::PointXYZI>::Ptr pointcloud)
793 {
794  float azimuth; // 0.01 dgree
795  float intensity;
796  float azimuth_diff;
797  float azimuth_corrected_f;
798  int azimuth_corrected;
799 
800  const raw_packet_t* raw = (const raw_packet_t*)&pkt.data[42];
801 
802  for (int block = 0; block < BLOCKS_PER_PACKET; block++, this->block_num++) // 1 packet:12 data blocks
803  {
804  if (UPPER_BANK != raw->blocks[block].header)
805  {
806  ROS_INFO_STREAM_THROTTLE(180, "skipping RSLIDAR DIFOP packet");
807  break;
808  }
809 
810  if (tempPacketNum < 20000 && tempPacketNum > 0) // update temperature information per 20000 packets
811  {
812  tempPacketNum++;
813  }
814  else
815  {
816  temper = computeTemperature(pkt.data[38], pkt.data[39]);
817  // ROS_INFO_STREAM("Temp is: " << temper);
818  tempPacketNum = 1;
819  }
820 
821  azimuth = (float)(256 * raw->blocks[block].rotation_1 + raw->blocks[block].rotation_2);
822 
823  if (block < (BLOCKS_PER_PACKET - 1)) // 12
824  {
825  int azi1, azi2;
826  azi1 = 256 * raw->blocks[block + 1].rotation_1 + raw->blocks[block + 1].rotation_2;
827  azi2 = 256 * raw->blocks[block].rotation_1 + raw->blocks[block].rotation_2;
828  azimuth_diff = (float)((36000 + azi1 - azi2) % 36000);
829 
830  // Ingnore the block if the azimuth change abnormal
831  if (azimuth_diff <= 0.0 || azimuth_diff > 25.0)
832  {
833  continue;
834  }
835  }
836  else
837  {
838  int azi1, azi2;
839  azi1 = 256 * raw->blocks[block].rotation_1 + raw->blocks[block].rotation_2;
840  azi2 = 256 * raw->blocks[block - 1].rotation_1 + raw->blocks[block - 1].rotation_2;
841  azimuth_diff = (float)((36000 + azi1 - azi2) % 36000);
842 
843  // Ingnore the block if the azimuth change abnormal
844  if (azimuth_diff <= 0.0 || azimuth_diff > 25.0)
845  {
846  continue;
847  }
848  }
849 
850  if (dis_resolution_mode == 0) // distance resolution is 0.5cm and delete the AB packet mechanism
851  {
852  for (int dsr = 0, k = 0; dsr < RS32_SCANS_PER_FIRING * RS32_FIRINGS_PER_BLOCK; dsr++, k += RAW_SCAN_SIZE) // 16 3
853  {
854  int dsr_temp;
855  if (dsr >= 16)
856  {
857  dsr_temp = dsr - 16;
858  }
859  else
860  {
861  dsr_temp = dsr;
862  }
863  azimuth_corrected_f = azimuth + (azimuth_diff * ((dsr_temp * RS32_DSR_TOFFSET)) / RS32_BLOCK_TDURATION);
864  azimuth_corrected = correctAzimuth(azimuth_corrected_f, dsr);
865 
866  union two_bytes tmp;
867  tmp.bytes[1] = raw->blocks[block].data[k];
868  tmp.bytes[0] = raw->blocks[block].data[k + 1];
869  int distance = tmp.uint;
870 
871  // read intensity
872  intensity = (float)raw->blocks[block].data[k + 2];
873  intensity = calibrateIntensity(intensity, dsr, distance);
874 
875  float distance2 = pixelToDistance(distance, dsr);
876  distance2 = distance2 * DISTANCE_RESOLUTION_NEW;
877 
878  float arg_horiz = (float)azimuth_corrected / 18000.0f * M_PI;
879  float arg_vert = VERT_ANGLE[dsr];
880  pcl::PointXYZI point;
881 
882  if (distance2 > max_distance || distance2 < min_distance) // invalid distance
883  {
884  point.x = NAN;
885  point.y = NAN;
886  point.z = NAN;
887  point.intensity = 0;
888  pointcloud->at(this->block_num, dsr) = point;
889  }
890  else
891  {
892  // If you want to fix the rslidar Y aixs to the front side of the cable, please use the two line below
893  // point.x = dis * cos(arg_vert) * sin(arg_horiz);
894  // point.y = dis * cos(arg_vert) * cos(arg_horiz);
895 
896  // If you want to fix the rslidar X aixs to the front side of the cable, please use the two line below
897  point.y = -distance2 * cos(arg_vert) * sin(arg_horiz);
898  point.x = distance2 * cos(arg_vert) * cos(arg_horiz);
899  point.z = distance2 * sin(arg_vert);
900  point.intensity = intensity;
901  pointcloud->at(this->block_num, dsr) = point;
902  }
903  }
904  }
905  else
906  {
907  // Estimate the type of packet
908  union two_bytes tmp_flag;
909  tmp_flag.bytes[1] = raw->blocks[block].data[0];
910  tmp_flag.bytes[0] = raw->blocks[block].data[1];
911  int ABflag = isABPacket(tmp_flag.uint);
912 
913  int k = 0;
914  int index;
915  for (int dsr = 0; dsr < RS32_SCANS_PER_FIRING * RS32_FIRINGS_PER_BLOCK; dsr++, k += RAW_SCAN_SIZE) // 16 3
916  {
917  if (ABflag == 1 && dsr < 16)
918  {
919  index = k + 48;
920  }
921  else if (ABflag == 1 && dsr >= 16)
922  {
923  index = k - 48;
924  }
925  else
926  {
927  index = k;
928  }
929 
930  int dsr_temp;
931  if (dsr >= 16)
932  {
933  dsr_temp = dsr - 16;
934  }
935  else
936  {
937  dsr_temp = dsr;
938  }
939  azimuth_corrected_f = azimuth + (azimuth_diff * ((dsr_temp * RS32_DSR_TOFFSET)) / RS32_BLOCK_TDURATION);
940  azimuth_corrected = correctAzimuth(azimuth_corrected_f, dsr);
941 
942  union two_bytes tmp;
943  tmp.bytes[1] = raw->blocks[block].data[index];
944  tmp.bytes[0] = raw->blocks[block].data[index + 1];
945  int ab_flag_in_block = isABPacket(tmp.uint);
946  int distance = tmp.uint - ab_flag_in_block * 32768;
947 
948  // read intensity
949  intensity = (float)raw->blocks[block].data[index + 2];
950  intensity = calibrateIntensity(intensity, dsr, distance);
951 
952  float distance2 = pixelToDistance(distance, dsr);
953  distance2 = distance2 * DISTANCE_RESOLUTION;
954 
955  float arg_horiz = (float)azimuth_corrected / 18000.0f * M_PI;
956  float arg_vert = VERT_ANGLE[dsr];
957  pcl::PointXYZI point;
958 
959  if (distance2 > max_distance || distance2 < min_distance) // invalid distance
960  {
961  point.x = NAN;
962  point.y = NAN;
963  point.z = NAN;
964  point.intensity = 0;
965  pointcloud->at(this->block_num, dsr) = point;
966  }
967  else
968  {
969  // If you want to fix the rslidar Y aixs to the front side of the cable, please use the two line below
970  // point.x = dis * cos(arg_vert) * sin(arg_horiz);
971  // point.y = dis * cos(arg_vert) * cos(arg_horiz);
972 
973  // If you want to fix the rslidar X aixs to the front side of the cable, please use the two line below
974  point.y = -distance2 * cos(arg_vert) * sin(arg_horiz);
975  point.x = distance2 * cos(arg_vert) * cos(arg_horiz);
976  point.z = distance2 * sin(arg_vert);
977  point.intensity = intensity;
978  pointcloud->at(this->block_num, dsr) = point;
979  }
980  }
981  }
982  }
983 }
984 
985 } // namespace rs_pointcloud
d
float CurvesRate[32]
Definition: rawdata.h:215
Interfaces for interpreting raw packets from the Robosense 3D LIDAR.
static const int RAW_SCAN_SIZE
Definition: rawdata.h:75
float computeTemperature(unsigned char bit1, unsigned char bit2)
Definition: rawdata.cc:629
static const float RS16_FIRING_TOFFSET
Definition: rawdata.h:96
static const int RS16_SCANS_PER_FIRING
Definition: rawdata.h:93
static const float DISTANCE_RESOLUTION_NEW
Definition: rawdata.h:85
float temper
Definition: rawdata.h:217
static const float RS32_BLOCK_TDURATION
Definition: rawdata.h:101
float calibrateIntensity(float inten, int calIdx, int distance)
Definition: rawdata.cc:448
f
static const float DISTANCE_MAX_UNITS
Definition: rawdata.h:86
uint16_t header
UPPER_BANK or LOWER_BANK.
Definition: rawdata.h:117
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::string model
Definition: convert.cc:57
int estimateTemperature(float Temper)
Definition: rawdata.cc:648
static const int RS32_SCANS_PER_FIRING
Definition: rawdata.h:100
uint8_t data[BLOCK_DATA_SIZE]
combine rotation1 and rotation2 together to get 0-35999, divide by 100 to get degrees ...
Definition: rawdata.h:120
Raw Rsldar packet.
Definition: rawdata.h:151
data
void unpack(const rslidar_msgs::rslidarPacket &pkt, pcl::PointCloud< pcl::PointXYZI >::Ptr pointcloud)
convert raw packet to point cloud
Definition: rawdata.cc:669
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const
static const float DISTANCE_RESOLUTION
Definition: rawdata.h:84
static const int RS16_FIRINGS_PER_BLOCK
Definition: rawdata.h:92
float aIntensityCal_old[1600][32]
Definition: rawdata.h:212
int isABPacket(int distance)
Definition: rawdata.cc:614
float calibrateIntensity_old(float inten, int calIdx, int distance)
Definition: rawdata.cc:575
ros::Subscriber difop_sub_
Definition: rawdata.h:197
float aIntensityCal[7][32]
Definition: rawdata.h:211
static const int BLOCKS_PER_PACKET
Definition: rawdata.h:135
float VERT_ANGLE[32]
Definition: rawdata.h:209
float HORI_ANGLE[32]
Definition: rawdata.h:210
int g_ChannelNum[32][51]
Definition: rawdata.h:214
static const float RS16_BLOCK_TDURATION
Definition: rawdata.h:94
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void loadConfigFile(ros::NodeHandle node, ros::NodeHandle private_nh)
Definition: rawdata.cc:66
static const uint16_t UPPER_BANK
Definition: rawdata.h:88
static const float RS16_DSR_TOFFSET
Definition: rawdata.h:95
void processDifop(const rslidar_msgs::rslidarPacket::ConstPtr &difop_msg)
Definition: rawdata.cc:266
#define ROS_INFO_STREAM(args)
static const int TEMPERATURE_MIN
Definition: rawdata.h:105
TFSIMD_FORCE_INLINE tfScalar distance2(const Vector3 &v) const
static const float RS32_DSR_TOFFSET
Definition: rawdata.h:102
float pixelToDistance(int pixelValue, int passageway)
Definition: rawdata.cc:414
#define ROS_ERROR_STREAM(args)
static const int RS32_FIRINGS_PER_BLOCK
Definition: rawdata.h:99
#define ROS_INFO_STREAM_THROTTLE(rate, args)
void unpack_RS32(const rslidar_msgs::rslidarPacket &pkt, pcl::PointCloud< pcl::PointXYZI >::Ptr pointcloud)
Definition: rawdata.cc:792
int tempPacketNum
Definition: rawdata.h:218
bool Curvesis_new
Definition: rawdata.h:213
raw_block_t blocks[BLOCKS_PER_PACKET]
Definition: rawdata.h:153
int correctAzimuth(float azimuth_f, int passageway)
Definition: rawdata.cc:429
RSLIDAR data conversion class.
Definition: rawdata.h:159
int TEMPERATURE_RANGE
Definition: rawdata.h:220


rslidar_pointcloud
Author(s): Tony Zhang , Tony Zhang, George Wang, Piyush Khandelwal, Jesse Vera
autogenerated on Mon Jun 10 2019 14:41:10