00001
00002
00003
00004
00005
00006
00007
00008
00009
00024 #include <fstream>
00025
00026 #include <ros/ros.h>
00027 #include <ros/package.h>
00028 #include <angles/angles.h>
00029
00030 #include <velodyne/data.h>
00031
00032 namespace velodyne
00033 {
00035
00036
00037
00039
00048 int Data::getParams()
00049 {
00050
00051 ros::NodeHandle private_nh("~/data");
00052
00053 private_nh.getParam("output", ofile_);
00054
00055
00056 if (!private_nh.getParam("angles", anglesFile_))
00057 {
00058
00059 std::string pkgPath = ros::package::getPath("velodyne_common");
00060 anglesFile_ = pkgPath + "/etc/angles.config";
00061 }
00062
00063 ROS_INFO_STREAM("correction angles: " << anglesFile_);
00064
00065 return 0;
00066 }
00067
00069 void Data::processRawScan(const velodyne_common::RawScan::ConstPtr &raw_scan)
00070 {
00071 rawScan_ = raw_scan;
00072 velodyne::raw_packet_t *raw =
00073 (velodyne::raw_packet_t *) &raw_scan->data[0];
00074 size_t npackets = (raw_scan->data.size()
00075 / velodyne_common::RawScan::PACKET_SIZE);
00076 processRaw(raw, npackets);
00077 }
00078
00079
00081 void Data::processRaw(const velodyne::raw_packet_t *raw, size_t npackets)
00082 {
00083 if (rawCB_)
00084 (*rawCB_)(raw, npackets);
00085 }
00086
00088 int Data::setup(void)
00089 {
00090
00091 ofp_ = NULL;
00092 if (ofile_ != "")
00093 {
00094 if (ofile_ == "-")
00095 {
00096 ROS_INFO("output to stdout");
00097 ofp_ = stdout;
00098 }
00099 else
00100 {
00101 ROS_INFO("output file: %s", ofile_.c_str());
00102 ofp_ = fopen(ofile_.c_str(), "w");
00103 if (ofp_ == NULL)
00104 {
00105 int rc = errno;
00106 ROS_ERROR("failed to open \"%s\" (%s)",
00107 ofile_.c_str(), strerror(rc));
00108 return rc;
00109 }
00110 }
00111 }
00112
00113
00114 std::ifstream config(anglesFile_.c_str());
00115 if (!config)
00116 {
00117 std::cerr << "Failure opening Velodyne angles correction file: "
00118 << anglesFile_ << std::endl;
00119 return -1;
00120 }
00121
00122 int index = 0;
00123 float rotational = 0;
00124 float vertical = 0;
00125 int enabled = 0;
00126 float offset1=0;
00127 float offset2=0;
00128 float offset3=0;
00129
00130 correction_angles * angles = 0;
00131
00132 char buffer[256];
00133 while(config.getline(buffer, sizeof(buffer)))
00134 {
00135 if (buffer[0] == '#') continue;
00136 else if (strcmp(buffer, "upper") == 0)
00137 continue;
00138 else if(strcmp(buffer, "lower") == 0)
00139 continue;
00140 else if(sscanf(buffer,"%d %f %f %f %f %f %d", &index, &rotational,
00141 &vertical, &offset1, &offset2, &offset3, &enabled) == 7)
00142 {
00143 int ind=index;
00144 if (index < 32)
00145 angles=&lower_[0];
00146 else
00147 {
00148 angles=&upper_[0];
00149 ind=index-32;
00150 }
00151 angles[ind].rotational = angles::from_degrees(rotational);
00152 angles[ind].vertical = angles::from_degrees(vertical);
00153 angles[ind].offset1 = offset1;
00154 angles[ind].offset2 = offset2;
00155 angles[ind].offset3 = offset3;
00156 angles[ind].enabled = enabled;
00157
00158
00159 #ifdef DEBUG_ANGLES
00160 ROS_DEBUG(stderr, "%d %.2f %.6f %.f %.f %.2f %d",
00161 index, rotational, vertical,
00162 angles[ind].offset1,
00163 angles[ind].offset2,
00164 angles[ind].offset3,
00165 angles[ind].enabled);
00166 #endif
00167 }
00168 }
00169
00170 config.close();
00171
00172 uninitialized_ = false;
00173
00174 return 0;
00175 }
00176
00178
00179
00180
00182
00183
00185 void DataScans::packet2scans(const raw_packet_t *raw, laserscan_t *scans)
00186 {
00187 int index = 0;
00188 uint16_t revolution = raw->revolution;
00189
00190 for (int i = 0; i < BLOCKS_PER_PACKET; i++)
00191 {
00192 int bank_origin = 32;
00193 correction_angles *corrections = upper_;
00194 if (raw->blocks[i].header == LOWER_BANK)
00195 {
00196 bank_origin = 0;
00197 corrections = lower_;
00198 }
00199
00200 float rotation = angles::from_degrees(raw->blocks[i].rotation
00201 * ROTATION_RESOLUTION);
00202
00203 for (int j = 0, k = 0; j < SCANS_PER_BLOCK; j++, k += RAW_SCAN_SIZE)
00204 {
00205 scans[index].laser_number = j + bank_origin;
00206
00207
00208
00209
00210
00212 scans[index].heading =
00213 angles::normalize_angle(-(rotation - corrections[j].rotational));
00214 scans[index].pitch = corrections[j].vertical;
00215
00216 union two_bytes tmp;
00217 tmp.bytes[0] = raw->blocks[i].data[k];
00218 tmp.bytes[1] = raw->blocks[i].data[k+1];
00219
00220
00221 scans[index].range = tmp.uint * DISTANCE_RESOLUTION;
00222 scans[index].range =
00223 (corrections[j].offset1 * scans[index].range * scans[index].range
00224 + corrections[j].offset2 * scans[index].range
00225 + corrections[j].offset3);
00226
00227 scans[index].intensity = raw->blocks[i].data[k+2];
00228 scans[index].revolution = revolution;
00229
00230 ++index;
00231 }
00232 }
00233
00234 ROS_ASSERT(index == SCANS_PER_PACKET);
00235 }
00236
00238 void DataScans::processRaw(const velodyne::raw_packet_t *raw, size_t npackets)
00239 {
00240 if (uninitialized_)
00241 return;
00242
00243
00244 Data::processRaw(raw, npackets);
00245
00246
00247 scans_.resize(npackets * SCANS_PER_PACKET);
00248 for (unsigned i = 0; i < (unsigned) npackets; ++i)
00249 {
00250 packet2scans(&raw[i], &scans_[i * SCANS_PER_PACKET]);
00251 }
00252
00253 if (!ros::ok())
00254 return;
00255
00256
00257 if (scansCB_)
00258 (*scansCB_)(scans_);
00259 else if (cb_)
00260 cb_(scans_);
00261 }
00262
00272 int DataScans::print(void)
00273 {
00274 if (uninitialized_)
00275 return EBADF;
00276
00277 if (ofp_ == NULL)
00278 return 0;
00279
00280 for (unsigned i = 0; i < scans_.size(); i++)
00281 {
00282 int rc = fprintf(ofp_, "%+08.6f %+08.6f %+011.6f %03u %02u %05u\n",
00283 scans_[i].heading,
00284 scans_[i].pitch,
00285 scans_[i].range,
00286 scans_[i].intensity,
00287 scans_[i].laser_number,
00288 scans_[i].revolution);
00289 if (rc < 0)
00290 return errno;
00291
00292
00293
00294 if (!ros::ok())
00295 return EINTR;
00296 }
00297
00298 return 0;
00299 }
00300
00301
00303
00304
00305
00307
00308 inline void DataXYZ::scan2xyz(const laserscan_t *scan,
00309 laserscan_xyz_t *point)
00310 {
00311 float xy_projection = scan->range * cosf(scan->pitch);
00312 point->laser_number = scan->laser_number;
00313 point->heading = scan->heading;
00314 point->revolution = scan->revolution;
00315 point->x = xy_projection * cosf(scan->heading);
00316 point->y = xy_projection * sinf(scan->heading);
00317 point->z = scan->range * sinf(scan->pitch);
00318 point->intensity = scan->intensity;
00319 }
00320
00322 void DataXYZ::processRaw(const velodyne::raw_packet_t *raw, size_t npackets)
00323 {
00324 if (uninitialized_)
00325 return;
00326
00327
00328 DataScans::processRaw(raw, npackets);
00329
00330
00331 xyzScans_.resize(scans_.size());
00332 for (unsigned i = 0; i < xyzScans_.size(); i++)
00333 {
00334 scan2xyz(&scans_[i], &xyzScans_[i]);
00335 }
00336
00337 if (!ros::ok())
00338 return;
00339
00340
00341 if (xyzCB_)
00342 (*xyzCB_)(xyzScans_);
00343 else if (cb_)
00344 cb_(xyzScans_);
00345 }
00346
00347
00354 int DataXYZ::print(void)
00355 {
00356 if (uninitialized_)
00357 return EBADF;
00358
00359 if (ofp_ == NULL)
00360 return 0;
00361
00362 for (unsigned i = 0; i < xyzScans_.size(); i++)
00363 {
00364
00365
00366 int rc = fprintf(ofp_, "%02u %+08.6f %+011.6f %+011.6f %+011.6f %03u\n",
00367 xyzScans_[i].laser_number,
00368 xyzScans_[i].heading,
00369 xyzScans_[i].x, xyzScans_[i].y, xyzScans_[i].z,
00370 xyzScans_[i].intensity);
00371 if (rc < 0)
00372 return errno;
00373
00374
00375
00376 if (!ros::ok())
00377 return EINTR;
00378 }
00379
00380 return 0;
00381 }
00382
00383 }