myahrs_plus.hpp
Go to the documentation of this file.
00001 //*****************************************************************************
00002 //
00003 // Copyright (c) 2014 Withrobot, Inc.  All rights reserved.
00004 //
00005 // Software License Agreement
00006 //
00007 // Withrobot, Inc.(Withrobot) is supplying this software for use solely and
00008 // exclusively on Withrobot's products.
00009 //
00010 // The software is owned by Withrobot and/or its suppliers, and is protected
00011 // under applicable copyright laws.  All rights are reserved.
00012 // Any use in violation of the foregoing restrictions may subject the user
00013 // to criminal sanctions under applicable laws, as well as to civil liability
00014 // for the breach of the terms and conditions of this license.
00015 //
00016 // THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
00017 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
00018 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
00019 // WITHROBOT SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
00020 // OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
00021 //
00022 //*****************************************************************************
00023 
00024 /*
00025  *  myahrs_plus.hpp
00026  *   - myAHRS+ SDK
00027  *
00028  *  2014.07.05 ('c')void
00029  *  2014.07.15 ('c')void
00030  *  2014.07.28 ('c')void
00031  *  2014.08.02 ('c')void
00032  *      ver. 1.0
00033  *  2014.08.14 ('c')void
00034  *      version string 추가
00035  *  2014.08.15 ('c')void
00036  *      통신 이외의 모든 실수형은 double
00037  *  2014.08.27 ('c')void
00038  *  2014.09.09 ('c')void
00039  *
00040  */
00041 
00042 /*
00043  *  DO NOT EDIT THIS FILE
00044  */
00045 
00046 #ifndef __MYAHRS_PLUS_H_
00047 #define __MYAHRS_PLUS_H_
00048 
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #include <string.h>
00052 #include <stdint.h>
00053 
00054 #define _USE_MATH_DEFINES
00055 #include <math.h>
00056 
00057 #include <exception>
00058 #include <string>
00059 #include <vector>
00060 #include <deque>
00061 #include <map>
00062 #include <iostream>
00063 #include <sstream>
00064 #include <algorithm>
00065 
00066 #ifdef WIN32
00067     #define _AFXDLL
00068     #include <afx.h>
00069     #include <windows.h>
00070     #include <cctype>
00071 
00072     #pragma warning( disable : 4996 ) // sprintf
00073     #pragma warning( disable : 4355 ) // warning C4355: 'this' : used in base member initializer list
00074     #pragma warning( disable : 4244 ) // warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
00075 
00076     #define DBG_PRINTF(x, ...)  {if(x) { printf(__VA_ARGS__);}}
00077 
00078 #else // LINUX
00079     #include <unistd.h>
00080     #include <pthread.h>
00081     #include <semaphore.h>
00082     #include <fcntl.h>
00083     #include <termios.h>
00084     #include <sys/time.h>
00085 
00086     #pragma GCC diagnostic ignored "-Wformat"
00087     #define DBG_PRINTF(x, args...)  {if(x) { printf(args);}}
00088 #endif // WIN32
00089 
00090 
00091 /*
00092  *  Version
00093  */
00094 #define WITHROBOT_MYAHRS_PLUS_SDK_VERSION "myahrs+ sdk. ver. 1.01"
00095 
00096 /*
00097  *  debugging sw
00098  */
00099 #define DEBUG_PLATFORM        false
00100 #define DEBUG_ASCII_PROTOCOL  false
00101 #define DEBUG_BINARY_PROTOCOL false
00102 #define DEBUG_MYAHRS_PLUS     false
00103 
00104 
00105 namespace WithRobot {
00106 
00107     class myAhrsException
00108     {
00109     public:
00110         std::string err;
00111         myAhrsException(std::string e=""): err(e){}
00112         virtual ~myAhrsException() {}
00113 
00114         const char* what() const throw() {
00115             return err.c_str();
00116         }
00117     };
00118 
00119 /**********************************************************************************************************
00120  *
00121  * Platform abstraction
00122  *
00123  **********************************************************************************************************/
00124 
00125 #ifdef WIN32
00126     class Platform
00127     {
00128     public:
00129         class SerialPort
00130         {
00131             std::string port_name;
00132             unsigned int baudrate;
00133 
00134             HANDLE m_hIDComDev;
00135             BOOL m_bOpened;
00136 
00137         public:
00138             SerialPort(const char* port="COM3", unsigned int brate=115200)
00139             : port_name(port), baudrate(brate)
00140             , m_hIDComDev(NULL), m_bOpened(FALSE)
00141             {
00142             }
00143 
00144             ~SerialPort() {
00145                 Close();
00146             }
00147 
00148             bool Open(const char* port, int brate) {
00149                 port_name = port;
00150                 baudrate = brate;
00151                 return Open();
00152             }
00153 
00154             bool Open() {
00155                 char szPort[32];
00156                 sprintf(szPort, "\\\\.\\%s", port_name.c_str());
00157                 CString port_str = CString::CStringT(CA2CT(szPort));
00158 
00159                 DBG_PRINTF(DEBUG_PLATFORM, "portname : %s, baudrate %d\n", szPort, baudrate);
00160 
00161                 m_hIDComDev = CreateFile( (LPCTSTR)port_str,
00162                                           GENERIC_READ | GENERIC_WRITE,
00163                                           0,
00164                                           NULL,
00165                                           OPEN_EXISTING,
00166                                           FILE_ATTRIBUTE_NORMAL,
00167                                           NULL );
00168 
00169                 if( m_hIDComDev == NULL ) {
00170                     DBG_PRINTF(DEBUG_PLATFORM, "ERROR : m_hIDComDev == NULL\n");
00171                     return false;
00172                 }
00173 
00174                 DCB dcb = {0};
00175 
00176                 if (!GetCommState(m_hIDComDev, &dcb)) {
00177                     //error getting state
00178                     CloseHandle( m_hIDComDev );
00179                     printf("ERROR : GetCommState()\n");
00180                     return false;
00181                 }
00182 
00183                 dcb.DCBlength = sizeof( DCB );
00184                 GetCommState( m_hIDComDev, &dcb );
00185                 dcb.BaudRate = baudrate;
00186                 dcb.ByteSize = 8;
00187 
00188                 if(!SetCommState(m_hIDComDev, &dcb)){
00189                     //error setting serial port state
00190                     CloseHandle( m_hIDComDev );
00191                     DBG_PRINTF(DEBUG_PLATFORM, "ERROR : SetCommState()\n");
00192                     return false;
00193                 }
00194 
00195                 COMMTIMEOUTS CommTimeOuts;
00196 
00197                 CommTimeOuts.ReadIntervalTimeout = 1;
00198                 CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
00199                 CommTimeOuts.ReadTotalTimeoutConstant = 1;
00200                 CommTimeOuts.WriteTotalTimeoutMultiplier = 1;
00201                 CommTimeOuts.WriteTotalTimeoutConstant = 10;
00202 
00203                 if(!SetCommTimeouts( m_hIDComDev, &CommTimeOuts)) {
00204                     CloseHandle( m_hIDComDev );
00205                     DBG_PRINTF(DEBUG_PLATFORM, "ERROR : SetCommTimeouts()\n");
00206                     return false;
00207                 }
00208 
00209                 m_bOpened = TRUE;
00210 
00211                 return (m_bOpened == TRUE);
00212             }
00213 
00214             void Close() {
00215                 if( !m_bOpened || m_hIDComDev == NULL ) {
00216                     return;
00217                 }
00218 
00219                 CloseHandle( m_hIDComDev );
00220                 m_bOpened = FALSE;
00221                 m_hIDComDev = NULL;
00222             }
00223 
00224             int Read(unsigned char* buf, unsigned int buf_len) {
00225                 if( !m_bOpened || m_hIDComDev == NULL ) return -1;
00226 
00227                 BOOL bReadStatus;
00228                 DWORD dwBytesRead, dwErrorFlags;
00229                 COMSTAT ComStat;
00230 
00231                 ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
00232 
00233                 if(ComStat.cbInQue <= 0) {
00234                     dwBytesRead = 1;
00235                 }
00236                 else {
00237                     dwBytesRead = (DWORD) ComStat.cbInQue;
00238                 }
00239 
00240                 if( buf_len < (int) dwBytesRead ) dwBytesRead = (DWORD) buf_len;
00241 
00242                 bReadStatus = ReadFile( m_hIDComDev, buf, dwBytesRead, &dwBytesRead, NULL );
00243                 if( !bReadStatus ){
00244                     //if( GetLastError() == ERROR_IO_PENDING ){
00245                     //    WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
00246                     //    return( (int) dwBytesRead );
00247                     //}
00248                     return 0;
00249                 }
00250 
00251                 return( (int) dwBytesRead );
00252             }
00253 
00254             int Write(unsigned char* data, unsigned int data_len) {
00255                 BOOL bWriteStat;
00256                 DWORD dwBytesWritten = 0;
00257 
00258                 if(m_bOpened != TRUE) {
00259                     return -1;
00260                 }
00261 
00262                 bWriteStat = WriteFile( m_hIDComDev, (LPSTR)data, data_len, &dwBytesWritten, NULL);
00263                 if(!bWriteStat) {
00264                       if (GetLastError() != ERROR_IO_PENDING) {
00265                          // WriteFile failed, but it isn't delayed. Report error and abort.
00266                          return dwBytesWritten;
00267                       }
00268                       else {
00269                          // Write is pending... 여기로 빠질리는 없지만서도...
00270                          //Sleep(10);
00271                          // retry;
00272                          return dwBytesWritten;
00273                       }
00274                 }
00275                 else {
00276                     return dwBytesWritten;
00277                 }
00278             }
00279 
00280             int Flush() {
00281                 int len= 0, count = 0;
00282                 unsigned char buf[256];
00283                 while((len = Read(buf, sizeof(buf))) > 0) {
00284                     count += len;
00285                 }
00286                 return count;
00287             }
00288         };
00289 
00290 
00291         class Mutex
00292         {
00293             CRITICAL_SECTION cs;
00294 
00295         public:
00296             Mutex() {
00297                 InitializeCriticalSection(&cs);
00298             }
00299 
00300             ~Mutex() {
00301                 DeleteCriticalSection(&cs);
00302             }
00303 
00304             inline void lock() {
00305                 EnterCriticalSection(&cs);
00306             }
00307 
00308             inline void unlock() {
00309                 LeaveCriticalSection(&cs);
00310             }
00311         };
00312 
00313         class Event
00314         {
00315             HANDLE event;
00316 
00317         public:
00318             Event() {
00319                 event = CreateEvent(NULL,
00320                                     TRUE,  // bManualReset
00321                                     FALSE,  // bInitialState
00322                                     _T("Event"));
00323             }
00324 
00325             ~Event() {
00326                 CloseHandle(event);
00327             }
00328 
00329             inline bool wait(int timeout_msec=-1) {
00330                 if(timeout_msec < 0) {
00331                     timeout_msec = INFINITE;
00332                 }
00333                 DWORD res = WaitForSingleObject(event, timeout_msec);
00334                 ResetEvent(event);
00335                 return (res == WAIT_OBJECT_0);
00336             }
00337 
00338             inline bool set() {
00339                 return (SetEvent(event) == TRUE);
00340             }
00341         };
00342 
00343 
00344         class Thread
00345         {
00346             DWORD thread_id;
00347             HANDLE thread;
00348 
00349         public:
00350             Thread() : thread(NULL), thread_id(0){}
00351 
00352             bool start(void*(*thread_proc)(void*), void* arg, size_t stack_size=16*1024) {
00353                 thread = CreateThread(NULL, (DWORD)stack_size, (LPTHREAD_START_ROUTINE)thread_proc, arg, 0, &thread_id);
00354                 return (thread != NULL);
00355             }
00356 
00357             void join() {
00358                 if(thread != NULL) {
00359                     WaitForSingleObject(thread, INFINITE);
00360                     CloseHandle(thread);
00361                 }
00362                 thread = NULL;
00363                 thread_id = 0;
00364             }
00365         };
00366 
00367         static void msleep(unsigned int msec) {
00368             Sleep(msec);
00369         }
00370     };
00371 
00372 #else
00373     /*
00374      * Unix-Like OS (Linux/OSX)
00375      */
00376     class Platform
00377     {
00378     public:
00379 
00380         class SerialPort
00381         {
00382             std::string port_name; // ex) "/dev/tty.usbmodem14241"
00383             int port_fd;
00384             unsigned int baudrate;
00385 
00386         public:
00387             SerialPort(const char* port = "", unsigned int brate=115200)
00388             : port_name(port), baudrate(brate)
00389             , port_fd(-1)
00390             {
00391             }
00392 
00393             ~SerialPort() {
00394                 Close();
00395             }
00396 
00397             bool Open(const char* port, int brate) {
00398                 port_name = port;
00399                 baudrate = brate;
00400                 return Open();
00401             }
00402 
00403             bool Open() {
00404                 int fd = 0;
00405                 struct termios options;
00406 
00407                 if(port_fd > 0) {
00408                     return true;
00409                 }
00410 
00411                 fd = open(port_name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
00412                 if(fd < 0) {
00413                     return false;
00414                 }
00415 
00416                 fcntl(fd, F_SETFL, 0);   // clear all flags on descriptor, enable direct I/O
00417                 tcgetattr(fd, &options); // read serial port options
00418 
00419                 cfsetspeed(&options, baudrate);
00420                 cfmakeraw(&options);
00421 
00422                 options.c_cflag |= CREAD | CLOCAL; // turn on READ
00423                 options.c_cflag |= CS8;
00424                 options.c_cc[VMIN] = 0;
00425                 options.c_cc[VTIME] = 1;
00426 
00427                 // set the new port options
00428                 tcsetattr(fd, TCSANOW, &options);
00429 
00430                 // flush I/O buffers
00431                 tcflush(fd, TCIOFLUSH);
00432 
00433                 port_fd = fd;
00434 
00435                 return (fd > 0);
00436 
00437             }
00438 
00439             void Close() {
00440                 if(port_fd > 0) {
00441                     close(port_fd);
00442                     port_fd = -1;
00443                 }
00444             }
00445 
00446             int Read(unsigned char* buf, unsigned int buf_len) {
00447                 if(port_fd < 0) {
00448                     return -1;
00449                 }
00450 
00451                 int n = read(port_fd, buf, buf_len-1);
00452                 if(n > 0) {
00453                     buf[n] = 0;
00454                 }
00455 
00456                 return n;
00457             }
00458 
00459             int Write(unsigned char* data, unsigned int data_len) {
00460                 if(port_fd < 0) {
00461                     return -1;
00462                 }
00463 
00464                 return write(port_fd, data, data_len);
00465             }
00466 
00467             int Flush() {
00468                 if(port_fd < 0) {
00469                     return -1;
00470                 }
00471 
00472                 // flush I/O buffers
00473                 return tcflush(port_fd, TCIOFLUSH);
00474             }
00475         };
00476 
00477 
00478         class Mutex
00479         {
00480             pthread_mutex_t mutex;
00481 
00482         public:
00483             Mutex() {
00484                 pthread_mutex_init(&mutex, NULL);
00485             }
00486 
00487             ~Mutex() {
00488                 pthread_mutex_destroy(&mutex);
00489             }
00490 
00491             inline void lock() {
00492                 pthread_mutex_lock(&mutex);
00493             }
00494 
00495             inline void unlock() {
00496                 pthread_mutex_unlock(&mutex);
00497             }
00498         };
00499 
00500         class Event
00501         {
00502             pthread_mutex_t mutex;
00503             pthread_cond_t  cond;
00504 
00505         public:
00506             Event() {
00507                 pthread_mutex_init(&mutex, NULL);
00508                 pthread_cond_init(&cond, NULL);
00509             }
00510 
00511             ~Event() {
00512                 pthread_mutex_destroy(&mutex);
00513                 pthread_cond_destroy(&cond);
00514             }
00515 
00516             inline bool wait(int timeout_msec=-1) {
00517                 bool res = true;
00518                 pthread_mutex_lock(&mutex);
00519                 if(timeout_msec > 0) {
00520                     struct timeval tv;
00521                     struct timespec ts;
00522 
00523                     gettimeofday(&tv, NULL);
00524 
00525                     ts.tv_sec = time(NULL) + timeout_msec / 1000;
00526                     ts.tv_nsec = tv.tv_usec * 1000 + 1000 * 1000 * (timeout_msec % 1000);
00527                     ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
00528                     ts.tv_nsec %= (1000 * 1000 * 1000);
00529 
00530                     int n = pthread_cond_timedwait(&cond, &mutex, &ts);
00531                     res = (n == 0); // n == 0 : signaled, n == ETIMEDOUT
00532                 }
00533                 else {
00534                     pthread_cond_wait(&cond, &mutex);
00535                     res = true;
00536                 }
00537                 pthread_mutex_unlock(&mutex);
00538                 return res;
00539             }
00540 
00541             inline bool set() {
00542                 pthread_mutex_lock(&mutex);
00543                 pthread_cond_signal(&cond);
00544                 pthread_mutex_unlock(&mutex);
00545                 return true;
00546             }
00547         };
00548 
00549 
00550         class Thread
00551         {
00552             pthread_t thread;
00553 
00554         public:
00555             Thread() : thread(0){ }
00556 
00557             bool start(void*(*thread_proc)(void*), void* arg, size_t stack_size=16*1024) {
00558                 pthread_attr_t attr;
00559                 size_t stacksize;
00560                 pthread_attr_init(&attr);
00561 
00562                 //pthread_attr_getstacksize(&attr, &stacksize);
00563 
00564                 pthread_attr_setstacksize(&attr, stack_size);
00565                 int res = pthread_create(&thread, &attr, thread_proc, (void*)arg);
00566                 if(res != 0) {
00567                     thread = 0;
00568                 }
00569 
00570                 return (res == 0);
00571             }
00572 
00573             void join() {
00574                 if(thread != 0) {
00575                     pthread_join(thread, NULL);
00576                 }
00577                 thread = 0;
00578             }
00579         };
00580 
00581         static void msleep(unsigned int msec) {
00582             usleep(msec*1000);
00583         }
00584     }; // Platform
00585 
00586 #endif // #ifdef WIN32
00587 
00588 
00589 /**********************************************************************************************************
00590  *
00591  * platform independent implementation
00592  *
00593  **********************************************************************************************************/
00594 
00595     class LockGuard {
00596 
00597         Platform::Mutex & mutex;
00598 
00599     public:
00600         LockGuard(Platform::Mutex& m) : mutex(m) {
00601             mutex.lock();
00602         }
00603 
00604         ~LockGuard() {
00605             mutex.unlock();
00606         }
00607     };
00608 
00609 
00610     class StringUtil
00611     {
00612     public:
00613         static void replace(std::string & src, std::string s1, std::string s2) {
00614             size_t ofs = 0;
00615 
00616             do {
00617                 ofs = src.find(s1, ofs);
00618                 if(ofs == -1) {
00619                     return;
00620                 }
00621                 src.replace(ofs, s1.length(), s2);
00622                 ofs += s2.length();
00623             }while(1);
00624         }
00625 
00626         // trim from start
00627         static inline std::string &ltrim(std::string &s) {
00628                 s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
00629                 return s;
00630         }
00631 
00632         // trim from end
00633         static inline std::string &rtrim(std::string &s) {
00634                 s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
00635                 return s;
00636         }
00637 
00638         // trim from both ends
00639         static inline std::string &strip(std::string &s) {
00640                 return ltrim(rtrim(s));
00641         }
00642 
00643         static int split(std::vector<std::string> & token_list, const char* c_str, char delimiter, int token_max=-1) {
00644             std::stringstream is(c_str);
00645             std::string token;
00646 
00647             bool check_max = (token_max > 0);
00648 
00649             token_list.clear();
00650             while(getline(is, token, delimiter)){
00651                 token_list.push_back(token);
00652                 if(check_max) {
00653                     if(--token_max <= 0) {
00654                         break;
00655                     }
00656                 }
00657             }
00658 
00659             return token_list.size();
00660         }
00661 
00662         static std::string join(std::vector<std::string>& str_list, const std::string& delimiter) {
00663             std::ostringstream s;
00664             for(size_t i=0; i<str_list.size(); i++) {
00665                 if(i != 0) {
00666                     s << delimiter;
00667                 }
00668                 s << str_list[i];
00669             }
00670             return s.str();
00671         }
00672 
00673         template <typename T>
00674         static void to_string_list(std::vector<std::string>& str_list, T* array, size_t array_num) {
00675             for(size_t i=0; i<array_num; i++) {
00676                 std::ostringstream s;
00677                 s << array[i];
00678                 str_list.push_back(s.str());
00679             }
00680         }
00681 
00682         static int extract_attributes(std::map<std::string, std::string>& attribute_list, std::vector<std::string>& tokens) {
00683             std::vector<std::string> attribute_pair;
00684 
00685             for(size_t i=0; i<tokens.size(); i++) {
00686                 // "attribute_name=value"
00687                 if(split(attribute_pair, tokens[i].c_str(), '=') == 2) {
00688                     attribute_list[attribute_pair[0]] = attribute_pair[1];
00689                 }
00690             }
00691 
00692             return attribute_list.size();
00693         }
00694     };
00695 
00696     struct FrameBuffer {
00697         unsigned char buffer[1024];
00698         size_t offset;
00699 
00700         FrameBuffer() {
00701             reset();
00702         }
00703 
00704         void push(unsigned char byte) {
00705             if(offset < sizeof(buffer)) {
00706                 buffer[offset++] = byte;
00707             }
00708         }
00709 
00710         void reset() {
00711             memset(buffer, 0, sizeof(buffer));
00712             offset = 0;
00713         }
00714     };
00715 
00716     /**************************************************************************
00717      *
00718      * COMMUNICATION PROTOCOL (ASCII)
00719      *
00720      **************************************************************************/
00721 
00722     class iAsciiProtocol {
00723     public:
00724         static const uint8_t MSG_HDR_SENSOR_DATA = '$';
00725         static const uint8_t MSG_HDR_COMMAND     = '@';
00726         static const uint8_t MSG_HDR_RESPONSE    = '~';
00727         static const uint8_t MSG_CRC_DELIMITER   = '*';
00728         static const uint8_t MSG_TAIL_CR         = '\r';
00729         static const uint8_t MSG_TAIL_LF         = '\n';
00730 
00731     private:
00732         FrameBuffer frame_buffer;
00733         bool debug;
00734 
00735     public:
00736         iAsciiProtocol(): debug(DEBUG_ASCII_PROTOCOL)
00737         {}
00738         virtual ~iAsciiProtocol() {}
00739 
00740     protected:
00741         void push_byte(unsigned char c) {
00742             switch(c) {
00743                 // start of frame
00744                 case MSG_HDR_SENSOR_DATA:
00745                 case MSG_HDR_RESPONSE:
00746                 case MSG_HDR_COMMAND:
00747                     frame_buffer.reset();
00748                     frame_buffer.push(c);
00749                     break;
00750 
00751                 // end of frame
00752                 case MSG_TAIL_LF:
00753                         if(frame_buffer.offset > 0) {
00754                                 parse_message(reinterpret_cast<const char*>(frame_buffer.buffer));
00755                         }
00756                     frame_buffer.reset();
00757                     break;
00758 
00759                 case MSG_TAIL_CR:
00760                     // nothing to do
00761                     break;
00762 
00763                 default:
00764                     frame_buffer.push(c);
00765             }
00766         }
00767 
00768         virtual void update_attributes(std::vector<std::string>& tokens) = 0;
00769 
00770     private:
00771         bool parse_message(const char* ascii_frame) {
00772             DBG_PRINTF(debug, "## ASC FRAME : [%s]\n", ascii_frame);
00773 
00774             std::vector<std::string> tokens;
00775             if(StringUtil::split(tokens, ascii_frame, '*') != 2) {
00776                 return false;
00777             }
00778 
00779             std::string& str_message = tokens[0];
00780             int crc_from_sensor = std::stoul(tokens[1].c_str(), nullptr, 16);
00781 
00782             uint8_t crc_calc = 0;
00783             for(size_t i=0; i<str_message.length(); i++) {
00784                 crc_calc ^= str_message[i];
00785             }
00786 
00787             DBG_PRINTF(debug, "\t= MSG %s, CRC %X, CRC_C %X\n", tokens[0].c_str(), crc_from_sensor, crc_calc);
00788 
00789             if(crc_calc == crc_from_sensor) {
00790                 StringUtil::split(tokens, str_message.c_str(), ',');
00791                 update_attributes(tokens);
00792                 return true;
00793             }
00794             else {
00795                 return false;
00796             }
00797         }
00798     };
00799 
00800     /**************************************************************************
00801      *
00802      * COMMUNICATION PROTOCOL (BINARY)
00803      *
00804      **************************************************************************/
00805 
00806     class FilterByteStuffing
00807     {
00808     public:
00809         enum {
00810             STX = 0x02,
00811             ETX = 0x03,
00812             DLE = 0x10,
00813         };
00814 
00815         enum ReturnCode {
00816             STATE_NOP = 0,
00817             STATE_BUSY,
00818             STATE_COMPLETE, // RECEIVE COMPLETE
00819             STATE_ERROR,
00820         };
00821 
00822     private:
00823         bool state_receiving;
00824         ReturnCode last_state;
00825 
00826         FrameBuffer& stream;
00827         uint8_t crc_calc;
00828         uint16_t accumulater;
00829 
00830         bool debug;
00831 
00832         ReturnCode (FilterByteStuffing::*receiver)(uint8_t);
00833 
00834     public:
00835         FilterByteStuffing(FrameBuffer& s)
00836         : stream(s), crc_calc(0), accumulater(0)
00837         , state_receiving(false), last_state(STATE_NOP)
00838         , debug(DEBUG_BINARY_PROTOCOL)
00839         {
00840             receiver = &FilterByteStuffing::state_data;
00841         }
00842 
00843         ~FilterByteStuffing() {}
00844 
00845         ReturnCode operator ()(uint8_t byte) {
00846             DBG_PRINTF(debug, "new byte %02X\n", byte);
00847             last_state = (this->*receiver)(byte);
00848             return last_state;
00849         }
00850 
00851         bool is_busy() {
00852             return (last_state==STATE_BUSY);
00853         }
00854 
00855     private:
00856         void clear_all_states() {
00857             state_receiving = false;
00858             stream.reset();
00859             crc_calc = 0;
00860             accumulater = 0;
00861         }
00862 
00863         bool check_crc() {
00864             uint8_t crc_rcv = accumulater & 0x00FF;
00865             DBG_PRINTF(debug, "### CRC_R %02X, CRC_C %02X\n", crc_rcv, crc_calc);
00866             return crc_rcv == crc_calc;
00867         }
00868 
00869         void push_data(uint8_t byte) {
00870             stream.push(byte);
00871 
00872             accumulater <<= 8;
00873             accumulater |= byte;
00874             uint8_t prv_byte = ((accumulater & 0xFF00) >> 8);
00875             crc_calc ^= prv_byte;
00876         }
00877 
00878         ReturnCode state_data(uint8_t byte) {
00879             if(byte == DLE) {
00880                 receiver = &FilterByteStuffing::state_control;
00881                 return STATE_BUSY;
00882             }
00883             else {
00884                 if(state_receiving) {
00885                     push_data(byte);
00886                     return STATE_BUSY;
00887                 }
00888                 else {
00889                     return STATE_NOP;
00890                 }
00891             }
00892         }
00893 
00894         ReturnCode state_control(uint8_t byte) {
00895             ReturnCode res;
00896 
00897             switch(byte) {
00898                 case STX:
00899                     clear_all_states();
00900                     state_receiving = true;
00901                     res = STATE_BUSY;
00902                     break;
00903 
00904                 case ETX:
00905                     state_receiving = false;
00906                     res = check_crc() ? STATE_COMPLETE : STATE_ERROR;
00907                     break;
00908 
00909                 case DLE:
00910                     push_data(byte);
00911                     res = STATE_BUSY;
00912                     break;
00913 
00914                 default:
00915                     clear_all_states();
00916                     state_receiving = true;
00917                     res = STATE_ERROR;
00918             }
00919 
00920             receiver = &FilterByteStuffing::state_data;
00921             return res;
00922         }
00923     }; // FilterDleToPlain
00924 
00925 
00926     class iNodeParser
00927     {
00928     public:
00929         enum Tag {
00930             // value type
00931             TAG_TYPE_NONE     =  0,
00932             TAG_TYPE_INT8     =  1,
00933             TAG_TYPE_UINT8    =  2,
00934             TAG_TYPE_INT16    =  3,
00935             TAG_TYPE_UINT16   =  4,
00936             TAG_TYPE_INT32    =  5,
00937             TAG_TYPE_UINT32   =  6,
00938             TAG_TYPE_INT64    =  7,
00939             TAG_TYPE_UINT64   =  8,
00940             TAG_TYPE_FLOAT32  =  9,
00941             TAG_TYPE_FLOAT64  =  10,
00942             TAG_TYPE_STRING   =  11,
00943 
00944             // node attribute
00945             TAG_HAS_LEAF_NODES  =  (0x01<<7),
00946             TAG_NEXT_NODE_EXIST =  (0x01<<6),
00947             TAG_LIST_NODE       =  (0x01<<5),
00948 
00949             TAG_TYPE_MASK       =  0x0F,
00950         };
00951 
00952     protected:
00953         struct Varient {
00954             Varient() : type(TAG_TYPE_NONE) {}
00955             uint8_t type;
00956             union {
00957                  int8_t    i8;
00958                 uint8_t   ui8;
00959                  int16_t  i16;
00960                 uint16_t ui16;
00961                  int32_t  i32;
00962                 uint32_t ui32;
00963                  int64_t  i64;
00964                 uint64_t ui64;
00965                 float     f32;
00966                 double    f64;
00967             } value;
00968 
00969             template <typename T>
00970             bool set(uint8_t t, T v) {
00971                 type = t;
00972                 switch(type) {
00973                     case TAG_TYPE_INT8:     value.i8   =   (int8_t)v; break;
00974                     case TAG_TYPE_UINT8:    value.ui8  =  (uint8_t)v; break;
00975                     case TAG_TYPE_INT16:    value.i16  =  (int16_t)v; break;
00976                     case TAG_TYPE_UINT16:   value.ui16 = (uint16_t)v; break;
00977                     case TAG_TYPE_INT32:    value.i32  =  (int32_t)v; break;
00978                     case TAG_TYPE_UINT32:   value.ui32 = (uint32_t)v; break;
00979                     case TAG_TYPE_INT64:    value.i64  =  (int64_t)v; break;
00980                     case TAG_TYPE_UINT64:   value.ui64 = (uint64_t)v; break;
00981                     case TAG_TYPE_FLOAT32:  value.f32  =    (float)v; break;
00982                     case TAG_TYPE_FLOAT64:  value.f64  =   (double)v; break;
00983                     default: return false;
00984                 }
00985                 return true;
00986             }
00987         };
00988 
00989     public:
00990         struct Node {
00991             std::string name;
00992             std::vector<Varient> list;
00993         };
00994 
00995     private:
00996         struct Stream {
00997             unsigned char* buffer;
00998             size_t pos;
00999             size_t length;
01000             bool debug;
01001 
01002             Stream(unsigned char* s, size_t l) : buffer(s), length(l), pos(0), debug(DEBUG_BINARY_PROTOCOL) {
01003                 print_buffer();
01004             }
01005 
01006             int getc() {
01007                 if(pos < length) { return buffer[pos++]; }
01008                 else { return -1; }
01009             }
01010 
01011             int peek() {
01012                 if(pos < length) { return buffer[pos]; }
01013                 else { return -1; }
01014             }
01015 
01016             template <typename T>
01017             void read_value(T& value) {
01018                 T* v = (T*)(&buffer[pos]);
01019                 pos += sizeof(T);
01020                 value = *v;
01021             }
01022 
01023             bool read_value(uint8_t value_type, Varient& v) {
01024                 switch(value_type) {
01025                     case TAG_TYPE_INT8:    {  int8_t value; read_value(value); v.set(value_type, value);} break;
01026                     case TAG_TYPE_UINT8:   { uint8_t value; read_value(value); v.set(value_type, value);} break;
01027                     case TAG_TYPE_INT16:   { int16_t value; read_value(value); v.set(value_type, value);} break;
01028                     case TAG_TYPE_UINT16:  {uint16_t value; read_value(value); v.set(value_type, value);} break;
01029                     case TAG_TYPE_INT32:   { int32_t value; read_value(value); v.set(value_type, value);} break;
01030                     case TAG_TYPE_UINT32:  {uint32_t value; read_value(value); v.set(value_type, value);} break;
01031                     case TAG_TYPE_INT64:   { int64_t value; read_value(value); v.set(value_type, value);} break;
01032                     case TAG_TYPE_UINT64:  {uint64_t value; read_value(value); v.set(value_type, value);} break;
01033                     case TAG_TYPE_FLOAT32: {   float value; read_value(value); v.set(value_type, value);} break;
01034                     case TAG_TYPE_FLOAT64: {  double value; read_value(value); v.set(value_type, value);} break;
01035                     default: return false;
01036                 }
01037                 return true;
01038             }
01039 
01040             void read_list(uint8_t value_type, std::vector<Varient>& list, size_t count) {
01041                 Varient v;
01042                 for(size_t i=0; i<count; i++) {
01043                     if(read_value(value_type, v) == true) {
01044                         list.push_back(v);
01045                     }
01046                 }
01047             }
01048 
01049             std::string read_string() {
01050                 std::string str((const char*)&buffer[pos]);
01051                 pos += str.length() + 1; // '\0'
01052                 return str;
01053             }
01054 
01055         private:
01056             void print_buffer() {
01057                 if(debug) {
01058                     for(size_t i=0; i<length; i++) {
01059                         DBG_PRINTF(debug, "%02X ", buffer[i]);
01060                     }
01061                     DBG_PRINTF(debug, "\n");
01062                 }
01063             }
01064         };
01065 
01066         Stream istream;
01067         bool debug;
01068 
01069         std::vector<Node> node_list;
01070 
01071     public:
01072         iNodeParser(unsigned char* stream=0, size_t stream_len=0) : istream(stream, stream_len), debug(false){}
01073         virtual ~iNodeParser() {}
01074 
01075         void parse() {
01076             read_nodes();
01077             new_node(node_list);
01078         }
01079 
01080         virtual void new_node(std::vector<Node>& node_list) = 0;
01081 
01082     private:
01083         void read_nodes() {
01084             if(istream.length == 0 || istream.peek() < 0) {
01085                 return;
01086             }
01087 
01088             uint8_t tag = istream.getc();
01089             uint8_t type_of_value = (tag & TAG_TYPE_MASK);
01090 
01091             Node node;
01092             node.name = istream.read_string();
01093             if(type_of_value) {
01094                 if(tag&TAG_LIST_NODE) {
01095                     uint16_t count = 0;
01096                     istream.read_value(count);
01097                     istream.read_list(type_of_value, node.list, count);
01098                 }
01099                 else {
01100                     Varient value;
01101                     istream.read_value(type_of_value, value);
01102                     node.list.push_back(value);
01103                 }
01104             }
01105 
01106             node_list.push_back(node);
01107 
01108             if((tag & TAG_HAS_LEAF_NODES) || (tag & TAG_NEXT_NODE_EXIST)) {
01109                 read_nodes();
01110             }
01111         }
01112     };
01113 
01114 
01115     class iBinaryProtocol {
01116         FilterByteStuffing filter_byte_stuffing;
01117         FrameBuffer binary_stream;
01118 
01119         class BinaryNodeParser : public iNodeParser
01120         {
01121             iBinaryProtocol* protocol;
01122 
01123         public:
01124             BinaryNodeParser(iBinaryProtocol* s, unsigned char* stream, size_t stream_len) : protocol(s), iNodeParser(stream, stream_len) {}
01125             void new_node(std::vector<Node>& node_list) {
01126                 protocol->update_attributes(node_list);
01127             }
01128         };
01129 
01130     public:
01131         iBinaryProtocol() : filter_byte_stuffing(binary_stream) {}
01132         virtual ~iBinaryProtocol() {}
01133 
01134     protected:
01135         void push_byte(unsigned char c) {
01136             if(filter_byte_stuffing(c) == FilterByteStuffing::STATE_COMPLETE) {
01137                 BinaryNodeParser parser(this, binary_stream.buffer, binary_stream.offset);
01138                 parser.parse();
01139             }
01140         }
01141 
01142         bool is_receiving() {
01143             return filter_byte_stuffing.is_busy();
01144         }
01145 
01146         virtual void update_attributes(std::vector<iNodeParser::Node>& node_list) = 0;
01147 
01148     }; // BinaryProtocol
01149 
01150 
01151     /**************************************************************************
01152      *
01153      * COMMUNICATION PROTOCOL
01154      *
01155      **************************************************************************/
01156 
01157     class iProtocol : public iAsciiProtocol, public iBinaryProtocol
01158     {
01159     public:
01160         iProtocol(){}
01161         virtual ~iProtocol() {}
01162 
01163         bool feed(unsigned char* data, int data_len) {
01164             if(!data || data_len <= 0) {
01165                 return false;
01166             }
01167 
01168             for(int i=0; i<data_len; i++) {
01169                 iBinaryProtocol::push_byte(data[i]);
01170                 if(iBinaryProtocol::is_receiving() == false) {
01171                     iAsciiProtocol::push_byte(data[i]);
01172                 }
01173             }
01174 
01175             return true;
01176         }
01177     };
01178 
01179     /**************************************************************************
01180      *
01181      * ATTITUDE REPRESENTATIONS
01182      *
01183      **************************************************************************/
01184 
01185     struct EulerAngle
01186     {
01187         double roll, pitch, yaw;
01188 
01189         EulerAngle(double r=0, double p=0, double y=0) : roll(r), pitch(p), yaw(y) {}
01190         EulerAngle(std::string str_rpy, char delimiter=' ') {
01191             set(str_rpy, delimiter);
01192         }
01193 
01194         inline void reset() {
01195             set(0, 0, 0);
01196         }
01197 
01198         inline void set(double r, double p, double y) {
01199             roll=r, pitch=p, yaw=y;
01200         }
01201 
01202         inline void set(std::string str_rpy, char delimiter=' ') {
01203             std::vector<std::string> tokens;
01204             if(StringUtil::split(tokens, str_rpy.c_str(), delimiter) == 3) {
01205                 set(tokens);
01206             }
01207             else {
01208                 throw(myAhrsException("EulerAngle: Invalid String"));
01209             }
01210         }
01211 
01212         inline void set(std::vector<std::string>& str_array) {
01213             if(str_array.size() != 3) {
01214                 throw(myAhrsException("EulerAngle: size error"));
01215             }
01216             roll  = atof(str_array[0].c_str());
01217             pitch = atof(str_array[1].c_str());
01218             yaw   = atof(str_array[2].c_str());
01219         }
01220 
01221         inline std::string to_string() {
01222             std::stringstream s;
01223             s << roll <<", "<< pitch <<", "<< yaw;
01224             return s.str();
01225         }
01226     };
01227 
01228     struct Quaternion;
01229     struct DirectionCosineMatrix
01230     {
01231         double mat[9];
01232 
01233         DirectionCosineMatrix() {
01234             reset();
01235         }
01236 
01237         DirectionCosineMatrix(double dcm[9]) {
01238             set(dcm);
01239         }
01240 
01241         DirectionCosineMatrix(double& m11, double& m12, double& m13,
01242                   double& m21, double& m22, double& m23,
01243                   double& m31, double& m32, double& m33) {
01244             set(m11, m12, m13, m21, m22, m23, m31, m32, m33);
01245         }
01246 
01247         DirectionCosineMatrix(std::string str_mat, char delimiter=' ') {
01248             set(str_mat, delimiter);
01249         }
01250 
01251         inline void reset() {
01252             memset(mat, 0, sizeof(mat));
01253         }
01254 
01255         inline void set(double dcm[9]) {
01256             memcpy(mat, dcm, sizeof(mat));
01257         }
01258 
01259         inline void set(double& m11, double& m12, double& m13,
01260                         double& m21, double& m22, double& m23,
01261                         double& m31, double& m32, double& m33) {
01262             mat[0] = m11, mat[1] = m12, mat[2] = m13,
01263             mat[3] = m21, mat[4] = m22, mat[5] = m23,
01264             mat[6] = m31, mat[7] = m32, mat[8] = m33;
01265         }
01266 
01267         inline void set(std::string str_mat, char delimiter=' ') {
01268             std::vector<std::string> tokens;
01269             if(StringUtil::split(tokens, str_mat.c_str(), delimiter) == 9) {
01270                 set(tokens);
01271             }
01272             else {
01273                 throw(myAhrsException("Matrix3x3: Invalid String"));
01274             }
01275         }
01276 
01277         inline void set(std::vector<std::string>& str_array) {
01278             if(str_array.size() != 9) {
01279                 throw(myAhrsException("Matrix3x3: size error"));
01280             }
01281             for(int i=0; i<9; i++) {
01282                 mat[i] = (double)atof(str_array[i].c_str());
01283             }
01284         }
01285 
01286         inline std::string to_string() {
01287             std::vector<std::string> temp;
01288             StringUtil::to_string_list(temp, mat, 9);
01289             return StringUtil::join(temp, ", ");
01290         }
01291 
01292         EulerAngle to_euler_angle() {
01293             EulerAngle e;
01294             double RAD2DEG = 180/M_PI;
01295             e.roll  = atan2(MAT(1, 2), MAT(2, 2))*RAD2DEG;
01296             e.pitch = -asin(MAT(0, 2))*RAD2DEG;
01297             e.yaw   = atan2(MAT(0, 1), MAT(0, 0))*RAD2DEG;
01298             return e;
01299         }
01300 
01301 #if 0
01302         void set(Quaternion& q) {
01303             // http://www.mathworks.co.kr/kr/help/aeroblks/quaternionstodirectioncosinematrix.html
01304             double xx = q.x*q.x;
01305             double xy = q.x*q.y;
01306             double xz = q.x*q.z;
01307             double xw = q.x*q.w;
01308             double yy = q.y*q.y;
01309             double yz = q.y*q.z;
01310             double yw = q.y*q.w;
01311             double zz = q.z*q.z;
01312             double zw = q.z*q.w;
01313             double ww = q.w*q.w;
01314 
01315             mat[0] =  xx - yy - zz + ww;
01316             mat[1] = 2.0*(xy + zw);
01317             mat[2] = 2.0*(xz - yw);
01318 
01319             mat[3] = 2.0*(xy - zw);
01320             mat[4] = -xx + yy - zz + ww;
01321             mat[5] = 2.0*(yz + xw);
01322 
01323             mat[6] = 2.0*(xz + yw);
01324             mat[7] = 2.0*(yz - xw);
01325             mat[8] = -xx - yy + zz + ww;
01326         }
01327 #else
01328         void set(Quaternion& q);
01329 #endif
01330 
01331     private:
01332         inline double MAT(unsigned int row, unsigned int col) {
01333             return mat[(row)*3 + col];
01334         }
01335     };
01336 
01337 
01338     struct Quaternion
01339     {
01340         double x, y, z, w;
01341 
01342         Quaternion(double _x=0, double _y=0, double _z=0, double _w=1): x(_x), y(_y), z(_z), w(_w) {}
01343         Quaternion(std::string str_xyzw, char delimiter=' ') {
01344             set(str_xyzw, delimiter);
01345         }
01346 
01347         inline void reset() {
01348             set(0, 0, 0, 1);
01349         }
01350 
01351         inline void set(double _x, double _y, double _z, double _w) {
01352             x=_x, y=_y, z=_z, w=_w;
01353         }
01354 
01355         inline void set(std::string str_xyzw, char delimiter=' ') {
01356             std::vector<std::string> tokens;
01357             if(StringUtil::split(tokens, str_xyzw.c_str(), delimiter) == 4) {
01358                 set(tokens);
01359             }
01360             else {
01361                 throw(myAhrsException("Quaternion: Invalid String"));
01362             }
01363         }
01364 
01365         inline void set(std::vector<std::string>& str_array) {
01366             if(str_array.size() != 4) {
01367                 throw(myAhrsException("Quaternion: size error"));
01368             }
01369             x = atof(str_array[0].c_str());
01370             y = atof(str_array[1].c_str());
01371             z = atof(str_array[2].c_str());
01372             w = atof(str_array[3].c_str());
01373         }
01374 
01375         inline std::string to_string() {
01376             std::stringstream s;
01377             s << x <<", "<< y <<", "<< z <<", "<< w;
01378             return s.str();
01379         }
01380 
01381         void normalize() {
01382             double norm = sqrt(x*x + y*y + z*z + w*w);
01383             x = x/norm;
01384             y = y/norm;
01385             z = z/norm;
01386             w = w/norm;
01387         }
01388 
01389         Quaternion conj() {
01390             Quaternion q;
01391             q.x = -x;
01392             q.y = -y;
01393             q.z = -z;
01394             q.w = w;
01395             return q;
01396         }
01397 
01398         // http://www.mathworks.co.kr/kr/help/aerotbx/ug/quatmultiply.html
01399         // qxr = q*r
01400         static Quaternion product(Quaternion& q, Quaternion& r) {
01401             Quaternion qxr;
01402 
01403             qxr.w = r.w*q.w - r.x*q.x - r.y*q.y - r.z*q.z;
01404             qxr.x = r.w*q.x + r.x*q.w - r.y*q.z + r.z*q.y;
01405             qxr.y = r.w*q.y + r.x*q.z + r.y*q.w - r.z*q.x;
01406             qxr.z = r.w*q.z - r.x*q.y + r.y*q.x + r.z*q.w;
01407 
01408             return qxr;
01409         }
01410 
01411         EulerAngle to_euler_angle() {
01412             double xx = x*x;
01413             double xy = x*y;
01414             double xz = x*z;
01415             double xw = x*w;
01416             double yy = y*y;
01417             double yz = y*z;
01418             double yw = y*w;
01419             double zz = z*z;
01420             double zw = z*w;
01421             double ww = w*w;
01422 
01423             double RAD2DEG = 180/M_PI;
01424             EulerAngle e;
01425             e.roll  = atan2(2.0*(yz + xw), -xx - yy + zz + ww)*RAD2DEG;
01426             e.pitch = -asin(2.0*(xz - yw))*RAD2DEG;
01427             e.yaw   = atan2(2.0*(xy + zw), xx - yy - zz + ww)*RAD2DEG;
01428             return e;
01429         }
01430 
01431         DirectionCosineMatrix to_dcm() {
01432             // http://www.mathworks.co.kr/kr/help/aeroblks/quaternionstodirectioncosinematrix.html
01433             double xx = x*x;
01434             double xy = x*y;
01435             double xz = x*z;
01436             double xw = x*w;
01437             double yy = y*y;
01438             double yz = y*z;
01439             double yw = y*w;
01440             double zz = z*z;
01441             double zw = z*w;
01442             double ww = w*w;
01443 
01444             DirectionCosineMatrix dcm;
01445 
01446             dcm.mat[0] =  xx - yy - zz + ww;
01447             dcm.mat[1] = 2.0*(xy + zw);
01448             dcm.mat[2] = 2.0*(xz - yw);
01449 
01450             dcm.mat[3] = 2.0*(xy - zw);
01451             dcm.mat[4] = -xx + yy - zz + ww;
01452             dcm.mat[5] = 2.0*(yz + xw);
01453 
01454             dcm.mat[6] = 2.0*(xz + yw);
01455             dcm.mat[7] = 2.0*(yz - xw);
01456             dcm.mat[8] = -xx - yy + zz + ww;
01457 
01458             return dcm;
01459         }
01460     };
01461 
01462     void DirectionCosineMatrix::set(Quaternion& q) {
01463         *this = q.to_dcm();
01464     }
01465 
01466 
01467     /**************************************************************************
01468      *
01469      * IMU
01470      *
01471      **************************************************************************/
01472     template <typename Type>
01473     struct ImuData
01474     {
01475         Type ax, ay, az, gx, gy, gz, mx, my, mz, temperature;
01476 
01477         ImuData() {
01478             ax = ay = az = gx = gy = gz = mx = my = mz = temperature = 0;
01479         }
01480 
01481         ImuData(Type data[10]) {
01482             set(data);
01483         }
01484 
01485         inline void reset() {
01486             Type d[10];
01487             memset(d, 0, sizeof(d));
01488             set(d);
01489         }
01490 
01491         inline void set(Type data[10]) {
01492             int i=0;
01493             ax = data[i++];
01494             ay = data[i++];
01495             az = data[i++];
01496 
01497             gx = data[i++];
01498             gy = data[i++];
01499             gz = data[i++];
01500 
01501             mx = data[i++];
01502             my = data[i++];
01503             mz = data[i++];
01504 
01505             temperature = data[i++];
01506         }
01507 
01508         inline void set(std::string str_mat, char delimiter=' ') {
01509             std::vector<std::string> tokens;
01510             if(StringUtil::split(tokens, str_mat.c_str(), delimiter) == 10) {
01511                 set(tokens);
01512             }
01513             else {
01514                 throw(myAhrsException("imu: Invalid String"));
01515             }
01516         }
01517 
01518         inline void set(std::vector<std::string>& str_array) {
01519             if(str_array.size() != 10) {
01520                 throw(myAhrsException("imu: size error"));
01521             }
01522             Type data[10];
01523             for(int i=0; i<10; i++) {
01524                 data[i] = (Type)atof(str_array[i].c_str());
01525             }
01526             set(data);
01527         }
01528 
01529         inline std::string to_string() {
01530             std::stringstream s;
01531             s << ax <<", "<<ay<<", "<<az<<", "<<gx<<", "<<gy<<", "<<gz<<", "<<mx<<", "<<my<<", "<<mz<<", "<<temperature;
01532             return s.str();
01533         }
01534     };
01535 
01536 
01537     /**************************************************************************
01538      *
01539      * AHRS
01540      *
01541      **************************************************************************/
01542 
01543     enum Attitude {
01544         NOT_DEF_ATTITUDE,
01545         QUATERNION,
01546         EULER_ANGLE,
01547     };
01548 
01549     enum Imu {
01550         NOT_DEF_IMU,
01551         COMPENSATED,
01552         RAW,
01553     };
01554 
01555     struct SensorData {
01556         int            sequence_number;
01557 
01558         Attitude       attitude_type;
01559         EulerAngle     euler_angle; // degree
01560         Quaternion     quaternion;
01561 
01562         Imu            imu_type;
01563         ImuData<int>   imu_rawdata;
01564         ImuData<float> imu;
01565 
01566         SensorData() {
01567             reset();
01568         }
01569 
01570         void reset() {
01571             sequence_number = -1;
01572             euler_angle.reset();
01573             quaternion.reset();
01574             imu_rawdata.reset();
01575             imu.reset();
01576             attitude_type = NOT_DEF_ATTITUDE;
01577             imu_type = NOT_DEF_IMU;
01578         }
01579 
01580         void update_attitude(EulerAngle& e) {
01581             euler_angle = e;
01582             attitude_type = EULER_ANGLE;
01583         }
01584 
01585         void update_attitude(Quaternion& q) {
01586             quaternion = q;
01587             attitude_type = QUATERNION;
01588         }
01589 
01590         void update_imu(ImuData<int>& i) {
01591             imu_rawdata = i;
01592             imu_type = RAW;
01593         }
01594 
01595         void update_imu(ImuData<float>& i) {
01596             imu = i;
01597             imu_type = COMPENSATED;
01598         }
01599 
01600         std::string to_string() {
01601             std::vector<std::string> str_array;
01602             char temp[32];
01603             sprintf(temp, "%d", sequence_number);
01604             str_array.push_back("sequence = " + std::string(temp));
01605 
01606             switch(attitude_type) {
01607             case EULER_ANGLE:
01608                 str_array.push_back("euler_angle = " + euler_angle.to_string());
01609                 break;
01610             case QUATERNION:
01611                 str_array.push_back("quaternion = " + quaternion.to_string());
01612                 break;
01613             default:
01614                 str_array.push_back("no attitude ");
01615                 break;
01616             }
01617 
01618             switch(imu_type) {
01619             case RAW:
01620                 str_array.push_back("imu_raw = " + imu_rawdata.to_string());
01621                 break;
01622             case COMPENSATED:
01623                 str_array.push_back("imu_comp = " + imu.to_string());
01624                 break;
01625             default:
01626                 str_array.push_back("no imu ");
01627                 break;
01628             }
01629             return StringUtil::join(str_array, "\n");
01630         }
01631     };
01632 
01633 
01634     class iMyAhrsPlus
01635     {
01636         bool debug;
01637 
01638         Platform::SerialPort serial;
01639 
01640         Platform::Mutex mutex_attribute;
01641         Platform::Mutex mutex_communication;
01642 
01643         bool thread_receiver_ready;
01644         Platform::Thread thread_receiver;
01645 
01646         bool activate_user_event;
01647         Platform::Thread thread_event;
01648 
01649         SensorData sensor_data;
01650 
01651         int sensor_id;
01652         std::map<std::string, std::string> attribute_map;
01653 
01654         typedef bool (iMyAhrsPlus::*AscHandler)(std::vector<std::string>& tokens);
01655         std::map<std::string, AscHandler> ascii_handler_data_map;
01656 
01657         typedef bool (iMyAhrsPlus::*AscRspHandler)(std::map<std::string, std::string>& attributes);
01658         std::map<std::string, AscRspHandler> ascii_handler_rsp_map;
01659 
01660         typedef bool (iMyAhrsPlus::*BinHandler)(iNodeParser::Node& node);
01661         std::map<std::string, BinHandler> binary_handler_data_map;
01662 
01663         static const int ACCEL_RANGE  = 16;
01664         static const int GYRO_RANGE   = 2000;
01665         static const int MAGNET_RANGE = 300;
01666         static const int TEMP_RANGE   = 200;
01667         static const int EULER_RANGE  = 180;
01668 
01669         class Protocol : public iProtocol
01670         {
01671             iMyAhrsPlus* ahrs;
01672 
01673         public:
01674             Protocol(iMyAhrsPlus* s) : ahrs(s) {}
01675 
01676             void update_attributes(std::vector<std::string>& tokens) {
01677                 if(tokens.size() >= 2) {
01678                     ahrs->ascii_parse_response(tokens);
01679                 }
01680             }
01681 
01682             void update_attributes(std::vector<iNodeParser::Node>& node_list) {
01683                 if(node_list.size() > 0) {
01684                     ahrs->binary_parse_response(node_list);
01685                 }
01686             }
01687         } protocol;
01688 
01689         class ResponsQueue {
01690 
01691             Platform::Mutex lock;
01692             Platform::Event event;
01693             std::deque< std::vector<std::string> > queue;
01694 
01695         public:
01696             ResponsQueue() {}
01697             ~ResponsQueue() {}
01698 
01699             void clear() {
01700                 LockGuard _l(lock);
01701                 queue.clear();
01702             }
01703 
01704             bool wait(int timeout_msec) {
01705                 if(size() <= 0) {
01706                         return event.wait(timeout_msec);
01707                 }
01708                 else {
01709                         return true;
01710                 }
01711             }
01712 
01713             void push_back(std::vector<std::string>& list) {
01714                 LockGuard _l(lock);
01715                 queue.push_back(list);
01716                 event.set();
01717             }
01718 
01719             size_t size() {
01720                 LockGuard _l(lock);
01721                 return queue.size();
01722             }
01723 
01724             bool pop(std::vector<std::string>& out) {
01725                 LockGuard _l(lock);
01726                 if(queue.size() > 0) {
01727                     out = queue.front();
01728                     queue.pop_front();
01729                     return true;
01730                 }
01731                 else {
01732                     return false;
01733                 }
01734             }
01735         } response_message_queue;
01736 
01737         class EventItem
01738         {
01739         public:
01740             enum EventId {
01741                 NONE = 0,
01742                 EXIT,
01743                 ATTRIBUTE,
01744                 DATA,
01745             };
01746 
01747             EventId event_id;
01748 
01749             EventItem(EventId id=NONE) : event_id(id) {}
01750             virtual ~EventItem() {}
01751 
01752             virtual SensorData* get_sensor_data() { return 0; }
01753             virtual std::map<std::string, std::string>* get_attribute() { return 0; }
01754         };
01755 
01756         class EventQueue {
01757         private:
01758             class EventItemExit : public EventItem
01759             {
01760             public:
01761                 EventItemExit() : EventItem(EXIT){}
01762             };
01763 
01764             class EventItemData : public EventItem
01765             {
01766                 SensorData data;
01767 
01768             public:
01769                 EventItemData(SensorData& d) : EventItem(DATA), data(d) {}
01770                 ~EventItemData() {}
01771                 SensorData* get_sensor_data() { return &data; }
01772             };
01773 
01774             class EventItemAttribute : public EventItem
01775             {
01776                 std::map<std::string, std::string> attribute;
01777 
01778             public:
01779                 EventItemAttribute(std::map<std::string, std::string>& a) : EventItem(ATTRIBUTE), attribute(a) {}
01780                 ~EventItemAttribute() {}
01781                 std::map<std::string, std::string>* get_attribute() { return &attribute; }
01782             };
01783 
01784             std::deque<EventItem*> deque;
01785             Platform::Mutex lock;
01786             Platform::Event event;
01787 
01788             static const size_t EVENT_MAX_NUM = 5;
01789 
01790         public:
01791             EventQueue() {}
01792             ~EventQueue() {
01793                 int num = deque.size();
01794                 for(int i=0; i<num; i++) {
01795                     delete pop_event();
01796                 }
01797             }
01798 
01799             inline bool wait(int timeout_msec=-1) {
01800                 return event.wait(timeout_msec);
01801             }
01802 
01803             void push_event_exit() {
01804                 LockGuard _l(lock);
01805                 deque.push_front(new EventItemExit()); // highest priority
01806                 event.set();
01807             }
01808 
01809             void push_event_attribute_change(std::string& attr_name, std::string& attr_value) {
01810                 LockGuard _l(lock);
01811                 std::map<std::string, std::string> attribute;
01812                 attribute[attr_name] = attr_value;
01813                 deque.push_back(new EventItemAttribute(attribute));
01814                 event.set();
01815             }
01816 
01817             void push_event_data(SensorData& data) {
01818                 LockGuard _l(lock);
01819                 if(deque.size() < EVENT_MAX_NUM) {
01820                     deque.push_back(new EventItemData(data));
01821                 }
01822                 event.set();
01823             }
01824 
01825             EventItem* pop_event() {
01826                 LockGuard _l(lock);
01827                 EventItem* i = 0;
01828                 if(deque.size() > 0) {
01829                     i = deque.front();
01830                     deque.pop_front();
01831                 }
01832                 return i;
01833             }
01834         } event_queue;
01835 
01836         // prevent copy
01837         iMyAhrsPlus(iMyAhrsPlus& rhs):protocol(this) {}
01838 
01839     public:
01840         iMyAhrsPlus(std::string port_name="", unsigned int baudrate=115200)
01841         : serial(port_name.c_str(), baudrate)
01842         , debug(DEBUG_MYAHRS_PLUS)
01843         , protocol(this)
01844         , sensor_id(-1)
01845         , activate_user_event(false)
01846         , thread_receiver_ready(false)
01847         {
01848             // response message parser (ascii)
01849             ascii_handler_rsp_map[std::string("~trig")]        = &iMyAhrsPlus::ascii_rsp_trigger;
01850             ascii_handler_rsp_map[std::string("~ping")]        = &iMyAhrsPlus::ascii_rsp_ping;
01851             ascii_handler_rsp_map[std::string("~divider")]     = &iMyAhrsPlus::ascii_rsp_divider;
01852             ascii_handler_rsp_map[std::string("~mode")]        = &iMyAhrsPlus::ascii_rsp_mode;
01853             ascii_handler_rsp_map[std::string("~asc_out")]     = &iMyAhrsPlus::ascii_rsp_asc_out;
01854             ascii_handler_rsp_map[std::string("~bin_out")]     = &iMyAhrsPlus::ascii_rsp_bin_out;
01855             ascii_handler_rsp_map[std::string("~set_offset")]  = &iMyAhrsPlus::ascii_rsp_user_orientation;
01856             ascii_handler_rsp_map[std::string("~clr_offset")]  = &iMyAhrsPlus::ascii_rsp_user_orientation;
01857             ascii_handler_rsp_map[std::string("~calib")]       = &iMyAhrsPlus::ascii_rsp_calib;
01858             ascii_handler_rsp_map[std::string("~factory")]     = &iMyAhrsPlus::ascii_rsp_factory;
01859             ascii_handler_rsp_map[std::string("~stat")]        = &iMyAhrsPlus::ascii_rsp_stat;
01860             ascii_handler_rsp_map[std::string("~version")]     = &iMyAhrsPlus::ascii_rsp_version;
01861             ascii_handler_rsp_map[std::string("~id")]          = &iMyAhrsPlus::ascii_rsp_id;
01862             ascii_handler_rsp_map[std::string("~sn")]          = &iMyAhrsPlus::ascii_rsp_serial_number;
01863             ascii_handler_rsp_map[std::string("~sensitivity")] = &iMyAhrsPlus::ascii_rsp_sensitivity;
01864             ascii_handler_rsp_map[std::string("~baudrate")]    = &iMyAhrsPlus::ascii_rsp_baudrate;
01865             ascii_handler_rsp_map[std::string("~save")]        = &iMyAhrsPlus::ascii_rsp_save;
01866 
01867             // data message (ascii)
01868             ascii_handler_data_map[std::string("$RPY")]        = &iMyAhrsPlus::ascii_update_euler;
01869             ascii_handler_data_map[std::string("$QUAT")]       = &iMyAhrsPlus::ascii_update_quaternion;
01870             ascii_handler_data_map[std::string("$RPYIMU")]     = &iMyAhrsPlus::ascii_update_rpyimu;
01871             ascii_handler_data_map[std::string("$QUATIMU")]    = &iMyAhrsPlus::ascii_update_quatimu;
01872             ascii_handler_data_map[std::string("$RIIMU")]      = &iMyAhrsPlus::ascii_update_riimu;
01873             ascii_handler_data_map[std::string("$IMU")]        = &iMyAhrsPlus::ascii_update_imu;
01874 
01875             // data node (binary)
01876             static const char* NAME_DATA_ROOT  = "d";
01877             static const char* NAME_RIIMU      = "r";
01878             static const char* NAME_IMU        = "i";
01879             static const char* NAME_EULER      = "e";
01880             static const char* NAME_QUATERNION = "q";
01881             static const char* NAME_DCM        = "c";
01882             static const char* NAME_SEQUANCE   = "s";
01883 
01884             binary_handler_data_map[std::string(NAME_SEQUANCE)]   = &iMyAhrsPlus::binary_update_sequence;
01885             binary_handler_data_map[std::string(NAME_EULER)]      = &iMyAhrsPlus::binary_update_euler;
01886             binary_handler_data_map[std::string(NAME_QUATERNION)] = &iMyAhrsPlus::binary_update_quaternion;
01887             binary_handler_data_map[std::string(NAME_IMU)]        = &iMyAhrsPlus::binary_update_imu;
01888             binary_handler_data_map[std::string(NAME_RIIMU)]      = &iMyAhrsPlus::binary_update_riimu;
01889 
01890             thread_event.start(thread_proc_callback, (void*)this);
01891         }
01892 
01893         virtual ~iMyAhrsPlus() {
01894             event_queue.push_event_exit();
01895             stop();
01896             thread_event.join();
01897         }
01898 
01899         const char* sdk_version() {
01900             return WITHROBOT_MYAHRS_PLUS_SDK_VERSION;
01901         }
01902 
01903         bool start(std::string port_name="", int baudrate=-1) {
01904             {
01905                 LockGuard _l(mutex_communication);
01906                 if(port_name == "" || baudrate < 0) {
01907                     if(serial.Open() == false) {
01908                         return false;
01909                     }
01910                 }
01911                 else {
01912                     if(serial.Open(port_name.c_str(), baudrate) == false) {
01913                         return false;
01914                     }
01915                 }
01916 
01917                 serial.Flush();
01918 
01919                 thread_receiver_ready = false;
01920                 if(thread_receiver.start(thread_proc_receiver, (void*)this) == false) {
01921                     return false;
01922                 }
01923 
01924                 while(thread_receiver_ready == false) {
01925                     Platform::msleep(10);
01926                 }
01927             }
01928 
01929             for(int i=0; i<3; i++) {
01930                 cmd_ping(1000);
01931             }
01932 
01933             activate_user_event = resync();
01934             return activate_user_event;
01935         }
01936 
01937         void stop() {
01938             LockGuard _l(mutex_communication);
01939             clear_all_attribute();
01940             activate_user_event = false;
01941             serial.Close();
01942             thread_receiver.join();
01943         }
01944 
01945         inline int get_sensor_id() {
01946             LockGuard _l(mutex_attribute);
01947             return sensor_id;
01948         }
01949 
01950         inline SensorData get_data() {
01951             LockGuard _l(mutex_attribute);
01952             return sensor_data;
01953         }
01954 
01955         inline void get_data(SensorData& data) {
01956             LockGuard _l(mutex_attribute);
01957             data = sensor_data;
01958         }
01959 
01960         /*
01961          *  access attributes
01962          */
01963         bool get_attribute(const char* attrib_name, std::string& attrib_value) {
01964             LockGuard _l(mutex_attribute);
01965 
01966             std::string attribute_name(attrib_name);
01967             std::map<std::string, std::string>::iterator it = attribute_map.find(attribute_name);
01968             if(it != attribute_map.end()) {
01969                 attrib_value = it->second;
01970                 return true;
01971             }
01972             else {
01973                 return false;
01974             }
01975         }
01976 
01977     private:
01978         bool is_exist(const std::string& attribute_name) {
01979             std::map<std::string, std::string>::iterator it = attribute_map.find(attribute_name);
01980             if(it != attribute_map.end()) {
01981                 return true;
01982             }
01983             else {
01984                 return false;
01985             }
01986         }
01987 
01988         void set_attribute(const std::string& attribute_name, const std::string& value) {
01989             attribute_map[attribute_name] = value;
01990 
01991             if(activate_user_event) {
01992                 std::string attr_name = attribute_name;
01993                 std::string attr_value = value;
01994                 event_queue.push_event_attribute_change(attr_name, attr_value);
01995             }
01996         }
01997 
01998         void clear_all_attribute() {
01999             LockGuard _l(mutex_attribute);
02000             attribute_map.clear();
02001             sensor_id = -1;
02002         }
02003 
02004     public:
02005         // ########################################################################################################################
02006         // #  accel_bias : -1.334012e+01, 2.941270e+01, 1.579460e+02
02007         // #  accel_max : 16
02008         // #  accel_sensitivity : 4.882813e-04
02009         // #  accel_sensitivity_matrix : 4.888283e-04, -1.201399e-06, -4.818384e-06, 0.000000e+00, 4.901073e-04, -1.257056e-06, 0.000000e+00, 0.000000e+00, 4.853439e-04
02010         // #  ascii_format : QUATIMU
02011         // #  baudrate : 115200
02012         // #  binary_format : QUATERNION, IMU
02013         // #  build_date : Jul 12 2014 18:55:53
02014         // #  coordinate_transformation_global_to_user : 0.000000e+00, 0.000000e+00, 0.000000e+00, 1.000000e+00
02015         // #  coordinate_transformation_sensor_to_vehicle : 0.000000e+00, 0.000000e+00, 0.000000e+00, 1.000000e+00
02016         // #  divider : 1
02017         // #  firmware_version : 1.5
02018         // #  gyro_bias : -1.633780e+01, -7.488200e+00, -1.367940e+01
02019         // #  gyro_max : 2000
02020         // #  gyro_sensitivity : 6.097561e-02
02021         // #  gyro_sensitivity_matrix : 6.128651e-02, -2.204396e-04, -9.754782e-04, 1.441085e-05, 6.082033e-02, 5.099393e-04, -1.803549e-04, 7.779496e-04, 6.148182e-02
02022         // #  magnet_bias : 9.936985e+01, 1.039952e+01, -9.331067e+01
02023         // #  magnet_sensitivity_matrix : 6.128308e-01, 1.720049e-03, 9.577197e-03, 1.720049e-03, 5.859380e-01, 1.020694e-03, 9.577197e-03, 1.020694e-03, 6.279327e-01
02024         // #  max_rate : 100
02025         // #  mode : BT
02026         // #  platform : myAhrsRevC
02027         // #  product_name : myAHRS+
02028         // #  sensor_id : 0
02029         // #  sensor_serial_number : 464432970808430886
02030         // #  yaw_offset : OFF
02031         // ########################################################################################################################
02032 
02033         std::vector<std::string> get_attribute_list() {
02034             LockGuard _l(mutex_attribute);
02035             std::vector<std::string> attribute_list;
02036             for(std::map<std::string, std::string>::iterator it=attribute_map.begin(); it!=attribute_map.end(); it++) {
02037                 attribute_list.push_back(it->first);
02038             }
02039             return attribute_list;
02040         }
02041 
02042         /*
02043          * re-sync all attributes
02044          */
02045         bool resync() {
02046             bool ok = false;
02047             std::string mode;
02048 
02049             do {
02050                 if(cmd_mode() == false) {
02051                     DBG_PRINTF(true, "cmd_mode() returns false\n");
02052                     break;
02053                 }
02054                 if(get_attribute("mode", mode) == false) {
02055                     DBG_PRINTF(true, "get_attribute('mode') returns false\n");
02056                     break;
02057                 }
02058                 if(cmd_mode("T") == false) {
02059                     DBG_PRINTF(true, "cmd_mode(T) returns false\n");
02060                     break;
02061                 }
02062                 if(cmd_divider() == false) {
02063                     DBG_PRINTF(true, "cmd_divider() returns false\n");
02064                     break;
02065                 }
02066                 if(cmd_ascii_data_format() == false) {
02067                     DBG_PRINTF(true, "cmd_ascii_data_format() returns false\n");
02068                     break;
02069                 }
02070                 if(cmd_binary_data_format() == false) {
02071                     DBG_PRINTF(true, "cmd_binary_data_format() returns false\n");
02072                     break;
02073                 }
02074                 if(cmd_set_user_orientation_offset() == false) {
02075                     DBG_PRINTF(true, "cmd_set_user_orientation_offset() returns false\n");
02076                     break;
02077                 }
02078                 if(cmd_calibration_parameter('A') == false) {
02079                     DBG_PRINTF(true, "cmd_calibration_parameter(A) returns false\n");
02080                     break;
02081                 }
02082                 if(cmd_calibration_parameter('G') == false) {
02083                     DBG_PRINTF(true, "cmd_calibration_parameter(G) returns false\n");
02084                     break;
02085                 }
02086                 if(cmd_calibration_parameter('M') == false) {
02087                     DBG_PRINTF(true, "cmd_calibration_parameter(M) returns false\n");
02088                     break;
02089                 }
02090                 if(cmd_version() == false) {
02091                     DBG_PRINTF(true, "cmd_version() returns false\n");
02092                     break;
02093                 }
02094                 if(cmd_id() == false) {
02095                     DBG_PRINTF(true, "cmd_id() returns false\n");
02096                     break;
02097                 }
02098                 if(cmd_sensitivity() == false) {
02099                     DBG_PRINTF(true, "cmd_sensitivity() returns false\n");
02100                     break;
02101                 }
02102                 if(cmd_baudrate() == false) {
02103                     DBG_PRINTF(true, "cmd_baudrate() returns false\n");
02104                     break;
02105                 }
02106                 if(cmd_mode(mode.c_str()) == false) {
02107                     DBG_PRINTF(true, "cmd_mode(restore) returns false\n");
02108                     break;
02109                 }
02110 
02111                 ok = true;
02112             }while(0);
02113 
02114             if(ok == true && debug) {
02115                 DBG_PRINTF(debug, "\n\n### ATTRIBUTES #####\n");
02116                 for (std::map<std::string, std::string>::iterator it=attribute_map.begin(); it!=attribute_map.end(); ++it) {
02117                     DBG_PRINTF(debug, "\t- attribute(%s) = \"%s\"\n", it->first.c_str(), it->second.c_str());
02118                 }
02119             }
02120 
02121             if(debug && ok == false) {
02122                 Platform::msleep(100);
02123             }
02124 
02125             return ok;
02126         }
02127 
02128         /*
02129          *  myahrs_plus commands
02130          */
02131         void cmd_trigger() {
02132             // no response, no wait
02133             send_command("@trig", -1);
02134         }
02135 
02136         bool cmd_ping(int timeout_msec=500) {
02137             return send_command("@ping", timeout_msec);
02138         }
02139 
02140         bool cmd_divider(int timeout_msec=500) {
02141             return send_command("@divider", timeout_msec);
02142         }
02143 
02144         bool cmd_divider(const char* divider, int timeout_msec=500) {
02145             if(strlen(divider) > 100) {
02146                 return false;
02147             }
02148             char buf[128];
02149             sprintf(buf, "@divider,%s", divider);
02150             return send_command(buf, timeout_msec);
02151         }
02152 
02153         bool cmd_mode(const char* mode_string=0, int timeout_msec=500) {
02154             if(mode_string == 0) {
02155                 return send_command("@mode", timeout_msec);
02156             }
02157             else {
02158                 std::string command = std::string("@mode,") + std::string(mode_string);
02159                 return send_command(command.c_str(), timeout_msec);
02160             }
02161         }
02162 
02163         bool cmd_ascii_data_format(const char* asc_output=0, int timeout_msec=500) {
02164             if(asc_output == 0) {
02165                 return send_command("@asc_out", timeout_msec);
02166             }
02167             else {
02168                 std::string command = std::string("@asc_out,") + std::string(asc_output);
02169                 return send_command(command.c_str(), timeout_msec);
02170             }
02171         }
02172 
02173         bool cmd_binary_data_format(const char* bin_output=0, int timeout_msec=500) {
02174             if(bin_output == 0) {
02175                 return send_command("@bin_out", timeout_msec);
02176             }
02177             else {
02178                 std::string command = std::string("@bin_out,") + std::string(bin_output);
02179                 return send_command(command.c_str(), timeout_msec);
02180             }
02181         }
02182 
02183         bool cmd_set_user_orientation_offset(int timeout_msec=500) {
02184             return send_command("@set_offset", timeout_msec);
02185         }
02186 
02187         bool cmd_set_user_orientation_offset(const char* enable_yaw_offset, int timeout_msec=500) {
02188             std::string command = std::string("@set_offset,") + std::string(enable_yaw_offset);
02189             return send_command(command.c_str(), timeout_msec);
02190         }
02191 
02192         bool cmd_clear_user_orientation_offset(int timeout_msec=500) {
02193             return send_command("@clr_offset", timeout_msec);
02194         }
02195 
02196         bool cmd_calibration_parameter(char sensor_type, const char* calibration_parameters=0, int timeout_msec=500) {
02197             char buf[512];
02198             if(calibration_parameters == 0) {
02199                 sprintf(buf, "@calib,%c", sensor_type);
02200                 return send_command(buf, timeout_msec);
02201             }
02202             else {
02203                 if(strlen(calibration_parameters) > sizeof(buf)-20) {
02204                     return false;
02205                 }
02206                 sprintf(buf, "@calib,%c,%s", sensor_type, calibration_parameters);
02207                 return send_command(buf, timeout_msec);
02208             }
02209         }
02210 
02211         bool cmd_restore_all_default(int timeout_msec=500) {
02212             return send_command("@factory", timeout_msec);
02213         }
02214 
02215         bool cmd_version(int timeout_msec=500) {
02216             return send_command("@version", timeout_msec);
02217         }
02218 
02219         bool cmd_id(int timeout_msec=500) {
02220             return send_command("@id", timeout_msec);
02221         }
02222 
02223         bool cmd_id(const char* str_sensor_id, int timeout_msec=500) {
02224             if(strlen(str_sensor_id) > 100) {
02225                 return false;
02226             }
02227             char buf[128];
02228             sprintf(buf, "@id,%s", str_sensor_id);
02229             return send_command(buf, timeout_msec);
02230         }
02231 
02232         bool cmd_serial_number(int timeout_msec=500) {
02233             return send_command("@sn", timeout_msec);
02234         }
02235 
02236         bool cmd_sensitivity(int timeout_msec=500) {
02237             return send_command("@sensitivity", timeout_msec);
02238         }
02239 
02240         bool cmd_baudrate(int timeout_msec=500) {
02241             return send_command("@baudrate", timeout_msec);
02242         }
02243 
02244         bool cmd_baudrate(const char* baudrate, int timeout_msec=500) {
02245             if(strlen(baudrate) > 100) {
02246                 return false;
02247             }
02248             char buf[128];
02249             sprintf(buf, "@baudrate,%s", baudrate);
02250             return send_command(buf, timeout_msec);
02251         }
02252 
02253         bool cmd_save(int timeout_msec=500) {
02254             return send_command("@save", timeout_msec);
02255         }
02256 
02257     protected:
02258         /*
02259          *  Event handler interface
02260          */
02261         virtual void OnSensorData(int sensor_id, SensorData sensor_data) {}
02262         virtual void OnAttributeChange(int sensor_id, std::string attribute_name, std::string value) {}
02263 
02264     private:
02265         bool send_command(std::string command_string, int timeout_msec) {
02266             LockGuard _l(mutex_communication);
02267 
02268             DBG_PRINTF(debug, "### SEND : %s\n", command_string.c_str());
02269 
02270             uint8_t crc = 0;
02271             char crc_string[16];
02272             for(size_t i=0; i<command_string.length(); i++) {
02273                 crc ^= command_string[i];
02274             }
02275             sprintf(crc_string, "*%02X\r\n", crc);
02276             std::string command_with_crc = command_string + std::string(crc_string);
02277 
02278             /*
02279              * send command
02280              */
02281             response_message_queue.clear();
02282             if(serial.Write((unsigned char*)command_with_crc.c_str(), command_with_crc.length()) <= 0) {
02283                 DBG_PRINTF(debug, "serial.Write() return false\n");
02284                 return false;
02285             }
02286 
02287             if(timeout_msec < 0) {
02288                 // no wait
02289                 return true;
02290             }
02291 
02292                         std::vector<std::string> tokens;
02293                         std::vector<std::string> cmd_tokens;
02294 
02295             do {
02296                                 /*
02297                                  * wait for response
02298                                  */
02299                                 DBG_PRINTF(debug, "### WAITING RESPONSE\n");
02300                                 if(response_message_queue.wait(timeout_msec) == false) {
02301                                         DBG_PRINTF(debug, "TIMEOUT!!(%d)\n", timeout_msec);
02302                                         return false;
02303                                 }
02304 
02305         #ifdef WIN32
02306                                 /*
02307                                  * stupid windows...
02308                                  */
02309                                 while(response_message_queue.size() == 0);
02310         #endif // WIN32
02311 
02312                                 /*
02313                                  *  check response
02314                                  */
02315                                 tokens.clear();
02316                                 if(response_message_queue.pop(tokens) == false) {
02317                                         if(debug) {
02318                                                 Platform::msleep(10);
02319                                                 DBG_PRINTF(debug, "ERROR??? : response_queue.pop() returns false (response_queue.size() %lu, cmd=%s)\n", response_message_queue.size(), command_string.c_str());
02320                                         }
02321                                         return false;
02322                                 }
02323 
02324                                 cmd_tokens.clear();
02325                                 StringUtil::split(cmd_tokens, command_string.c_str(), ',');
02326                                 StringUtil::replace(cmd_tokens[0], "@", "~");
02327                                 if(tokens[0] == cmd_tokens[0]) {
02328                                         DBG_PRINTF(debug, "### RCV OK(%s)\n", cmd_tokens[0].c_str());
02329                                         break;
02330                                 }
02331                                 else {
02332                                         DBG_PRINTF(debug, "ERROR: invalid response. command %s, response %s)\n", cmd_tokens[0].c_str(), tokens[0].c_str());
02333                                         continue;
02334                                 }
02335             }while(1);
02336 
02337 
02338             /*
02339              *  handle error response
02340              */
02341             if(tokens[1] != std::string("OK")) {
02342                 // print error message
02343                 DBG_PRINTF(debug, "ERROR: status is not OK. command %s)\n", cmd_tokens[0].c_str());
02344                 return false;
02345             }
02346 
02347             /*
02348              *  run response handler
02349              */
02350             std::map<std::string, AscRspHandler>::iterator it = ascii_handler_rsp_map.find(tokens[0]);
02351             if(it != ascii_handler_rsp_map.end()) {
02352                 std::map<std::string, std::string> attributes;
02353                 bool res = true;
02354                 if(StringUtil::extract_attributes(attributes, tokens) > 0) {
02355                     LockGuard _l(mutex_attribute);
02356                     res = (this->*(it->second))(attributes);
02357                     if(res == false) {
02358                         DBG_PRINTF(debug, "ERROR: message hander returns false. command %s)\n", cmd_tokens[0].c_str());
02359                     }
02360                 }
02361 
02362                 if(res) {
02363                         DBG_PRINTF(debug, "### OK : message hander returns true. command %s, rcvq_sz %d)\n", cmd_tokens[0].c_str(), response_message_queue.size());
02364                 }
02365 
02366                 return res;
02367             }
02368             else {
02369                 return false;
02370             }
02371         }
02372 
02373         /*
02374          * threads
02375          */
02376         void proc_receiver() {
02377             int len;
02378             unsigned char buffer[1024];
02379 
02380             thread_receiver_ready = true;
02381 
02382             while(true) {
02383                 memset(buffer, 0, sizeof(buffer));
02384                 len = serial.Read(buffer, sizeof(buffer)-1);
02385                 if(len == 0) {
02386                     Platform::msleep(1);
02387                     continue;
02388                 }
02389                 else if(len < 0) {
02390                     break; // stop thread
02391                 }
02392                 else if(len > 0) {
02393                     DBG_PRINTF(debug, "### SZ(%d) [%s]\n", len, buffer);
02394                     protocol.feed(buffer, len);
02395                 }
02396             }
02397 
02398             DBG_PRINTF(debug, "### %s() exit\n", __FUNCTION__);
02399         }
02400 
02401         void proc_callback() {
02402             EventItem* event;
02403             bool exit_thread = false;
02404 
02405             while(exit_thread == false) {
02406                 event = event_queue.pop_event();
02407                 if(event == 0) {
02408                     event_queue.wait();
02409                     continue;
02410                 }
02411 
02412                 try {
02413                     switch(event->event_id) {
02414                         case EventItem::EXIT:
02415                             DBG_PRINTF(debug, "receive EventItem::EXIT\n");
02416                             exit_thread = true;
02417                             break;
02418                         case EventItem::ATTRIBUTE: {
02419                                 std::map<std::string, std::string>* attribute_pair = event->get_attribute();
02420                                 for(std::map<std::string, std::string>::iterator it=attribute_pair->begin(); it!=attribute_pair->end(); it++) {
02421                                     OnAttributeChange(sensor_id, it->first, it->second);
02422                                 }
02423                             }
02424                             break;
02425                         case EventItem::DATA: {
02426                                 SensorData* sensor_data = event->get_sensor_data();
02427                                 OnSensorData(sensor_id, *sensor_data);
02428                             }
02429                             break;
02430                         default:
02431                             break;
02432                     }
02433                 }
02434                 catch(...) {}
02435 
02436                 delete event;
02437             } // while(exit_thread == false)
02438 
02439             DBG_PRINTF(debug, "### %s() exit\n", __FUNCTION__);
02440         }
02441 
02442         static void* thread_proc_receiver(void* arg) {
02443             ((iMyAhrsPlus*)arg)->proc_receiver();
02444             return 0;
02445         }
02446 
02447         static void* thread_proc_callback(void* arg) {
02448             ((iMyAhrsPlus*)arg)->proc_callback();
02449             return 0;
02450         }
02451 
02452 
02453         /*
02454          *  ascii response handlers
02455          */
02456         bool ascii_parse_response(std::vector<std::string>& tokens) {
02457             if(tokens[0][0] == iAsciiProtocol::MSG_HDR_RESPONSE) {
02458                 // message parsing will be delegated to send_command()
02459                 response_message_queue.push_back(tokens);
02460                 return true;
02461             }
02462             else {
02463                 LockGuard _l(mutex_attribute);
02464 
02465                 sensor_data.reset();
02466                 bool res = false;
02467 
02468                 std::map<std::string, AscHandler>::iterator it = ascii_handler_data_map.find(tokens[0]);
02469                 if(it != ascii_handler_data_map.end()) {
02470                     res = (this->*(it->second))(tokens);
02471                 }
02472 
02473                 if(res && activate_user_event) {
02474                     event_queue.push_event_data(sensor_data);
02475                 }
02476 
02477                 return res;
02478             }
02479         }
02480 
02481         void dbg_show_all_attributes(std::map<std::string, std::string>& attributes) {
02482             for (std::map<std::string, std::string>::iterator it=attributes.begin(); it!=attributes.end(); ++it) {
02483                 DBG_PRINTF(debug, "   --- %s : %s\n", (it->first).c_str(), (it->second).c_str());
02484             }
02485         }
02486 
02487         bool ascii_rsp_trigger(std::map<std::string, std::string>& attributes) {
02488             return true;
02489         }
02490 
02491         bool ascii_rsp_ping(std::map<std::string, std::string>& attributes) {
02492             return true;
02493         }
02494 
02495         bool ascii_rsp_divider(std::map<std::string, std::string>& attributes) {
02496             dbg_show_all_attributes(attributes);
02497 
02498             set_attribute("divider", attributes["divider"]);
02499             set_attribute("max_rate", attributes["max_rate"]);
02500 
02501             return true;
02502         }
02503 
02504         bool ascii_rsp_mode(std::map<std::string, std::string>& attributes) {
02505             dbg_show_all_attributes(attributes);
02506 
02507             set_attribute("mode", attributes["mode"]);
02508 
02509             return true;
02510         }
02511 
02512         bool ascii_rsp_asc_out(std::map<std::string, std::string>& attributes) {
02513             dbg_show_all_attributes(attributes);
02514 
02515             set_attribute("ascii_format", attributes["fmt"]);
02516 
02517             return true;
02518         }
02519 
02520         bool ascii_rsp_bin_out(std::map<std::string, std::string>& attributes) {
02521             dbg_show_all_attributes(attributes);
02522 
02523             std::vector<std::string> prop_bin_format;
02524             StringUtil::split(prop_bin_format, attributes["fmt"].c_str(), ' ');
02525             set_attribute("binary_format", StringUtil::join(prop_bin_format, ", "));
02526 
02527             return true;
02528         }
02529 
02530         bool ascii_rsp_user_orientation(std::map<std::string, std::string>& attributes) {
02531             dbg_show_all_attributes(attributes);
02532 
02533             // ~set_offset,OK,yaw_offset=OFF,q_s2v=0.000000e+00 0.000000e+00 0.000000e+00 1.000000e+00,q_g2u=0.000000e+00 0.000000e+00 0.000000e+00 1.000000e+00*12
02534 
02535             set_attribute("yaw_offset", attributes["yaw_offset"]);
02536 
02537             std::vector<std::string> parameters;
02538 
02539             if(StringUtil::split(parameters, attributes["q_s2v"].c_str(), ' ') != 4) {
02540                 return false;
02541             }
02542             set_attribute("coordinate_transformation_sensor_to_vehicle", StringUtil::join(parameters, ", "));
02543 
02544             if(StringUtil::split(parameters, attributes["q_g2u"].c_str(), ' ') != 4) {
02545                 return false;
02546             }
02547             set_attribute("coordinate_transformation_global_to_user", StringUtil::join(parameters, ", "));
02548 
02549             return true;
02550         }
02551 
02552         bool ascii_rsp_calib(std::map<std::string, std::string>& attributes) {
02553             dbg_show_all_attributes(attributes);
02554 
02555             // ~calib,OK,sensor=A,param=4.882813e-04 0.000000e+00 0.000000e+00 0.000000e+00 4.882813e-04 0.000000e+00 0.000000e+00 0.000000e+00 4.882813e-04 0.000000e+00 0.000000e+00 0.000000e+00*0E
02556 
02557             std::string sensor = attributes["sensor"];
02558 
02559             switch((char)sensor[0]) {
02560             case 'A':
02561                 sensor = "accel";
02562                 break;
02563             case 'G':
02564                 sensor = "gyro";
02565                 break;
02566             case 'M':
02567                 sensor = "magnet";
02568                 break;
02569             default:
02570                 return false;
02571             }
02572 
02573             std::vector<std::string> parameters;
02574             if(StringUtil::split(parameters, attributes["param"].c_str(), ' ') != 12) {
02575                 return false;
02576             }
02577 
02578             std::vector<std::string> transform(9, "");
02579             std::vector<std::string> bias(3, "");
02580 
02581             std::copy_n(parameters.begin(), 9, transform.begin());
02582             std::copy_n(parameters.begin()+9, 3, bias.begin());
02583 
02584             set_attribute(sensor + "_calibration_matrix", StringUtil::join(transform, ", "));
02585             set_attribute(sensor + "_bias", StringUtil::join(bias, ", "));
02586 
02587             return true;
02588         }
02589 
02590         bool ascii_rsp_factory(std::map<std::string, std::string>& attributes) {
02591             dbg_show_all_attributes(attributes);
02592 
02593             return true;
02594         }
02595 
02596         bool ascii_rsp_stat(std::map<std::string, std::string>& attributes) {
02597             dbg_show_all_attributes(attributes);
02598 
02599             return true;
02600         }
02601 
02602         bool ascii_rsp_version(std::map<std::string, std::string>& attributes) {
02603             dbg_show_all_attributes(attributes);
02604 
02605             set_attribute("build_date", attributes["build"]);
02606             set_attribute("platform", attributes["platform"]);
02607             set_attribute("product_name", attributes["product"]);
02608             set_attribute("sensor_serial_number", attributes["sn"]);
02609             set_attribute("firmware_version", attributes["ver"]);
02610 
02611             return true;
02612         }
02613 
02614         bool ascii_rsp_id(std::map<std::string, std::string>& attributes) {
02615             dbg_show_all_attributes(attributes);
02616 
02617             std::string str_sensor_id = attributes["id"];
02618             set_attribute("sensor_id", str_sensor_id);
02619             sensor_id = atoi(str_sensor_id.c_str());
02620 
02621             return true;
02622         }
02623 
02624         bool ascii_rsp_serial_number(std::map<std::string, std::string>& attributes) {
02625             dbg_show_all_attributes(attributes);
02626 
02627             set_attribute("sensor_serial_number", attributes["sn"]);
02628 
02629             return true;
02630         }
02631 
02632         bool ascii_rsp_sensitivity(std::map<std::string, std::string>& attributes) {
02633             dbg_show_all_attributes(attributes);
02634 
02635             set_attribute("accel_max", attributes["acc_range"]);
02636             set_attribute("gyro_max", attributes["gyro_range"]);
02637             set_attribute("accel_sensitivity", attributes["acc_sensitivity"]);
02638             set_attribute("gyro_sensitivity", attributes["gyro_sensitivity"]);
02639 
02640             return true;
02641         }
02642 
02643         bool ascii_rsp_baudrate(std::map<std::string, std::string>& attributes) {
02644             dbg_show_all_attributes(attributes);
02645 
02646             set_attribute("baudrate", attributes["baudrate"]);
02647 
02648             return true;
02649         }
02650 
02651         bool ascii_rsp_save(std::map<std::string, std::string>& attributes) {
02652             dbg_show_all_attributes(attributes);
02653 
02654             return true;
02655         }
02656 
02657 
02658         /*
02659          *  ascii data message handlers
02660          */
02661 
02662         // $RPY,04,-1.55,-1.25,96.94*50
02663         bool ascii_update_euler(std::vector<std::string>& tokens) {
02664             static const int DATA_NUM = 3;
02665             if(tokens.size() != DATA_NUM + 2) {
02666                 return false;
02667             }
02668 
02669             sensor_data.sequence_number = atoi(tokens[1].c_str());
02670 
02671             std::vector<std::string> str_euler(DATA_NUM, "");
02672             std::copy_n(tokens.begin() + 2, DATA_NUM, str_euler.begin());
02673 
02674             EulerAngle e;
02675             e.set(str_euler);
02676             sensor_data.update_attitude(e);
02677 
02678             DBG_PRINTF(debug, "### %s(%s)\n", __FUNCTION__, StringUtil::join(str_euler, ", ").c_str());
02679 
02680             return true;
02681         }
02682 
02683         // $QUAT,68,0.0006,0.0174,-0.7489,-0.6625*16
02684         bool ascii_update_quaternion(std::vector<std::string>& tokens) {
02685             static const int DATA_NUM = 4;
02686             if(tokens.size() != DATA_NUM + 2) {
02687                 return false;
02688             }
02689 
02690             sensor_data.sequence_number = atoi(tokens[1].c_str());
02691 
02692             std::vector<std::string> str_quat(DATA_NUM, "");
02693             std::copy_n(tokens.begin() + 2, DATA_NUM, str_quat.begin());
02694 
02695             Quaternion q;
02696             q.set(str_quat);
02697             sensor_data.update_attitude(q);
02698 
02699             DBG_PRINTF(debug, "### %s(%s)\n", __FUNCTION__, StringUtil::join(str_quat, ", ").c_str());
02700 
02701             return true;
02702         }
02703 
02704         // $RPYIMU,15,-1.55,-1.25,97.31,-0.0142,-0.0010,-0.9224,-0.9756,-0.3659,-0.8537,-8.4000,-46.8000,5.4000,38.3*36
02705         bool ascii_update_rpyimu(std::vector<std::string>& tokens) {
02706             static const int DATA_NUM_EULER = 3;
02707             static const int DATA_NUM_IMU = 10;
02708             if(tokens.size() != DATA_NUM_EULER + DATA_NUM_IMU + 2) {
02709                 return false;
02710             }
02711 
02712             sensor_data.sequence_number = atoi(tokens[1].c_str());
02713 
02714             std::vector<std::string> str_euler(DATA_NUM_EULER, "");
02715             std::copy_n(tokens.begin() + 2, DATA_NUM_EULER, str_euler.begin());
02716 
02717             EulerAngle e;
02718             e.set(str_euler);
02719             sensor_data.update_attitude(e);
02720 
02721             std::vector<std::string> str_imu(DATA_NUM_IMU, "");
02722             std::copy_n(tokens.begin() + 2 + DATA_NUM_EULER, DATA_NUM_IMU, str_imu.begin());
02723 
02724             ImuData<float> imu;
02725             imu.set(str_imu);
02726             sensor_data.update_imu(imu);
02727 
02728             DBG_PRINTF(debug, "### %s(euler=(%s), imu=(%s))\n", __FUNCTION__, StringUtil::join(str_euler, ", ").c_str(), StringUtil::join(str_imu, ", ").c_str());
02729 
02730             return true;
02731         }
02732 
02733         // $QUATIMU,53,0.0424,-0.1791,0.2366,0.9540,-0.3636,0.0027,-0.9260,0.0156,0.1537,0.2896,212.2648,-72.7573,168.2144,36.8*7F
02734         bool ascii_update_quatimu(std::vector<std::string>& tokens) {
02735             static const int DATA_NUM_QUAT = 4;
02736             static const int DATA_NUM_IMU = 10;
02737             if(tokens.size() != DATA_NUM_QUAT + DATA_NUM_IMU + 2) {
02738                 return false;
02739             }
02740 
02741             sensor_data.sequence_number = atoi(tokens[1].c_str());
02742 
02743             std::vector<std::string> str_quat(DATA_NUM_QUAT, "");
02744             std::copy_n(tokens.begin() + 2, DATA_NUM_QUAT, str_quat.begin());
02745 
02746             Quaternion q;
02747             q.set(str_quat);
02748             sensor_data.update_attitude(q);
02749 
02750             std::vector<std::string> str_imu(DATA_NUM_IMU, "");
02751             std::copy_n(tokens.begin() + 2 + DATA_NUM_QUAT, DATA_NUM_IMU, str_imu.begin());
02752 
02753             ImuData<float> imu;
02754             imu.set(str_imu);
02755             sensor_data.update_imu(imu);
02756 
02757             DBG_PRINTF(debug, "### %s(quaternion=(%s), imu=(%s))\n", __FUNCTION__, StringUtil::join(str_quat, ", ").c_str(), StringUtil::join(str_imu, ", ").c_str());
02758 
02759 
02760             return true;
02761         }
02762 
02763         // $RIIMU,59,-16,-8,-1897,-14,-7,-12,-26,-156,18,1101*79
02764         bool ascii_update_riimu(std::vector<std::string>& tokens) {
02765             static const int DATA_NUM = 10;
02766             if(tokens.size() != DATA_NUM + 2) {
02767                 return false;
02768             }
02769 
02770             sensor_data.sequence_number = atoi(tokens[1].c_str());
02771 
02772             std::vector<std::string> str_imu(DATA_NUM, "");
02773             std::copy_n(tokens.begin() + 2, DATA_NUM, str_imu.begin());
02774 
02775             ImuData<int> imu_rawdata;
02776             imu_rawdata.set(str_imu);
02777             sensor_data.update_imu(imu_rawdata);
02778 
02779             DBG_PRINTF(debug, "### %s(%s)\n", __FUNCTION__, StringUtil::join(str_imu, ", ").c_str());
02780 
02781             return true;
02782         }
02783 
02784         // $IMU,74,-0.0054,-0.0015,-0.9204,-0.7317,-0.4878,-0.7317,-7.2000,-45.6000,6.6000,38.2*68
02785         bool ascii_update_imu(std::vector<std::string>& tokens) {
02786             static const int DATA_NUM = 10;
02787             if(tokens.size() != DATA_NUM + 2) {
02788                 return false;
02789             }
02790 
02791             sensor_data.sequence_number = atoi(tokens[1].c_str());
02792 
02793             std::vector<std::string> str_imu(DATA_NUM, "");
02794             std::copy_n(tokens.begin() + 2, DATA_NUM, str_imu.begin());
02795 
02796             ImuData<float> imu;
02797             imu.set(str_imu);
02798             sensor_data.update_imu(imu);
02799 
02800             DBG_PRINTF(debug, "### %s(%s)\n", __FUNCTION__, StringUtil::join(str_imu, ", ").c_str());
02801 
02802             return true;
02803         }
02804 
02805 
02806         /*
02807          * binary data message handlers
02808          */
02809         bool binary_parse_response(std::vector<iNodeParser::Node>& node_list) {
02810             LockGuard _l(mutex_attribute);
02811 
02812             sensor_data.reset();
02813 
02814             if(debug) {
02815                 for(size_t i=0; i<node_list.size(); i++) {
02816                     DBG_PRINTF(debug, "\t#### node(%lu/%lu)->name[%02X] : %s\n", i, node_list.size(), node_list[i].name[0], node_list[i].name.c_str());
02817                 }
02818             }
02819 
02820             for(size_t i=0; i<node_list.size(); i++) {
02821                 iNodeParser::Node& node = node_list[i];
02822                 std::map<std::string, BinHandler>::iterator it = binary_handler_data_map.find(node.name);
02823                 if(it != binary_handler_data_map.end()) {
02824                     if((this->*(it->second))(node) == false) {
02825                         return false;
02826                     }
02827                 }
02828             }
02829 
02830             if(activate_user_event) {
02831                 event_queue.push_event_data(sensor_data);
02832             }
02833 
02834             return true;
02835         }
02836 
02837         float int16tofloat(int16_t value, float value_max) {
02838             static const int SCALE_FACTOR = 0x7FFF;
02839             double ratio = ((double)value)/SCALE_FACTOR;
02840             return (float)(ratio*value_max);
02841         }
02842 
02843         bool binary_update_sequence(iNodeParser::Node& node) {
02844             sensor_data.sequence_number = node.list[0].value.ui8;
02845 
02846             DBG_PRINTF(debug, "### binary_update_sequence(%d)\n", node.list[0].value.ui8);
02847 
02848             return true;
02849         }
02850 
02851         bool binary_update_euler(iNodeParser::Node& node) {
02852             static const int DATA_NUM = 3;
02853             if(node.list.size() != DATA_NUM) {
02854                 return false;
02855             }
02856 
02857             float roll  = int16tofloat(node.list[0].value.i16, (float)EULER_RANGE);
02858             float pitch = int16tofloat(node.list[1].value.i16, (float)EULER_RANGE);
02859             float yaw   = int16tofloat(node.list[2].value.i16, (float)EULER_RANGE);
02860 
02861             EulerAngle e;
02862             e.set(roll, pitch, yaw);
02863             sensor_data.update_attitude(e);
02864 
02865             DBG_PRINTF(debug, "### %s(%f, %f, %f)\n", __FUNCTION__, roll, pitch, yaw);
02866 
02867             return true;
02868         }
02869 
02870         bool binary_update_quaternion(iNodeParser::Node& node) {
02871             static const int DATA_NUM = 4;
02872             if(node.list.size() != DATA_NUM) {
02873                 return false;
02874             }
02875 
02876             float x = int16tofloat(node.list[0].value.i16, 1);
02877             float y = int16tofloat(node.list[1].value.i16, 1);
02878             float z = int16tofloat(node.list[2].value.i16, 1);
02879             float w = int16tofloat(node.list[3].value.i16, 1);
02880 
02881             Quaternion q;
02882             q.set(x, y, z, w);
02883             sensor_data.update_attitude(q);
02884 
02885             DBG_PRINTF(debug, "### %s(%f, %f, %f, %f)\n", __FUNCTION__, x,y,z,w);
02886 
02887             return true;
02888         }
02889 
02890         bool binary_update_imu(iNodeParser::Node& node) {
02891             static const int DATA_NUM = 10;
02892             if(node.list.size() != DATA_NUM) {
02893                 return false;
02894             }
02895 
02896             float m[DATA_NUM];
02897 
02898             m[0] = int16tofloat(node.list[0].value.i16, (float)ACCEL_RANGE);
02899             m[1] = int16tofloat(node.list[1].value.i16, (float)ACCEL_RANGE);
02900             m[2] = int16tofloat(node.list[2].value.i16, (float)ACCEL_RANGE);
02901 
02902             m[3] = int16tofloat(node.list[3].value.i16, (float)GYRO_RANGE);
02903             m[4] = int16tofloat(node.list[4].value.i16, (float)GYRO_RANGE);
02904             m[5] = int16tofloat(node.list[5].value.i16, (float)GYRO_RANGE);
02905 
02906             m[6] = int16tofloat(node.list[6].value.i16, (float)MAGNET_RANGE);
02907             m[7] = int16tofloat(node.list[7].value.i16, (float)MAGNET_RANGE);
02908             m[8] = int16tofloat(node.list[8].value.i16, (float)MAGNET_RANGE);
02909 
02910             m[9] = int16tofloat(node.list[9].value.i16, (float)TEMP_RANGE);
02911 
02912             ImuData<float> imu;
02913             imu.set(m);
02914             sensor_data.update_imu(imu);
02915 
02916             if(debug) {
02917                 std::vector<std::string> str_list;
02918                 StringUtil::to_string_list(str_list, m, DATA_NUM);
02919                 DBG_PRINTF(debug, "### %s(%s)\n", __FUNCTION__, StringUtil::join(str_list, ", ").c_str());
02920             }
02921 
02922             return true;
02923         }
02924 
02925         bool binary_update_riimu(iNodeParser::Node& node) {
02926             static const int DATA_NUM = 10;
02927             if(node.list.size() != DATA_NUM) {
02928                 return false;
02929             }
02930 
02931             int m[DATA_NUM];
02932             for(int i=0; i<DATA_NUM; i++) {
02933                 m[i] = node.list[i].value.i16;
02934             }
02935 
02936             ImuData<int> imu_rawdata;
02937             imu_rawdata.set(m);
02938             sensor_data.update_imu(imu_rawdata);
02939 
02940             if(debug) {
02941                 std::vector<std::string> str_list;
02942                 StringUtil::to_string_list(str_list, m, DATA_NUM);
02943                 DBG_PRINTF(debug, "### %s(%s)\n", __FUNCTION__, StringUtil::join(str_list, ", ").c_str());
02944             }
02945 
02946             return true;
02947         }
02948     }; // iMyAhrsPlus
02949 
02950 
02951     class MyAhrsPlus : public iMyAhrsPlus
02952     {
02953         Platform::Event event;
02954         Platform::Mutex lock;
02955 
02956         void(*attribute_callback)(void* context, int sensor_id, const char* attribute_name, const char* value);
02957         void* attribute_callback_context;
02958 
02959         void(*data_callback)(void* context, int sensor_id, SensorData* sensor_data);
02960         void* data_callback_context;
02961 
02962         uint32_t sample_count;
02963 
02964     public:
02965         MyAhrsPlus(std::string port="", unsigned int baudrate=115200)
02966         : iMyAhrsPlus(port, baudrate), sample_count(0)
02967         , attribute_callback(0), attribute_callback_context(0)
02968         , data_callback(0), data_callback_context(0)
02969         {}
02970 
02971         virtual ~MyAhrsPlus() {
02972             attribute_callback = 0;
02973             attribute_callback_context = 0;
02974             data_callback = 0;
02975             data_callback_context = 0;
02976         }
02977 
02978         bool wait_data(int timeout_msec=500) {
02979             return event.wait(timeout_msec);
02980         }
02981 
02982         void register_attribute_callback(void(*callback)(void* context, int sensor_id, const char* attribute_name, const char* value), void* callback_context) {
02983             LockGuard _l(lock);
02984             attribute_callback_context = callback_context;
02985             attribute_callback = callback;
02986         }
02987 
02988         void register_data_callback(void(*callback)(void* context, int sensor_id, SensorData* sensor_data), void* callback_context) {
02989             LockGuard _l(lock);
02990             data_callback_context = callback_context;
02991             data_callback = callback;
02992         }
02993 
02994         inline uint32_t get_sample_count() {
02995             LockGuard _l(lock);
02996             return sample_count;
02997         }
02998 
02999     protected:
03000         void OnAttributeChange(int sensor_id, std::string attribute_name, std::string value) {
03001             LockGuard _l(lock);
03002             if(attribute_callback) {
03003                 try {
03004                     attribute_callback(attribute_callback_context, sensor_id, attribute_name.c_str(), value.c_str());
03005                 } catch(...) {}
03006             }
03007         }
03008 
03009         void OnSensorData(int sensor_id, SensorData data) {
03010             LockGuard _l(lock);
03011             sample_count++;
03012             event.set();
03013             if(data_callback) {
03014                 try {
03015                     data_callback(data_callback_context, sensor_id, &data);
03016                 } catch(...) {}
03017             }
03018         }
03019     };
03020 }; // WithRobot
03021 
03022 #endif // __MYAHRS_PLUS_H_


myahrs_driver
Author(s): Yoonseok Pyo
autogenerated on Sat Jun 8 2019 10:27:56