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 }