velodyne.cpp
Go to the documentation of this file.
1 /**************************************************************************************************
2  Software License Agreement (BSD License)
3 
4  Copyright (c) 2011-2013, LAR toolkit developers - University of Aveiro - http://lars.mec.ua.pt
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without modification, are permitted
8  provided that the following conditions are met:
9 
10  *Redistributions of source code must retain the above copyright notice, this list of
11  conditions and the following disclaimer.
12  *Redistributions in binary form must reproduce the above copyright notice, this list of
13  conditions and the following disclaimer in the documentation and/or other materials provided
14  with the distribution.
15  *Neither the name of the University of Aveiro nor the names of its contributors may be used to
16  endorse or promote products derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
19  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 ***************************************************************************************************/
35 #include <stdio.h>
36 #include <stdint.h>
37 #include <math.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <assert.h>
41 
42 #include "math_util.h"
43 
44 #include "velodyne.h"
45 
46 #define UPPER_MAGIC 0xeeff
47 #define LOWER_MAGIC 0xddff
48 
49 #include "velodyne-newunit.h"
50 
51 #define RADIANS_PER_LSB 0.00017453293
52 #define METERS_PER_LSB 0.002
53 
54 // return an upper bound on the # of samples in this message
56  int datalen)
57 {
58  return (datalen / 3) +1;
59 }
60 
62  const void *_data, int datalen)
63 {
64  vd->data = (uint8_t*) _data;
65  vd->data_remaining = datalen;
66  vd->i = 0;
67 
68  if (datalen != 1206) {
69  printf("velodyne: bad len %i\n", datalen);
70  vd->data_remaining = 0; // don't decode it.
71  return -1;
72  }
73 
74  // copy out the version string
75  if (vd->data[1202]=='v') {
76  vd->revolution_count = vd->data[1200] + (vd->data[1201]<<8);
77  memcpy(vd->version_string, &vd->data[1202], 4);
78  vd->version_string[4]=0;
79  } else {
80  vd->version_string[0]=0;
81  vd->revolution_count=-1;
82  }
83 
84  return 0;
85 }
86 
88  velodyne_sample_t *sample)
89 {
90  // if we finished the last block, "consume" this block of data.
91  if (vd->i == 32) {
92  vd->data_remaining -= 100;
93  vd->data += 100;
94  vd->i = 0;
95  }
96 
97  uint8_t *data = vd->data;
98 
99  // starting a new block?
100  if (vd->i == 0) {
101  // enough data for another block?
102  if (vd->data_remaining < 100)
103  return -1;
104 
105  int magic = data[0] + (data[1]<<8);
106 
107  if (magic == UPPER_MAGIC)
108  vd->laser_offset = 32;
109  else if (magic == LOWER_MAGIC)
110  vd->laser_offset = 0;
111  else {
112  printf("Unknown velodyne magic %4x\n", magic);
113  return -2;
114  }
115 
116  // position of velodyne head, constant for all 32 measurements that
117  // follow
118  vd->ctheta = 2*PI - (data[2] + (data[3]<<8)) * RADIANS_PER_LSB;
119  if (vd->ctheta == 2*PI)
120  vd->ctheta = 0;
121 
122  vd->sin_ctheta = sin(vd->ctheta);
123  vd->cos_ctheta = cos(vd->ctheta);
124  vd->i = 0;
125  }
126 
127  // Decode the laser sample
128  int i = vd->i;
129 
130  sample->physical = vd->laser_offset + i;
131  sample->logical = velodyne_physical_to_logical(v, sample->physical);
132 
133  struct velodyne_laser_calib *params = &v->lasers[sample->physical];
134 
135  sample->raw_range = (data[4 + i*3] + (data[5+i*3]<<8)) * METERS_PER_LSB;
136  sample->range = (sample->raw_range + params->range_offset) * (1.0 + params->range_scale_offset);
137  sample->ctheta = vd->ctheta;
138  sample->theta = mod2pi_ref(PI, vd->ctheta + params->rcf);
139  sample->phi = params->vcf;
140  sample->intensity = data[6 + i*3]/255.0;
141 
142  double sin_theta, cos_theta;
143  sin_theta = sin(sample->theta);
144  cos_theta = cos(sample->theta);
145  double sin_phi = v->sincos[sample->physical][0];
146  double cos_phi = v->sincos[sample->physical][1];
147 
148  sample->xyz[0] = sample->range * cos_theta * cos_phi;
149  sample->xyz[1] = sample->range * sin_theta * cos_phi;
150  sample->xyz[2] = sample->range * sin_phi;
151 
152  // handle horizontal offset ("parallax")
153  sample->xyz[0] -= params->hcf * vd->cos_ctheta;
154  sample->xyz[1] -= params->hcf * vd->sin_ctheta;
155  vd->i++;
156 
157  // successful decode
158  return 0;
159 }
160 
161 int velodyne_decode(velodyne_calib_t *v, const void *_data, int datalen,
162  double *_theta0,
163  double *ranges, double *intensities, double *thetas,
164  double *phis, int *laserids, int *nsamples, int *badscans)
165 {
166  if (datalen != 1206) {
167  printf("velodyne: bad len %i\n", datalen);
168  return -1;
169  }
170 
171  int out_idx = 0;
172  int laser_offset = 0;
173 
174  uint8_t *data;
175  for (data = (uint8_t*) _data;
176  datalen >= 100;
177  datalen-=100, data += 100) {
178 
179  int magic = data[0] + (data[1]<<8);
180 
181  if (magic == UPPER_MAGIC)
182  laser_offset = 32;
183  else if (magic == LOWER_MAGIC)
184  laser_offset = 0;
185  else {
186  printf("Unknown velodyne magic %4x\n", magic);
187  continue;
188  }
189 
190  double theta0 = 2*PI - (data[2] + (data[3]<<8)) * RADIANS_PER_LSB;
191  *_theta0 = theta0;
192 
193  int i;
194  for (i = 0; i < 32; i++) {
195  struct velodyne_laser_calib *params = &v->lasers[laser_offset + i];
196 
197  ranges[out_idx] = (data[4 + i*3] + (data[5+i*3]<<8)) * METERS_PER_LSB;
198  ranges[out_idx] *= (1.0 + params->range_scale_offset);
199  ranges[out_idx] -= params->range_offset;
200 
201  // skip illegally short ranges
202  if (ranges[out_idx] < 0.5) {
203  badscans[laser_offset+i]++;
204  continue;
205  }
206 
207  intensities[out_idx] = data[6 + i*3]/255.0;
208  thetas[out_idx] = theta0 + params->rcf;
209  phis[out_idx] = params->vcf;
210  laserids[out_idx] = laser_offset + i;
211  out_idx++;
212  }
213  }
214 
215  *nsamples = out_idx;
216  // last six bytes are status. we don't know what to do with them.
217 
218  return 0;
219 }
220 
222 {
223  printf("struct velodyne_laser_calib velodyne_NAME_ME_HERE[] = {\n");
224  int i;
225  for (i = 0; i < VELODYNE_NUM_LASERS; i++) {
226  struct velodyne_laser_calib *params = &v->lasers[i];
227  printf(" { %11.7f, %11.7f, %8.4f, %8.4f, %10.6f }, // laser %2d\n",
228  params->rcf, params->vcf, params->hcf, params->range_offset, params->range_scale_offset, i);
229  }
230  printf("};\n\n");
231 }
232 
233 
235 static int laser_phi_compare(const void *_a, const void *_b)
236 {
237  int a = *((int*) _a);
238  int b = *((int*) _b);
239 
240  if (__v->lasers[a].vcf < __v->lasers[b].vcf)
241  return -1;
242  return 1;
243 }
244 
245 // NOT REENTRANT
247 {
248  assert (!__v); // check for reentrancy...
249 
250  __v = v;
251 
252  int i;
253  for (i = 0; i < VELODYNE_NUM_LASERS; i++)
254  v->logical2physical[i] = i;
255  qsort(v->logical2physical, VELODYNE_NUM_LASERS, sizeof(int),
257 
258  int logical;
259  for (logical = 0; logical < VELODYNE_NUM_LASERS; logical++) {
260  v->physical2logical[v->logical2physical[logical]] = logical;
261  }
262 
263  int physical;
264  for (physical = 0; physical < VELODYNE_NUM_LASERS; physical++) {
265  v->sincos[physical][0] = sin(v->lasers[physical].vcf);
266  v->sincos[physical][1] = cos(v->lasers[physical].vcf);
267  }
268  __v = NULL;
269 
270  return 0;
271 }
272 
274 {
275  velodyne_calib_t *v = (velodyne_calib_t*) calloc(1, sizeof(velodyne_calib_t));
278 
279  return v;
280 }
int physical2logical[VELODYNE_NUM_LASERS]
Definition: velodyne.h:86
#define PI
Definition: math_util.h:42
Defines a struc for velodyne calibration.
#define UPPER_MAGIC
Definition: velodyne.cpp:46
header file with velodyne types
void velodyne_calib_dump(velodyne_calib_t *v)
Definition: velodyne.cpp:221
int logical2physical[VELODYNE_NUM_LASERS]
Definition: velodyne.h:87
struct velodyne_laser_calib velodyne_uncalibrated[]
int velodyne_decoder_estimate_samples(velodyne_calib_t *v, const void *_data, int datalen)
Definition: velodyne.cpp:55
static velodyne_calib_t * __v
Definition: velodyne.cpp:234
char version_string[16]
Definition: velodyne.h:57
double ctheta
Definition: velodyne.h:54
int32_t revolution_count
Definition: velodyne.h:56
velodyne_calib_t * velodyne_calib_create()
Definition: velodyne.cpp:273
#define METERS_PER_LSB
Definition: velodyne.cpp:52
static int velodyne_physical_to_logical(velodyne_calib_t *v, int phys)
Definition: velodyne.h:105
int velodyne_decoder_next(velodyne_calib_t *v, velodyne_decoder_t *vd, velodyne_sample_t *sample)
Definition: velodyne.cpp:87
int velodyne_decode(velodyne_calib_t *v, const void *_data, int datalen, double *_theta0, double *ranges, double *intensities, double *thetas, double *phis, int *laserids, int *nsamples, int *badscans)
Definition: velodyne.cpp:161
double theta
Definition: velodyne.h:67
static double mod2pi_ref(double ref, double vin)
Definition: math_util.h:100
double phi
Definition: velodyne.h:68
#define RADIANS_PER_LSB
Definition: velodyne.cpp:51
struct velodyne_laser_calib lasers[VELODYNE_NUM_LASERS]
Definition: velodyne.h:85
int data_remaining
Definition: velodyne.h:50
double cos_ctheta
Definition: velodyne.h:54
static int laser_phi_compare(const void *_a, const void *_b)
Definition: velodyne.cpp:235
double sincos[VELODYNE_NUM_LASERS][2]
Definition: velodyne.h:88
double sin_ctheta
Definition: velodyne.h:54
double intensity
Definition: velodyne.h:69
#define LOWER_MAGIC
Definition: velodyne.cpp:47
uint8_t * data
Definition: velodyne.h:48
int velodyne_decoder_init(velodyne_calib_t *v, velodyne_decoder_t *vd, const void *_data, int datalen)
Definition: velodyne.cpp:61
double raw_range
Definition: velodyne.h:64
double xyz[3]
Definition: velodyne.h:63
int velodyne_calib_precompute(velodyne_calib_t *v)
Definition: velodyne.cpp:246
double range_scale_offset
Definition: velodyne.h:80
double ctheta
Definition: velodyne.h:66
header file for math utilities
#define VELODYNE_NUM_LASERS
Definition: velodyne.h:43
double range
Definition: velodyne.h:65


mit_darpa_logs_player
Author(s): Miguel Oliveira
autogenerated on Mon Mar 2 2015 01:32:15