callback.h
Go to the documentation of this file.
00001 //==============================================================================
00002 // Copyright (c) 2012, Johannes Meyer, TU Darmstadt
00003 // All rights reserved.
00004 
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are met:
00007 //     * Redistributions of source code must retain the above copyright
00008 //       notice, this list of conditions and the following disclaimer.
00009 //     * Redistributions in binary form must reproduce the above copyright
00010 //       notice, this list of conditions and the following disclaimer in the
00011 //       documentation and/or other materials provided with the distribution.
00012 //     * Neither the name of the Flight Systems and Automatic Control group,
00013 //       TU Darmstadt, nor the names of its contributors may be used to
00014 //       endorse or promote products derived from this software without
00015 //       specific prior written permission.
00016 
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00020 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //==============================================================================
00028 
00029 #ifndef UBLOX_GPS_CALLBACK_H
00030 #define UBLOX_GPS_CALLBACK_H
00031 
00032 #include <ros/console.h>
00033 #include <ublox/serialization/ublox_msgs.h>
00034 #include <boost/format.hpp>
00035 #include <boost/function.hpp>
00036 #include <boost/thread.hpp>
00037 
00038 namespace ublox_gps {
00039 
00043 class CallbackHandler {
00044  public:
00048   virtual void handle(ublox::Reader& reader) = 0;
00049 
00053   bool wait(const boost::posix_time::time_duration& timeout) {
00054     boost::mutex::scoped_lock lock(mutex_);
00055     return condition_.timed_wait(lock, timeout);
00056   }
00057 
00058  protected:
00059   boost::mutex mutex_; 
00060   boost::condition_variable condition_; 
00061 };
00062 
00067 template <typename T>
00068 class CallbackHandler_ : public CallbackHandler {
00069  public:
00070   typedef boost::function<void(const T&)> Callback; 
00071 
00076   CallbackHandler_(const Callback& func = Callback()) : func_(func) {}
00077   
00081   virtual const T& get() { return message_; }
00082 
00087   void handle(ublox::Reader& reader) {
00088     boost::mutex::scoped_lock lock(mutex_);
00089     try {
00090       if (!reader.read<T>(message_)) {
00091         ROS_DEBUG_COND(debug >= 2, 
00092                        "U-Blox Decoder error for 0x%02x / 0x%02x (%d bytes)", 
00093                        static_cast<unsigned int>(reader.classId()),
00094                        static_cast<unsigned int>(reader.messageId()),
00095                        reader.length());
00096         condition_.notify_all();
00097         return;
00098       }
00099     } catch (std::runtime_error& e) {
00100       ROS_DEBUG_COND(debug >= 2, 
00101                      "U-Blox Decoder error for 0x%02x / 0x%02x (%d bytes)", 
00102                      static_cast<unsigned int>(reader.classId()),
00103                      static_cast<unsigned int>(reader.messageId()),
00104                      reader.length());
00105       condition_.notify_all();
00106       return;
00107     }
00108 
00109     if (func_) func_(message_);
00110     condition_.notify_all();
00111   }
00112   
00113  private:
00114   Callback func_; 
00115   T message_; 
00116 };
00117 
00121 class CallbackHandlers {
00122  public:
00128   template <typename T>
00129   void insert(typename CallbackHandler_<T>::Callback callback) {
00130     boost::mutex::scoped_lock lock(callback_mutex_);
00131     CallbackHandler_<T>* handler = new CallbackHandler_<T>(callback);
00132     callbacks_.insert(
00133       std::make_pair(std::make_pair(T::CLASS_ID, T::MESSAGE_ID),
00134                      boost::shared_ptr<CallbackHandler>(handler)));
00135   }
00136 
00145   template <typename T>
00146   void insert(
00147       typename CallbackHandler_<T>::Callback callback, 
00148       unsigned int message_id) {
00149     boost::mutex::scoped_lock lock(callback_mutex_);
00150     CallbackHandler_<T>* handler = new CallbackHandler_<T>(callback);
00151     callbacks_.insert(
00152       std::make_pair(std::make_pair(T::CLASS_ID, message_id),
00153                      boost::shared_ptr<CallbackHandler>(handler)));
00154   }
00155 
00160   void handle(ublox::Reader& reader) {
00161     // Find the callback handlers for the message & decode it
00162     boost::mutex::scoped_lock lock(callback_mutex_);
00163     Callbacks::key_type key =
00164         std::make_pair(reader.classId(), reader.messageId());
00165     for (Callbacks::iterator callback = callbacks_.lower_bound(key);
00166          callback != callbacks_.upper_bound(key); ++callback)
00167       callback->second->handle(reader);
00168   }
00169 
00175   template <typename T>
00176   bool read(T& message, const boost::posix_time::time_duration& timeout) {
00177     bool result = false;
00178     // Create a callback handler for this message
00179     callback_mutex_.lock();
00180     CallbackHandler_<T>* handler = new CallbackHandler_<T>();
00181     Callbacks::iterator callback = callbacks_.insert(
00182       (std::make_pair(std::make_pair(T::CLASS_ID, T::MESSAGE_ID),
00183                       boost::shared_ptr<CallbackHandler>(handler))));
00184     callback_mutex_.unlock();
00185 
00186     // Wait for the message
00187     if (handler->wait(timeout)) {
00188       message = handler->get();
00189       result = true;
00190     }
00191     
00192     // Remove the callback handler
00193     callback_mutex_.lock();
00194     callbacks_.erase(callback);
00195     callback_mutex_.unlock();
00196     return result;
00197   }
00198 
00205   void readCallback(unsigned char* data, std::size_t& size) {
00206     ublox::Reader reader(data, size);
00207     // Read all U-Blox messages in buffer
00208     while (reader.search() != reader.end() && reader.found()) {
00209       if (debug >= 3) {
00210         // Print the received bytes
00211         std::ostringstream oss;
00212         for (ublox::Reader::iterator it = reader.pos();
00213              it != reader.pos() + reader.length() + 8; ++it)
00214           oss << boost::format("%02x") % static_cast<unsigned int>(*it) << " ";
00215         ROS_DEBUG("U-blox: reading %d bytes\n%s", reader.length() + 8, 
00216                  oss.str().c_str());
00217       }
00218 
00219       handle(reader);
00220     }
00221 
00222     // delete read bytes from ASIO input buffer
00223     std::copy(reader.pos(), reader.end(), data);
00224     size -= reader.pos() - data;
00225   }
00226 
00227  private:
00228   typedef std::multimap<std::pair<uint8_t, uint8_t>,
00229                         boost::shared_ptr<CallbackHandler> > Callbacks;
00230 
00231   // Call back handlers for u-blox messages
00232   Callbacks callbacks_;
00233   boost::mutex callback_mutex_;
00234 };
00235 
00236 }  // namespace ublox_gps
00237 
00238 #endif  // UBLOX_GPS_CALLBACK_H


ublox_gps
Author(s): Johannes Meyer
autogenerated on Fri Jun 14 2019 19:26:13