00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00036 #ifndef __VELODYNE_DATA_H
00037 #define __VELODYNE_DATA_H
00038
00039 #include <errno.h>
00040 #include <stdint.h>
00041 #include <string>
00042
00043 #include <ros/ros.h>
00044 #include <velodyne_common/RawScan.h>
00045 #include <boost/format.hpp>
00046
00047 namespace velodyne
00048 {
00049
00053 static const int SIZE_BLOCK = 100;
00054 static const int RAW_SCAN_SIZE = 3;
00055 static const int SCANS_PER_BLOCK = 32;
00056 static const int BLOCK_DATA_SIZE = (SCANS_PER_BLOCK * RAW_SCAN_SIZE);
00057
00058 static const float ROTATION_RESOLUTION = 0.01f;
00059 static const float ROTATION_MAX_UNITS = 36000;
00063 static const float DISTANCE_MAX = 130.0f;
00064 static const float DISTANCE_RESOLUTION = 0.002f;
00065 static const float DISTANCE_MAX_UNITS = (DISTANCE_MAX
00066 / DISTANCE_RESOLUTION + 1.0);
00067 static const uint16_t UPPER_BANK = 0xeeff;
00068 static const uint16_t LOWER_BANK = 0xddff;
00069
00077 typedef struct raw_block
00078 {
00079 uint16_t header;
00080 uint16_t rotation;
00081 uint8_t data[BLOCK_DATA_SIZE];
00082 } raw_block_t;
00083
00089 union two_bytes
00090 {
00091 uint16_t uint;
00092 uint8_t bytes[2];
00093 };
00094
00095 static const int PACKET_SIZE = 1206;
00096 static const int BLOCKS_PER_PACKET = 12;
00097 static const int PACKET_STATUS_SIZE = 4;
00098 static const int SCANS_PER_PACKET = (SCANS_PER_BLOCK * BLOCKS_PER_PACKET);
00099 static const int PACKETS_PER_REV = 260;
00100 static const int SCANS_PER_REV = (SCANS_PER_PACKET * PACKETS_PER_REV);
00101
00114 typedef struct raw_packet
00115 {
00116 raw_block_t blocks[BLOCKS_PER_PACKET];
00117 uint16_t revolution;
00118 uint8_t status[PACKET_STATUS_SIZE];
00119 } raw_packet_t;
00120
00122 struct correction_angles
00123 {
00124 float rotational;
00125 float vertical;
00126 float offset1, offset2, offset3;
00127 int enabled;
00128 };
00129
00138 typedef void (*raw_callback_t)(const raw_packet_t *raw, size_t npackets);
00139
00141 class Data
00142 {
00143 public:
00144 Data(std::string ofile="",
00145 std::string anglesFile="")
00146 {
00147 ofile_ = ofile;
00148 anglesFile_ = anglesFile;
00149
00150 ofp_ = NULL;
00151 rawCB_ = NULL;
00152 memset(&upper_, 0, sizeof(upper_));
00153 memset(&lower_, 0, sizeof(lower_));
00154 }
00155
00156 virtual ~Data() {}
00157
00158 #if !ROS_VERSION_MINIMUM(1, 3, 0)
00159
00169 virtual const roslib::Header *getMsgHeader(void) const
00170 {
00171 if (rawScan_)
00172 return &rawScan_->header;
00173 else
00174 return NULL;
00175 }
00176 #endif
00177
00183 void getMsgHeaderFields(ros::Time &stamp, std::string &frame_id) const
00184 {
00185 if (rawScan_)
00186 {
00187 stamp = rawScan_->header.stamp;
00188 frame_id = rawScan_->header.frame_id;
00189 }
00190 }
00191
00199 virtual int getParams(void);
00200
00206 virtual int print(void)
00207 {
00208 if (uninitialized_)
00209 return EBADF;
00210 return 0;
00211 }
00212
00234 void processRawScan(const velodyne_common::RawScan::ConstPtr &raw_scan);
00235
00241 virtual void processRaw(const raw_packet_t *raw, size_t npackets);
00242
00254 virtual int setup(void);
00255
00257 virtual void shutdown(void)
00258 {
00259 ros::shutdown();
00260 uninitialized_ = true;
00261 }
00262
00264 void subscribeRaw(raw_callback_t rawCB)
00265 {
00266 ROS_INFO("raw callback defined");
00267 rawCB_ = rawCB;
00268 }
00269
00270 protected:
00271
00273 std::string ofile_;
00274 std::string anglesFile_;
00275
00277 FILE *ofp_;
00278 raw_callback_t rawCB_;
00279 bool uninitialized_;
00280
00282 velodyne_common::RawScan::ConstPtr rawScan_;
00283
00288 correction_angles lower_[SCANS_PER_BLOCK];
00289 correction_angles upper_[SCANS_PER_BLOCK];
00290 };
00291
00292
00301 typedef struct laserscan
00302 {
00303 float range;
00304 float heading;
00305 float pitch;
00306 uint16_t revolution;
00307 uint8_t laser_number;
00308 uint8_t intensity;
00309 } laserscan_t;
00310
00319 typedef void (*scans_callback_t)(const std::vector<laserscan_t> &scan);
00320 typedef boost::function<void(const std::vector<laserscan_t> &)> scanCallback;
00321
00323 class DataScans: public Data
00324 {
00325 public:
00326 DataScans(std::string ofile="",
00327 std::string anglesFile=""):
00328 Data(ofile, anglesFile)
00329 {
00330
00331
00332 scans_.resize(SCANS_PER_REV);
00333 scansCB_ = NULL;
00334 }
00335
00336 virtual int print(void);
00337 virtual void processRaw(const raw_packet_t *raw, size_t npackets);
00338
00347 ros::Subscriber subscribe(ros::NodeHandle node,
00348 const std::string &topic,
00349 uint32_t queue_size,
00350 const scanCallback callback,
00351 const ros::TransportHints &transport_hints
00352 = ros::TransportHints())
00353 {
00354 ROS_INFO("generic scan callback defined");
00355 cb_ = callback;
00356 return node.subscribe(topic, queue_size,
00357 &velodyne::Data::processRawScan,
00358 (velodyne::Data *) this,
00359 transport_hints);
00360 }
00361
00366 virtual void subscribeScans(scans_callback_t scansCB)
00367 {
00368 ROS_INFO("scans callback defined");
00369 scansCB_ = scansCB;
00370 }
00371
00372 protected:
00373 void packet2scans(const raw_packet_t *raw, laserscan_t *scans);
00374
00375
00376 std::vector<laserscan_t> scans_;
00377
00378 private:
00379 scans_callback_t scansCB_;
00380 scanCallback cb_;
00381 };
00382
00383
00388 typedef struct laserscan_xyz
00389 {
00390 float x, y, z;
00391 float heading;
00392 uint16_t revolution;
00393 uint8_t laser_number;
00394 uint8_t intensity;
00395 } laserscan_xyz_t;
00396
00406 typedef void (*xyz_callback_t)(const std::vector<laserscan_xyz_t> &scan);
00407 typedef boost::function<void(const std::vector<laserscan_xyz_t> &)> xyzCallback;
00408
00410 class DataXYZ: public DataScans
00411 {
00412 public:
00413 DataXYZ(std::string ofile="",
00414 std::string anglesFile=""):
00415 DataScans(ofile, anglesFile)
00416 {
00417
00418
00419 xyzScans_.resize(SCANS_PER_REV);
00420 xyzCB_ = NULL;
00421 }
00422
00423 virtual int print(void);
00424 virtual void processRaw(const raw_packet_t *raw, size_t npackets);
00425
00434 ros::Subscriber subscribe(ros::NodeHandle node,
00435 const std::string &topic,
00436 uint32_t queue_size,
00437 const xyzCallback callback,
00438 const ros::TransportHints &transport_hints
00439 = ros::TransportHints())
00440 {
00441 ROS_INFO("XYZ callback subscribed");
00442 cb_ = callback;
00443 return node.subscribe(topic, queue_size,
00444 &velodyne::Data::processRawScan,
00445 (velodyne::Data *) this,
00446 transport_hints);
00447 }
00448
00453 virtual void subscribeXYZ(xyz_callback_t xyzCB)
00454 {
00455 ROS_INFO("XYZ callback defined");
00456 xyzCB_ = xyzCB;
00457 }
00458
00459 protected:
00460 void scan2xyz(const laserscan_t *scan, laserscan_xyz_t *point);
00461
00462
00463 std::vector<laserscan_xyz_t> xyzScans_;
00464
00465 private:
00466 xyz_callback_t xyzCB_;
00467 xyzCallback cb_;
00468 };
00469
00470
00471 }
00472
00473 #endif // __VELODYNE_DATA_H