robot_eye_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) 2012-, Open Perception, 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 the copyright holder(s) 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/io/robot_eye_grabber.h>
00039 #include <pcl/console/print.h>
00040 
00042 pcl::RobotEyeGrabber::RobotEyeGrabber ()
00043   : terminate_thread_ (false)
00044   , signal_point_cloud_size_ (1000)
00045   , data_port_ (443)
00046   , sensor_address_ (boost::asio::ip::address_v4::any ())
00047 {
00048   point_cloud_signal_ = createSignal<sig_cb_robot_eye_point_cloud_xyzi> ();
00049   resetPointCloud ();
00050 }
00051 
00053 pcl::RobotEyeGrabber::RobotEyeGrabber (const boost::asio::ip::address& ipAddress, unsigned short port)
00054   : terminate_thread_ (false)
00055   , signal_point_cloud_size_ (1000)
00056   , data_port_ (port)
00057   , sensor_address_ (ipAddress)
00058 {
00059   point_cloud_signal_ = createSignal<sig_cb_robot_eye_point_cloud_xyzi> ();
00060   resetPointCloud ();
00061 }
00062 
00064 pcl::RobotEyeGrabber::~RobotEyeGrabber () throw ()
00065 {
00066   stop ();
00067   disconnect_all_slots<sig_cb_robot_eye_point_cloud_xyzi> ();
00068 }
00069 
00071 std::string
00072 pcl::RobotEyeGrabber::getName () const
00073 {
00074   return (std::string ("Ocular Robotics RobotEye Grabber"));
00075 }
00076 
00078 float
00079 pcl::RobotEyeGrabber::getFramesPerSecond () const
00080 {
00081   return (0.0f);
00082 }
00083 
00085 bool
00086 pcl::RobotEyeGrabber::isRunning () const
00087 {
00088   return (socket_thread_ != NULL);
00089 }
00090 
00092 unsigned short
00093 pcl::RobotEyeGrabber::getDataPort () const
00094 {
00095   return (data_port_);
00096 }
00097 
00099 void
00100 pcl::RobotEyeGrabber::setDataPort (const unsigned short port)
00101 {
00102   data_port_ = port;
00103 }
00104 
00106 const boost::asio::ip::address&
00107 pcl::RobotEyeGrabber::getSensorAddress () const
00108 {
00109   return (sensor_address_);
00110 }
00111 
00113 void
00114 pcl::RobotEyeGrabber::setSensorAddress (const boost::asio::ip::address& ipAddress)
00115 {
00116   sensor_address_ = ipAddress;
00117 }
00118 
00120 std::size_t
00121 pcl::RobotEyeGrabber::getSignalPointCloudSize () const
00122 {
00123   return (signal_point_cloud_size_);
00124 }
00125 
00127 void
00128 pcl::RobotEyeGrabber::setSignalPointCloudSize (std::size_t numberOfPoints)
00129 {
00130   signal_point_cloud_size_ = numberOfPoints;
00131 }
00132 
00134 boost::shared_ptr<pcl::PointCloud<pcl::PointXYZI> >
00135 pcl::RobotEyeGrabber::getPointCloud () const
00136 {
00137   return point_cloud_xyzi_;
00138 }
00139 
00141 void
00142 pcl::RobotEyeGrabber::resetPointCloud ()
00143 {
00144   point_cloud_xyzi_.reset (new pcl::PointCloud<pcl::PointXYZI>);
00145   point_cloud_xyzi_->is_dense = true;
00146 }
00147 
00149 void
00150 pcl::RobotEyeGrabber::consumerThreadLoop ()
00151 {
00152   while (true)
00153   {
00154     boost::shared_array<unsigned char> data;
00155     if (!packet_queue_.dequeue (data))
00156       return;
00157 
00158     convertPacketData (data.get(), 464);
00159   }
00160 }
00161 
00163 void
00164 pcl::RobotEyeGrabber::convertPacketData (unsigned char *dataPacket, size_t length)
00165 {
00166   const size_t bytesPerPoint = 8;
00167   const size_t totalPoints = length / bytesPerPoint;
00168 
00169   for (int i = 0; i < totalPoints; ++i)
00170   {
00171     PointXYZI xyzi;
00172     computeXYZI (xyzi, dataPacket + i*bytesPerPoint);
00173 
00174     if (pcl::isFinite(xyzi))
00175     {
00176       point_cloud_xyzi_->push_back (xyzi);
00177     }
00178   }
00179 
00180 
00181   if (point_cloud_xyzi_->size () > signal_point_cloud_size_)
00182   {
00183     if (point_cloud_signal_->num_slots () > 0)
00184       point_cloud_signal_->operator() (point_cloud_xyzi_);
00185 
00186     resetPointCloud ();
00187   }
00188 }
00189 
00191 void
00192 pcl::RobotEyeGrabber::computeXYZI (pcl::PointXYZI& point, unsigned char* pointData)
00193 {
00194   uint16_t buffer = 0;
00195   double az = 0.0;
00196   double el = 0.0;
00197   double range = 0.0;
00198   uint16_t intensity = 0;
00199 
00200   buffer = 0x00;
00201   buffer = pointData[0] << 8;
00202   buffer |= pointData[1]; // First 2-byte read will be Azimuth
00203   az = (buffer / 100.0);
00204 
00205   buffer = 0x00;
00206   buffer =  pointData[2] << 8;
00207   buffer |= pointData[3]; // Second 2-byte read will be Elevation
00208   el = (signed short int)buffer / 100.0;
00209 
00210   buffer = 0x00;
00211   buffer =  pointData[4] << 8;
00212   buffer |= pointData[5]; // Third 2-byte read will be Range
00213   range = (signed short int)buffer / 100.0;
00214 
00215   buffer = 0x00;
00216   buffer =  pointData[6] << 8;
00217   buffer |= pointData[7]; // Fourth 2-byte read will be Intensity
00218   intensity = buffer;
00219 
00220   point.x = range * std::cos (el * M_PI/180) * std::sin (az * M_PI/180);
00221   point.y = range * std::cos (el * M_PI/180) * std::cos (az * M_PI/180);
00222   point.z = range * std::sin (el * M_PI/180);
00223   point.intensity = intensity;
00224 }
00225 
00227 void
00228 pcl::RobotEyeGrabber::socketThreadLoop()
00229 {
00230   asyncSocketReceive();
00231   io_service_.reset();
00232   io_service_.run();
00233 }
00234 
00236 void
00237 pcl::RobotEyeGrabber::asyncSocketReceive()
00238 {
00239   // expecting exactly 464 bytes, using a larger buffer so that if a
00240   // larger packet arrives unexpectedly we'll notice it.
00241   socket_->async_receive_from(boost::asio::buffer(receive_buffer_, 500), sender_endpoint_,
00242     boost::bind(&RobotEyeGrabber::socketCallback, this,
00243         boost::asio::placeholders::error,
00244         boost::asio::placeholders::bytes_transferred));
00245 }
00246 
00248 void
00249 pcl::RobotEyeGrabber::socketCallback(const boost::system::error_code&, std::size_t numberOfBytes)
00250 {
00251   if (terminate_thread_)
00252     return;
00253 
00254   if (sensor_address_ == boost::asio::ip::address_v4::any ()
00255       || sensor_address_ == sender_endpoint_.address ())
00256   {
00257     if (numberOfBytes == 464)
00258     {
00259       unsigned char *dup = new unsigned char[numberOfBytes];
00260       memcpy (dup, receive_buffer_, numberOfBytes);
00261       packet_queue_.enqueue (boost::shared_array<unsigned char>(dup));
00262     }
00263   }
00264 
00265   asyncSocketReceive ();
00266 }
00267 
00269 void
00270 pcl::RobotEyeGrabber::start ()
00271 {
00272   if (isRunning ())
00273     return;
00274 
00275   boost::asio::ip::udp::endpoint destinationEndpoint (boost::asio::ip::address_v4::any (), data_port_);
00276 
00277   try
00278   {
00279           socket_.reset (new boost::asio::ip::udp::socket (io_service_, destinationEndpoint));
00280   }
00281   catch (std::exception &e)
00282   {
00283           PCL_ERROR ("[pcl::RobotEyeGrabber::start] Unable to bind to socket! %s\n", e.what ());
00284     return;
00285   }
00286 
00287   terminate_thread_ = false;
00288   resetPointCloud ();
00289   consumer_thread_.reset(new boost::thread (boost::bind (&RobotEyeGrabber::consumerThreadLoop, this)));
00290   socket_thread_.reset(new boost::thread (boost::bind (&RobotEyeGrabber::socketThreadLoop, this)));
00291 }
00292 
00294 void
00295 pcl::RobotEyeGrabber::stop ()
00296 {
00297   if (!isRunning ())
00298     return;
00299 
00300   terminate_thread_ = true;
00301 
00302 
00303   socket_->close ();
00304   io_service_.stop ();
00305   socket_thread_->join ();
00306   socket_thread_.reset ();
00307   socket_.reset();
00308 
00309   packet_queue_.stopQueue ();
00310   consumer_thread_->join ();
00311   consumer_thread_.reset ();
00312 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:32:10