driver.cc
Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2007 Austin Robot Technology, Patrick Beeson
00003  *  Copyright (C) 2009-2012 Austin Robot Technology, Jack O'Quin
00004  * 
00005  *  License: Modified BSD Software License Agreement
00006  *
00007  *  $Id$
00008  */
00009 
00015 #include <string>
00016 #include <cmath>
00017 
00018 #include <ros/ros.h>
00019 #include <tf/transform_listener.h>
00020 #include <velodyne_msgs/VelodyneScan.h>
00021 
00022 #include "driver.h"
00023 
00024 namespace velodyne_driver
00025 {
00026 
00027 VelodyneDriver::VelodyneDriver(ros::NodeHandle node,
00028                                ros::NodeHandle private_nh)
00029 {
00030   // use private node handle to get parameters
00031   private_nh.param("frame_id", config_.frame_id, std::string("velodyne"));
00032   std::string tf_prefix = tf::getPrefixParam(private_nh);
00033   ROS_DEBUG_STREAM("tf_prefix: " << tf_prefix);
00034   config_.frame_id = tf::resolve(tf_prefix, config_.frame_id);
00035 
00036   // get model name, validate string, determine packet rate
00037   private_nh.param("model", config_.model, std::string("64E"));
00038   double packet_rate;                   // packet frequency (Hz)
00039   std::string model_full_name;
00040   if ((config_.model == "64E_S2") || 
00041       (config_.model == "64E_S2.1"))    // generates 1333312 points per second
00042     {                                   // 1 packet holds 384 points
00043       packet_rate = 3472.17;            // 1333312 / 384
00044       model_full_name = std::string("HDL-") + config_.model;
00045     }
00046   else if (config_.model == "64E")
00047     {
00048       packet_rate = 2600.0;
00049       model_full_name = std::string("HDL-") + config_.model;
00050     }
00051   else if (config_.model == "32E")
00052     {
00053       packet_rate = 1808.0;
00054       model_full_name = std::string("HDL-") + config_.model;
00055     }
00056   else if (config_.model == "VLP16")
00057     {
00058       packet_rate = 781.25;             // 300000 / 384
00059       model_full_name = "VLP-16";
00060     }
00061   else
00062     {
00063       ROS_ERROR_STREAM("unknown Velodyne LIDAR model: " << config_.model);
00064       packet_rate = 2600.0;
00065     }
00066   std::string deviceName(std::string("Velodyne ") + model_full_name);
00067 
00068   private_nh.param("rpm", config_.rpm, 600.0);
00069   ROS_INFO_STREAM(deviceName << " rotating at " << config_.rpm << " RPM");
00070   double frequency = (config_.rpm / 60.0);     // expected Hz rate
00071 
00072   // default number of packets for each scan is a single revolution
00073   // (fractions rounded up)
00074   config_.npackets = (int) ceil(packet_rate / frequency);
00075   private_nh.getParam("npackets", config_.npackets);
00076   ROS_INFO_STREAM("publishing " << config_.npackets << " packets per scan");
00077 
00078   std::string dump_file;
00079   private_nh.param("pcap", dump_file, std::string(""));
00080 
00081   // initialize diagnostics
00082   diagnostics_.setHardwareID(deviceName);
00083   const double diag_freq = packet_rate/config_.npackets;
00084   diag_max_freq_ = diag_freq;
00085   diag_min_freq_ = diag_freq;
00086   ROS_INFO("expected frequency: %.3f (Hz)", diag_freq);
00087 
00088   using namespace diagnostic_updater;
00089   diag_topic_.reset(new TopicDiagnostic("velodyne_packets", diagnostics_,
00090                                         FrequencyStatusParam(&diag_min_freq_,
00091                                                              &diag_max_freq_,
00092                                                              0.1, 10),
00093                                         TimeStampStatusParam()));
00094 
00095   // open Velodyne input device or file
00096   if (dump_file != "")
00097     {
00098       input_.reset(new velodyne_driver::InputPCAP(private_nh,
00099                                                   packet_rate,
00100                                                   dump_file));
00101     }
00102   else
00103     {
00104       input_.reset(new velodyne_driver::InputSocket(private_nh));
00105     }
00106 
00107   // raw data output topic
00108   output_ = node.advertise<velodyne_msgs::VelodyneScan>("velodyne_packets", 10);
00109 }
00110 
00115 bool VelodyneDriver::poll(void)
00116 {
00117   // Allocate a new shared pointer for zero-copy sharing with other nodelets.
00118   velodyne_msgs::VelodyneScanPtr scan(new velodyne_msgs::VelodyneScan);
00119   scan->packets.resize(config_.npackets);
00120 
00121   // Since the velodyne delivers data at a very high rate, keep
00122   // reading and publishing scans as fast as possible.
00123   for (int i = 0; i < config_.npackets; ++i)
00124     {
00125       while (true)
00126         {
00127           // keep reading until full packet received
00128           int rc = input_->getPacket(&scan->packets[i]);
00129           if (rc == 0) break;       // got a full packet?
00130           if (rc < 0) return false; // end of file reached?
00131         }
00132     }
00133 
00134   // publish message using time of last packet read
00135   ROS_DEBUG("Publishing a full Velodyne scan.");
00136   scan->header.stamp = ros::Time(scan->packets[config_.npackets - 1].stamp);
00137   scan->header.frame_id = config_.frame_id;
00138   output_.publish(scan);
00139 
00140   // notify diagnostics that a message has been published, updating
00141   // its status
00142   diag_topic_->tick(scan->header.stamp);
00143   diagnostics_.update();
00144 
00145   return true;
00146 }
00147 
00148 } // namespace velodyne_driver


velodyne_driver
Author(s): Jack O'Quin, Patrick Beeson, Michael Quinlan, Yaxin Liu
autogenerated on Thu Aug 27 2015 15:37:01