Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 #ifndef __COMM_H__
00033 #define __COMM_H__
00034 
00035 #include <iostream>
00036 #include <map>
00037 #include <vector>
00038 #include <boost/bind.hpp>
00039 #include <boost/function.hpp>
00040 #include <boost/shared_ptr.hpp>
00041 #include <boost/thread.hpp>
00042 #include <boost/asio.hpp>
00043 
00044 #include <ros/ros.h>
00045 
00046 
00047 #include <asctec_hl_comm/HL_interface.h>
00048 
00049 typedef boost::function<void(uint8_t*, int32_t)> CommCallbackType;
00050 typedef std::map<uint8_t, CommCallbackType> CommCallbackMap;
00051 
00052 class Comm;
00053 typedef boost::shared_ptr<Comm> CommPtr;
00054 
00056 
00062 class Comm
00063 {
00064   typedef boost::asio::serial_port SerialPort;
00065   typedef boost::shared_ptr<SerialPort> SerialPortPtr;
00066 
00067 private:
00068 
00069   SerialPortPtr port_rx_;
00070   SerialPortPtr port_tx_;
00071   boost::asio::io_service uart_service_;
00072   boost::asio::deadline_timer rx_timeout_;
00073   bool rx_timeout_occurred_;
00074   boost::thread uart_thread_[2];
00075 
00076   std::string port_rx_name_;
00077   std::string port_tx_name_;
00078 
00079   uint32_t rx_packet_cnt_;
00080   uint32_t rx_packet_good_cnt_;
00081 
00082   uint8_t tx_buffer_[256];
00083   uint8_t rx_buffer_[256];
00084   uint32_t tx_bytes2send_;
00085   int rx_state_;
00086   std::vector<uint8_t> packet_acks_;
00087   boost::mutex tx_mutex_;
00088   const int TX_HEADER_SIZE;
00089 
00090   CommCallbackMap callbacks_;
00091 
00092   void rxReadStart(uint32_t length, uint32_t timeout = 0);
00093   void rxReadCallback(const boost::system::error_code& error, size_t bytes_transferred);
00094   void rxTimeoutCallback(const boost::system::error_code & error);
00095   bool configurePort(SerialPortPtr & serial_port, uint32_t *baudrate);
00096   bool connect(SerialPortPtr & serial_port, const std::string & port, uint32_t baudrate);
00097 
00098   void processPacketAck(uint8_t * buf, uint32_t length);
00099   bool validateChecksum(uint8_t * buf, uint32_t length, uint16_t checksum);
00100 
00101   bool waitForPacketAck(uint8_t ack_id, const double & timeout = 1.0);
00102 
00103   inline uint16_t crc_update(uint16_t crc, uint8_t data);
00104   uint16_t crc16(void* data, uint16_t cnt, uint16_t crc = 0xff);
00105 
00106   void serializePacket(uint8_t packet_id, const void * data, const int32_t & packet_size, uint8_t flag = 0);
00107 
00108 public:
00109   Comm();
00110 
00111   ~Comm();
00112 
00114 
00125   bool connect(const std::string & port_rx, const std::string & port_tx, uint32_t baudrate);
00126 
00128   void close();
00129 
00130   uint32_t getRxPackets()
00131   {
00132     return rx_packet_cnt_;
00133   }
00134 
00135   uint32_t getRxPacketsGood()
00136   {
00137     return rx_packet_good_cnt_;
00138   }
00139 
00141   template<typename T>
00142     bool sendPacket(uint8_t packet_id, const T & data)
00143     {
00144       serializePacket(packet_id, &data, sizeof(T));
00145 
00146       return tx_bytes2send_ == boost::asio::write(*port_tx_, boost::asio::buffer(tx_buffer_, tx_bytes2send_));
00147     }
00148 
00150   template<typename T>
00151     bool sendPacketAck(uint8_t packet_id, const T & data, const double & timeout = 1.0)
00152     {
00153       
00154       ros::Time time_start = ros::Time::now();
00155       uint8_t ack_id = (uint8_t)(time_start.toNSec() & 0xff) | HLI_COMM_ACK;
00156 
00157 
00158 
00159 
00160       serializePacket(packet_id, &data, sizeof(T), ack_id);
00161       if (tx_bytes2send_ != boost::asio::write(*port_tx_, boost::asio::buffer(tx_buffer_, tx_bytes2send_)))
00162         return false;
00163 
00164       return waitForPacketAck(ack_id, timeout);
00165     }
00166 
00168 
00175   template<class T>
00176     void registerCallback(uint8_t id, void(T::*cb_func)(uint8_t*, uint32_t), T* p_obj)
00177     {
00178       if (callbacks_.find(id) != callbacks_.end())
00179         std::cerr<<"message "<< id << "is already registered"<<std::endl;
00180       else
00181         callbacks_[id] = boost::bind(cb_func, p_obj, _1, _2);
00182     }
00183 void loopOnce(){uart_service_.run_one();};
00184 };
00185 
00186 #endif