00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
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
00093
00094 #define WITHROBOT_MYAHRS_PLUS_SDK_VERSION "myahrs+ sdk. ver. 1.01"
00095
00096
00097
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
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
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
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
00245
00246
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
00266 return dwBytesWritten;
00267 }
00268 else {
00269
00270
00271
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,
00321 FALSE,
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
00375
00376 class Platform
00377 {
00378 public:
00379
00380 class SerialPort
00381 {
00382 std::string port_name;
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);
00417 tcgetattr(fd, &options);
00418
00419 cfsetspeed(&options, baudrate);
00420 cfmakeraw(&options);
00421
00422 options.c_cflag |= CREAD | CLOCAL;
00423 options.c_cflag |= CS8;
00424 options.c_cc[VMIN] = 0;
00425 options.c_cc[VTIME] = 1;
00426
00427
00428 tcsetattr(fd, TCSANOW, &options);
00429
00430
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
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);
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
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 };
00585
00586 #endif // #ifdef WIN32
00587
00588
00589
00590
00591
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
00627 static inline std::string <rim(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
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
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
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
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
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
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
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
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,
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 };
00924
00925
00926 class iNodeParser
00927 {
00928 public:
00929 enum Tag {
00930
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
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;
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 };
01149
01150
01151
01152
01153
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
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
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
01399
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
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
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
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;
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());
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
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
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
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
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
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
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
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
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
02130
02131 void cmd_trigger() {
02132
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
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
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
02289 return true;
02290 }
02291
02292 std::vector<std::string> tokens;
02293 std::vector<std::string> cmd_tokens;
02294
02295 do {
02296
02297
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
02308
02309 while(response_message_queue.size() == 0);
02310 #endif // WIN32
02311
02312
02313
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
02340
02341 if(tokens[1] != std::string("OK")) {
02342
02343 DBG_PRINTF(debug, "ERROR: status is not OK. command %s)\n", cmd_tokens[0].c_str());
02344 return false;
02345 }
02346
02347
02348
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
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;
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 }
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
02455
02456 bool ascii_parse_response(std::vector<std::string>& tokens) {
02457 if(tokens[0][0] == iAsciiProtocol::MSG_HDR_RESPONSE) {
02458
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
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
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
02660
02661
02662
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
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
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
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
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
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
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 };
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 };
03021
03022 #endif // __MYAHRS_PLUS_H_