RmpUsb.cpp
Go to the documentation of this file.
00001 /*
00002   COPYRIGHT (c) 2014 SEGWAY Inc.
00003 
00004   Software License Agreement:
00005 
00006   The software supplied herewith by Segway Inc. (the "Company") for its 
00007   RMP Robotic Platforms is intended and supplied to you, the Company's 
00008   customer, for use solely and exclusively with Segway products. The 
00009   software is owned by the Company and/or its supplier, and is protected 
00010   under applicable copyright laws.  All rights are reserved. Any use in 
00011   violation of the foregoing restrictions may subject the user to criminal
00012   sanctions under applicable laws, as well as to civil liability for the 
00013   breach of the terms and conditions of this license. The Company may 
00014   immediately terminate this Agreement upon your use of the software with 
00015   any products that are not Segway products.
00016 
00017   You shall indemnify, defend and hold the Company harmless from any claims, 
00018   demands, liabilities or expenses, including reasonable attorneys fees, incurred 
00019   by the Company as a result of any claim or proceeding against the Company 
00020   arising out of or based upon: 
00021 
00022   (i) The combination, operation or use of the software by you with any hardware, 
00023       products, programs or data not supplied or approved in writing by the Company, 
00024       if such claim or proceeding would have been avoided but for such combination, 
00025       operation or use.
00026 
00027   (ii) The modification of the software by or on behalf of you.
00028 
00029   (iii) Your use of the software.
00030 
00031   THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
00032   WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED
00033   TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00034   PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
00035   IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
00036   CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
00037 */
00038 
00039 #include <RmpUsb.h>
00040 
00041 #include <exception>
00042 
00043 #include <boost/asio.hpp>
00044 #include <boost/bind.hpp>
00045 #include <boost/date_time/posix_time/posix_time_types.hpp>
00046 
00047 #include <RmpHelper.h>
00048 #include <RmpLogger.h>
00049 
00050 namespace segway
00051 {
00052   static const size_t MAX_RCV_SIZE = 1024;
00053   static const long TIMEOUT = 30; // [ms]
00054   static const unsigned int BAUD_RATE = 115200;
00055   static const unsigned int CHARACTER_SIZE = 8; // [bit]
00056   
00057   class RmpUsb::Impl
00058   {
00059   public:
00060     Impl(const std::string& rDevicePort);
00061     size_t Write(const Bytes& rData, float timeout, boost::system::error_code& rErrorCode);
00062     size_t Read(Bytes& rData, float timeout, boost::system::error_code& rErrorCode);
00063 
00064   private:
00065     void CheckDeadline();
00066     static void Handle(const boost::system::error_code& rErrorCodeIn, size_t sizeIn, boost::system::error_code* pErrorCodeOut, std::size_t* pSizeOut);
00067 
00068     boost::asio::io_service m_IoService;
00069     boost::asio::serial_port m_SerialPort;
00070     boost::asio::deadline_timer m_Timer;
00071   };
00072 
00073   RmpUsb::RmpUsb(const std::string& rDevicePort)
00074     : m_pImpl(new Impl(rDevicePort)) 
00075   {}
00076 
00077   RmpUsb::~RmpUsb()
00078   {}
00079 
00080   bool RmpUsb::Send(uint16_t commandId, uint32_t value1, uint32_t value2)
00081   {
00082     Bytes message;
00083     ConvertCommandToBytes(commandId, value1, value2, message);
00084     AppendCrc16(message);
00085 
00086     boost::system::error_code errorCode;
00087     size_t bytesSent = m_pImpl->Write(message, TIMEOUT, errorCode);
00088 
00089     if (errorCode.value() != boost::system::errc::success)
00090     {
00091       SEGWAY_LOG(ERROR, "Fail to usb send: " << errorCode.message());
00092 
00093       return false;
00094     }
00095     
00096     if (bytesSent != message.size())
00097     {
00098       return false;
00099     }
00100 
00101     return true;
00102   }
00103 
00104   bool RmpUsb::Receive(Bytes& rData, size_t size)
00105   {
00106     rData.resize(size + CRC_FEEDBACK_SIZE);
00107 
00108     boost::system::error_code errorCode;
00109     size_t bytesReceived = m_pImpl->Read(rData, TIMEOUT, errorCode);
00110 
00111     if (errorCode.value() != boost::system::errc::success)
00112     {
00113       SEGWAY_LOG(DEBUG, "Fail to receive usb packet: " << errorCode.message());
00114 
00115       return false;
00116     }
00117     
00118     if (bytesReceived != (size + CRC_FEEDBACK_SIZE))
00119     {
00120       SEGWAY_LOG(DEBUG, "Received usb packet of unexpected size: " << bytesReceived << ", expected: " << size + CRC_FEEDBACK_SIZE);
00121       
00122       return false;
00123     }
00124  
00125     if (!IsCrcValid(rData, bytesReceived))
00126     {
00127       SEGWAY_LOG(ERROR, "CRC mismatched on usb receive.");
00128 
00129       return false;
00130     }
00131 
00132     rData.erase(rData.begin() + size, rData.end());
00133 
00134     return true;
00135   }
00136 
00137   RmpUsb::Impl::Impl(const std::string& rDevicePort)
00138     : m_IoService()
00139     , m_SerialPort(m_IoService)
00140     , m_Timer(m_IoService)
00141   {
00142     boost::system::error_code errorCode;
00143     m_SerialPort.open(rDevicePort, errorCode);
00144 
00145     if (errorCode.value() != boost::system::errc::success)
00146     {
00147       std::stringstream stringStream;
00148       stringStream << "Unable to open serial port " << rDevicePort << ": " << errorCode.message();
00149       
00150       throw std::runtime_error(stringStream.str());
00151     }
00152     
00153     m_SerialPort.set_option(boost::asio::serial_port_base::baud_rate(BAUD_RATE));
00154     m_SerialPort.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
00155     m_SerialPort.set_option(boost::asio::serial_port_base::character_size(CHARACTER_SIZE));
00156     m_SerialPort.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));
00157     m_SerialPort.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
00158     
00159     m_Timer.expires_at(boost::posix_time::pos_infin);
00160          
00161     CheckDeadline();
00162   }
00163 
00164   size_t RmpUsb::Impl::Write(const Bytes& rData, float timeout, boost::system::error_code& rErrorCode)
00165   {
00166     m_Timer.expires_from_now(boost::posix_time::milliseconds(timeout));
00167 
00168     rErrorCode = boost::asio::error::would_block;
00169     size_t size = 0;
00170 
00171     boost::asio::async_write(m_SerialPort, boost::asio::buffer(rData), boost::bind(&Impl::Handle, _1, _2, &rErrorCode, &size));
00172 
00173     do
00174     {
00175       m_IoService.run_one();
00176     }
00177     while (rErrorCode == boost::asio::error::would_block);
00178     
00179     return size;
00180   }
00181 
00182   size_t RmpUsb::Impl::Read(Bytes& rData, float timeout, boost::system::error_code& rErrorCode)
00183   {
00184     m_Timer.expires_from_now(boost::posix_time::milliseconds(timeout));
00185 
00186     rErrorCode = boost::asio::error::would_block;
00187     size_t size = 0;
00188 
00189     boost::asio::async_read(m_SerialPort, boost::asio::buffer(rData), boost::bind(&Impl::Handle, _1, _2, &rErrorCode, &size));
00190 
00191     do
00192     {
00193       m_IoService.run_one();
00194     }
00195     while (rErrorCode == boost::asio::error::would_block);
00196 
00197     return size;
00198   }
00199 
00200   void RmpUsb::Impl::CheckDeadline()
00201   {
00202     if (m_Timer.expires_at() <= boost::asio::deadline_timer::traits_type::now())
00203     {
00204       m_SerialPort.cancel();
00205 
00206       m_Timer.expires_at(boost::posix_time::pos_infin);
00207     }
00208 
00209     m_Timer.async_wait(boost::bind(&Impl::CheckDeadline, this));
00210   }
00211 
00212   void RmpUsb::Impl::Handle(const boost::system::error_code& rErrorCodeIn, size_t sizeIn, boost::system::error_code* pErrorCodeOut, std::size_t* pSizeOut)
00213   {
00214     *pErrorCodeOut = rErrorCodeIn;
00215     *pSizeOut = sizeIn;
00216   }
00217 
00218 } // namespace segway


rmp_base
Author(s):
autogenerated on Wed Aug 26 2015 16:24:39