pcd_grabber.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2012, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00038 #include <pcl/pcl_config.h>
00039 #include <pcl/io/pcd_grabber.h>
00040 #include <pcl/point_cloud.h>
00041 #include <pcl/point_types.h>
00042 #include <pcl/io/pcd_io.h>
00043 #include <pcl/io/tar.h>
00044 
00045 #ifdef _WIN32
00046 # include <io.h>
00047 # include <windows.h>
00048 # define pcl_open                    _open
00049 # define pcl_close(fd)               _close(fd)
00050 # define pcl_lseek(fd,offset,origin) _lseek(fd,offset,origin)
00051 #else
00052 # include <sys/mman.h>
00053 # define pcl_open                    open
00054 # define pcl_close(fd)               close(fd)
00055 # define pcl_lseek(fd,offset,origin) lseek(fd,offset,origin)
00056 #endif
00057 
00060 struct pcl::PCDGrabberBase::PCDGrabberImpl
00061 {
00062   PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::string& pcd_path, float frames_per_second, bool repeat);
00063   PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat);
00064   void trigger ();
00065   void readAhead ();
00066   
00067   // TAR reading I/O
00068   int openTARFile (const std::string &file_name);
00069   void closeTARFile ();
00070   bool readTARHeader ();
00071 
00072   pcl::PCDGrabberBase& grabber_;
00073   float frames_per_second_;
00074   bool repeat_;
00075   bool running_;
00076   std::vector<std::string> pcd_files_;
00077   std::vector<std::string>::iterator pcd_iterator_;
00078   TimeTrigger time_trigger_;
00079 
00080   sensor_msgs::PointCloud2 next_cloud_;
00081   Eigen::Vector4f origin_;
00082   Eigen::Quaternionf orientation_;
00083   bool valid_;
00084 
00085   // TAR reading I/O
00086   int tar_fd_;
00087   int tar_offset_;
00088   std::string tar_file_;
00089   pcl::io::TARHeader tar_header_;
00090 };
00091 
00093 pcl::PCDGrabberBase::PCDGrabberImpl::PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::string& pcd_path, float frames_per_second, bool repeat)
00094   : grabber_ (grabber)
00095   , frames_per_second_ (frames_per_second)
00096   , repeat_ (repeat)
00097   , running_ (false)
00098   , pcd_files_ ()
00099   , pcd_iterator_ ()
00100   , time_trigger_ (1.0 / static_cast<double> (std::max (frames_per_second, 0.001f)), boost::bind (&PCDGrabberImpl::trigger, this))
00101   , next_cloud_ ()
00102   , origin_ ()
00103   , orientation_ ()
00104   , valid_ (false)
00105   , tar_fd_ (-1)
00106   , tar_offset_ (0)
00107   , tar_file_ ()
00108   , tar_header_ ()
00109 {
00110   pcd_files_.push_back (pcd_path);
00111   pcd_iterator_ = pcd_files_.begin ();
00112 }
00113 
00115 pcl::PCDGrabberBase::PCDGrabberImpl::PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat)
00116   : grabber_ (grabber)
00117   , frames_per_second_ (frames_per_second)
00118   , repeat_ (repeat)
00119   , running_ (false)
00120   , pcd_files_ ()
00121   , pcd_iterator_ ()
00122   , time_trigger_ (1.0 / static_cast<double> (std::max (frames_per_second, 0.001f)), boost::bind (&PCDGrabberImpl::trigger, this))
00123   , next_cloud_ ()
00124   , origin_ ()
00125   , orientation_ ()
00126   , valid_ (false)
00127   , tar_fd_ (-1)
00128   , tar_offset_ (0)
00129   , tar_file_ ()
00130   , tar_header_ ()
00131 {
00132   pcd_files_ = pcd_files;
00133   pcd_iterator_ = pcd_files_.begin ();
00134 }
00135 
00137 void 
00138 pcl::PCDGrabberBase::PCDGrabberImpl::readAhead ()
00139 {
00140   PCDReader reader;
00141   int pcd_version;
00142 
00143   // Check if we're still reading files from a TAR file
00144   if (tar_fd_ != -1)
00145   {
00146     if (!readTARHeader ())
00147       closeTARFile ();
00148     valid_ = (reader.read (tar_file_, next_cloud_, origin_, orientation_, pcd_version, tar_offset_) == 0);
00149     if (!valid_)
00150       closeTARFile ();
00151     else
00152     {
00153       tar_offset_ += (tar_header_.getFileSize ()) + (512 - tar_header_.getFileSize () % 512);
00154       int result = static_cast<int> (pcl_lseek (tar_fd_, tar_offset_, SEEK_SET));
00155       if (result < 0)
00156         closeTARFile ();
00157     }
00158   }
00159   // We're not still reading from a TAR file, so check if there are other PCD/TAR files in the list
00160   else
00161   {
00162     if (pcd_iterator_ != pcd_files_.end ())
00163     {
00164       // Try to read in the file as a PCD first
00165       valid_ = (reader.read (*pcd_iterator_, next_cloud_, origin_, orientation_, pcd_version) == 0);
00166 
00167       // Has an error occured? Check if we can interpret the file as a TAR file first before going onto the next
00168       if (!valid_)
00169       {
00170         if (openTARFile (*pcd_iterator_) >= 0)
00171         {
00172           if (!readTARHeader ())
00173             closeTARFile ();
00174           tar_file_ = *pcd_iterator_;
00175           valid_ = (reader.read (tar_file_, next_cloud_, origin_, orientation_, pcd_version, tar_offset_) == 0);
00176           if (!valid_)
00177             closeTARFile ();
00178           else
00179           {
00180             tar_offset_ += (tar_header_.getFileSize ()) + (512 - tar_header_.getFileSize () % 512);
00181             int result = static_cast<int> (pcl_lseek (tar_fd_, tar_offset_, SEEK_SET));
00182             if (result < 0)
00183               closeTARFile ();
00184           }
00185         }
00186       }
00187 
00188       if (++pcd_iterator_ == pcd_files_.end () && repeat_)
00189         pcd_iterator_ = pcd_files_.begin ();
00190     }
00191     else
00192       valid_ = false;
00193   }
00194 }
00195 
00197 bool
00198 pcl::PCDGrabberBase::PCDGrabberImpl::readTARHeader ()
00199 {
00200   // Read in the header
00201   int result = static_cast<int> (::read (tar_fd_, reinterpret_cast<char*> (&tar_header_), 512));
00202   if (result == -1)
00203   {
00204     closeTARFile ();
00205     return (false);
00206   }
00207 
00208   // We only support regular files for now. 
00209   // Addional file types in TAR include: hard links, symbolic links, device/special files, block devices, 
00210   // directories, and named pipes.
00211   if (tar_header_.file_type[0] != '0' && tar_header_.file_type[0] != '\0')
00212   {
00213     closeTARFile ();
00214     return (false);
00215   }
00216 
00217   // We only support USTAR version 0 files for now
00218   if (std::string (tar_header_.ustar).substr (0, 5) != "ustar")
00219   {
00220     closeTARFile ();
00221     return (false);
00222   }
00223 
00224   if (tar_header_.getFileSize () == 0)
00225   {
00226     closeTARFile ();
00227     return (false);
00228   }
00229 
00230   tar_offset_ += 512;
00231 
00232   return (true);
00233 }
00234 
00236 void
00237 pcl::PCDGrabberBase::PCDGrabberImpl::closeTARFile ()
00238 {
00239   pcl_close (tar_fd_);
00240   tar_fd_ = -1;
00241   tar_offset_ = 0;
00242   memset (&tar_header_.file_name[0], 0, 512);
00243 }
00244 
00246 int
00247 pcl::PCDGrabberBase::PCDGrabberImpl::openTARFile (const std::string &file_name)
00248 {
00249   tar_fd_ = pcl_open (file_name.c_str (), O_RDONLY);
00250   if (tar_fd_ == -1)
00251     return (-1);
00252 
00253   return (0);
00254 }
00255 
00257 void 
00258 pcl::PCDGrabberBase::PCDGrabberImpl::trigger ()
00259 {
00260   if (valid_)
00261     grabber_.publish (next_cloud_,origin_,orientation_);
00262 
00263   // use remaining time, if there is time left!
00264   readAhead ();
00265 }
00266 
00269 pcl::PCDGrabberBase::PCDGrabberBase (const std::string& pcd_path, float frames_per_second, bool repeat)
00270 : impl_ (new PCDGrabberImpl (*this, pcd_path, frames_per_second, repeat))
00271 {
00272 }
00273 
00275 pcl::PCDGrabberBase::PCDGrabberBase (const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat)
00276 : impl_ (new PCDGrabberImpl (*this, pcd_files, frames_per_second, repeat))
00277 {
00278 }
00279 
00281 pcl::PCDGrabberBase::~PCDGrabberBase () throw ()
00282 {
00283   stop ();
00284   delete impl_;
00285 }
00286 
00288 void 
00289 pcl::PCDGrabberBase::start ()
00290 {
00291   if (impl_->frames_per_second_ > 0)
00292   {
00293     impl_->running_ = true;
00294     impl_->time_trigger_.start ();
00295   }
00296   else // manual trigger
00297     impl_->trigger ();
00298 }
00299 
00301 void 
00302 pcl::PCDGrabberBase::stop ()
00303 {
00304   if (impl_->frames_per_second_ > 0)
00305   {
00306     impl_->time_trigger_.stop ();
00307     impl_->running_ = false;
00308   }
00309 }
00310 
00312 void
00313 pcl::PCDGrabberBase::trigger ()
00314 {
00315   if (impl_->frames_per_second_ > 0)
00316     return;
00317   impl_->trigger ();
00318 }
00319 
00321 bool 
00322 pcl::PCDGrabberBase::isRunning () const
00323 {
00324   return (impl_->running_);
00325 }
00326 
00328 std::string 
00329 pcl::PCDGrabberBase::getName () const
00330 {
00331   return ("PCDGrabber");
00332 }
00333 
00335 void 
00336 pcl::PCDGrabberBase::rewind ()
00337 {
00338   impl_->pcd_iterator_ = impl_->pcd_files_.begin ();
00339 }
00340 
00342 float 
00343 pcl::PCDGrabberBase::getFramesPerSecond () const
00344 {
00345   return (impl_->frames_per_second_);
00346 }
00347 
00349 bool 
00350 pcl::PCDGrabberBase::isRepeatOn () const
00351 {
00352   return (impl_->repeat_);
00353 }
00354 


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:16:23