00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00035 #include <stdio.h>
00036 #include <stdint.h>
00037 #include <math.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <assert.h>
00041
00042 #include "math_util.h"
00043
00044 #include "velodyne.h"
00045
00046 #define UPPER_MAGIC 0xeeff
00047 #define LOWER_MAGIC 0xddff
00048
00049 #include "velodyne-newunit.h"
00050
00051 #define RADIANS_PER_LSB 0.00017453293
00052 #define METERS_PER_LSB 0.002
00053
00054
00055 int velodyne_decoder_estimate_samples(velodyne_calib_t *v, const void *_data,
00056 int datalen)
00057 {
00058 return (datalen / 3) +1;
00059 }
00060
00061 int velodyne_decoder_init(velodyne_calib_t *v, velodyne_decoder_t *vd,
00062 const void *_data, int datalen)
00063 {
00064 vd->data = (uint8_t*) _data;
00065 vd->data_remaining = datalen;
00066 vd->i = 0;
00067
00068 if (datalen != 1206) {
00069 printf("velodyne: bad len %i\n", datalen);
00070 vd->data_remaining = 0;
00071 return -1;
00072 }
00073
00074
00075 if (vd->data[1202]=='v') {
00076 vd->revolution_count = vd->data[1200] + (vd->data[1201]<<8);
00077 memcpy(vd->version_string, &vd->data[1202], 4);
00078 vd->version_string[4]=0;
00079 } else {
00080 vd->version_string[0]=0;
00081 vd->revolution_count=-1;
00082 }
00083
00084 return 0;
00085 }
00086
00087 int velodyne_decoder_next(velodyne_calib_t *v, velodyne_decoder_t *vd,
00088 velodyne_sample_t *sample)
00089 {
00090
00091 if (vd->i == 32) {
00092 vd->data_remaining -= 100;
00093 vd->data += 100;
00094 vd->i = 0;
00095 }
00096
00097 uint8_t *data = vd->data;
00098
00099
00100 if (vd->i == 0) {
00101
00102 if (vd->data_remaining < 100)
00103 return -1;
00104
00105 int magic = data[0] + (data[1]<<8);
00106
00107 if (magic == UPPER_MAGIC)
00108 vd->laser_offset = 32;
00109 else if (magic == LOWER_MAGIC)
00110 vd->laser_offset = 0;
00111 else {
00112 printf("Unknown velodyne magic %4x\n", magic);
00113 return -2;
00114 }
00115
00116
00117
00118 vd->ctheta = 2*PI - (data[2] + (data[3]<<8)) * RADIANS_PER_LSB;
00119 if (vd->ctheta == 2*PI)
00120 vd->ctheta = 0;
00121
00122 vd->sin_ctheta = sin(vd->ctheta);
00123 vd->cos_ctheta = cos(vd->ctheta);
00124 vd->i = 0;
00125 }
00126
00127
00128 int i = vd->i;
00129
00130 sample->physical = vd->laser_offset + i;
00131 sample->logical = velodyne_physical_to_logical(v, sample->physical);
00132
00133 struct velodyne_laser_calib *params = &v->lasers[sample->physical];
00134
00135 sample->raw_range = (data[4 + i*3] + (data[5+i*3]<<8)) * METERS_PER_LSB;
00136 sample->range = (sample->raw_range + params->range_offset) * (1.0 + params->range_scale_offset);
00137 sample->ctheta = vd->ctheta;
00138 sample->theta = mod2pi_ref(PI, vd->ctheta + params->rcf);
00139 sample->phi = params->vcf;
00140 sample->intensity = data[6 + i*3]/255.0;
00141
00142 double sin_theta, cos_theta;
00143 sin_theta = sin(sample->theta);
00144 cos_theta = cos(sample->theta);
00145 double sin_phi = v->sincos[sample->physical][0];
00146 double cos_phi = v->sincos[sample->physical][1];
00147
00148 sample->xyz[0] = sample->range * cos_theta * cos_phi;
00149 sample->xyz[1] = sample->range * sin_theta * cos_phi;
00150 sample->xyz[2] = sample->range * sin_phi;
00151
00152
00153 sample->xyz[0] -= params->hcf * vd->cos_ctheta;
00154 sample->xyz[1] -= params->hcf * vd->sin_ctheta;
00155 vd->i++;
00156
00157
00158 return 0;
00159 }
00160
00161 int velodyne_decode(velodyne_calib_t *v, const void *_data, int datalen,
00162 double *_theta0,
00163 double *ranges, double *intensities, double *thetas,
00164 double *phis, int *laserids, int *nsamples, int *badscans)
00165 {
00166 if (datalen != 1206) {
00167 printf("velodyne: bad len %i\n", datalen);
00168 return -1;
00169 }
00170
00171 int out_idx = 0;
00172 int laser_offset = 0;
00173
00174 uint8_t *data;
00175 for (data = (uint8_t*) _data;
00176 datalen >= 100;
00177 datalen-=100, data += 100) {
00178
00179 int magic = data[0] + (data[1]<<8);
00180
00181 if (magic == UPPER_MAGIC)
00182 laser_offset = 32;
00183 else if (magic == LOWER_MAGIC)
00184 laser_offset = 0;
00185 else {
00186 printf("Unknown velodyne magic %4x\n", magic);
00187 continue;
00188 }
00189
00190 double theta0 = 2*PI - (data[2] + (data[3]<<8)) * RADIANS_PER_LSB;
00191 *_theta0 = theta0;
00192
00193 int i;
00194 for (i = 0; i < 32; i++) {
00195 struct velodyne_laser_calib *params = &v->lasers[laser_offset + i];
00196
00197 ranges[out_idx] = (data[4 + i*3] + (data[5+i*3]<<8)) * METERS_PER_LSB;
00198 ranges[out_idx] *= (1.0 + params->range_scale_offset);
00199 ranges[out_idx] -= params->range_offset;
00200
00201
00202 if (ranges[out_idx] < 0.5) {
00203 badscans[laser_offset+i]++;
00204 continue;
00205 }
00206
00207 intensities[out_idx] = data[6 + i*3]/255.0;
00208 thetas[out_idx] = theta0 + params->rcf;
00209 phis[out_idx] = params->vcf;
00210 laserids[out_idx] = laser_offset + i;
00211 out_idx++;
00212 }
00213 }
00214
00215 *nsamples = out_idx;
00216
00217
00218 return 0;
00219 }
00220
00221 void velodyne_calib_dump(velodyne_calib_t *v)
00222 {
00223 printf("struct velodyne_laser_calib velodyne_NAME_ME_HERE[] = {\n");
00224 int i;
00225 for (i = 0; i < VELODYNE_NUM_LASERS; i++) {
00226 struct velodyne_laser_calib *params = &v->lasers[i];
00227 printf(" { %11.7f, %11.7f, %8.4f, %8.4f, %10.6f }, // laser %2d\n",
00228 params->rcf, params->vcf, params->hcf, params->range_offset, params->range_scale_offset, i);
00229 }
00230 printf("};\n\n");
00231 }
00232
00233
00234 static velodyne_calib_t *__v;
00235 static int laser_phi_compare(const void *_a, const void *_b)
00236 {
00237 int a = *((int*) _a);
00238 int b = *((int*) _b);
00239
00240 if (__v->lasers[a].vcf < __v->lasers[b].vcf)
00241 return -1;
00242 return 1;
00243 }
00244
00245
00246 int velodyne_calib_precompute(velodyne_calib_t *v)
00247 {
00248 assert (!__v);
00249
00250 __v = v;
00251
00252 int i;
00253 for (i = 0; i < VELODYNE_NUM_LASERS; i++)
00254 v->logical2physical[i] = i;
00255 qsort(v->logical2physical, VELODYNE_NUM_LASERS, sizeof(int),
00256 laser_phi_compare);
00257
00258 int logical;
00259 for (logical = 0; logical < VELODYNE_NUM_LASERS; logical++) {
00260 v->physical2logical[v->logical2physical[logical]] = logical;
00261 }
00262
00263 int physical;
00264 for (physical = 0; physical < VELODYNE_NUM_LASERS; physical++) {
00265 v->sincos[physical][0] = sin(v->lasers[physical].vcf);
00266 v->sincos[physical][1] = cos(v->lasers[physical].vcf);
00267 }
00268 __v = NULL;
00269
00270 return 0;
00271 }
00272
00273 velodyne_calib_t *velodyne_calib_create()
00274 {
00275 velodyne_calib_t *v = (velodyne_calib_t*) calloc(1, sizeof(velodyne_calib_t));
00276 memcpy(v->lasers, velodyne_uncalibrated, sizeof(struct velodyne_laser_calib) * VELODYNE_NUM_LASERS);
00277 velodyne_calib_precompute(v);
00278
00279 return v;
00280 }