├── .gitignore ├── ControlCAN.dll ├── ControlCAN.h ├── ControlCAN.lib ├── IMUFilter.pro ├── IMUFilter.pro.user ├── IMUfilter.cpp ├── IMUfilter.h ├── LICENSE ├── README.md ├── devicefilter.cpp ├── devicefilter.h ├── kerneldlls ├── CAN232.dll ├── CANETE.dll ├── CANET_TCP.dll ├── PC104C2.dll ├── PC104CAN.dll ├── PCI5121.dll ├── gisadll.dll ├── gpcidll.dll ├── isa5420.dll ├── kerneldll.ini └── usbcan.dll ├── macrodefs.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── qcustomplot.cpp ├── qcustomplot.h ├── usbcan.cpp └── usbcan.h /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | *.pro.user 16 | *.pro.user.* 17 | moc_*.cpp 18 | qrc_*.cpp 19 | Makefile 20 | *-build-* 21 | -------------------------------------------------------------------------------- /ControlCAN.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/ControlCAN.dll -------------------------------------------------------------------------------- /ControlCAN.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTROLCAN_H 2 | #define CONTROLCAN_H 3 | 4 | //接口卡类型定义 5 | #define VCI_PCI5121 1 6 | #define VCI_PCI9810 2 7 | #define VCI_USBCAN1 3 8 | #define VCI_USBCAN2 4 9 | #define VCI_USBCAN2A 4 10 | #define VCI_PCI9820 5 11 | #define VCI_CAN232 6 12 | #define VCI_PCI5110 7 13 | #define VCI_CANLITE 8 14 | #define VCI_ISA9620 9 15 | #define VCI_ISA5420 10 16 | #define VCI_PC104CAN 11 17 | #define VCI_CANETUDP 12 18 | #define VCI_CANETE 12 19 | #define VCI_DNP9810 13 20 | #define VCI_PCI9840 14 21 | #define VCI_PC104CAN2 15 22 | #define VCI_PCI9820I 16 23 | #define VCI_CANETTCP 17 24 | #define VCI_PEC9920 18 25 | #define VCI_PCIE_9220 18 26 | #define VCI_PCI5010U 19 27 | #define VCI_USBCAN_E_U 20 28 | #define VCI_USBCAN_2E_U 21 29 | #define VCI_PCI5020U 22 30 | #define VCI_EG20T_CAN 23 31 | #define VCI_PCIE9221 24 32 | 33 | //CAN错误码 34 | #define ERR_CAN_OVERFLOW 0x0001 //CAN控制器内部FIFO溢出 35 | #define ERR_CAN_ERRALARM 0x0002 //CAN控制器错误报警 36 | #define ERR_CAN_PASSIVE 0x0004 //CAN控制器消极错误 37 | #define ERR_CAN_LOSE 0x0008 //CAN控制器仲裁丢失 38 | #define ERR_CAN_BUSERR 0x0010 //CAN控制器总线错误 39 | #define ERR_CAN_BUSOFF 0x0020 //总线关闭错误 40 | //通用错误码 41 | #define ERR_DEVICEOPENED 0x0100 //设备已经打开 42 | #define ERR_DEVICEOPEN 0x0200 //打开设备错误 43 | #define ERR_DEVICENOTOPEN 0x0400 //设备没有打开 44 | #define ERR_BUFFEROVERFLOW 0x0800 //缓冲区溢出 45 | #define ERR_DEVICENOTEXIST 0x1000 //此设备不存在 46 | #define ERR_LOADKERNELDLL 0x2000 //装载动态库失败 47 | #define ERR_CMDFAILED 0x4000 //执行命令失败错误码 48 | #define ERR_BUFFERCREATE 0x8000 //内存不足 49 | 50 | 51 | //函数调用返回状态值 52 | #define STATUS_OK 1 53 | #define STATUS_ERR 0 54 | 55 | #define CMD_DESIP 0 56 | #define CMD_DESPORT 1 57 | #define CMD_CHGDESIPANDPORT 2 58 | #define CMD_SRCPORT 2 59 | #define CMD_TCP_TYPE 4 //tcp 工作方式,服务器:1 或是客户端:0 60 | #define TCP_CLIENT 0 61 | #define TCP_SERVER 1 62 | //服务器方式下有效 63 | #define CMD_CLIENT_COUNT 5 //连接上的客户端计数 64 | #define CMD_CLIENTS 6 //连接上的客户端 65 | #define CMD_DISCONN_CLINET 7 //断开一个连接 66 | 67 | typedef struct tagRemoteClient{ 68 | int iIndex; 69 | DWORD port; 70 | HANDLE hClient; 71 | char szip[32]; 72 | }REMOTE_CLIENT; 73 | 74 | 75 | //1.ZLGCAN系列接口卡信息的数据类型。 76 | typedef struct _VCI_BOARD_INFO{ 77 | USHORT hw_Version; 78 | USHORT fw_Version; 79 | USHORT dr_Version; 80 | USHORT in_Version; 81 | USHORT irq_Num; 82 | BYTE can_Num; 83 | CHAR str_Serial_Num[20]; 84 | CHAR str_hw_Type[40]; 85 | USHORT Reserved[4]; 86 | } VCI_BOARD_INFO,*PVCI_BOARD_INFO; 87 | 88 | //2.定义CAN信息帧的数据类型。 89 | typedef struct _VCI_CAN_OBJ{ 90 | UINT ID; 91 | UINT TimeStamp; 92 | BYTE TimeFlag; 93 | BYTE SendType; 94 | BYTE RemoteFlag;//是否是远程帧 95 | BYTE ExternFlag;//是否是扩展帧 96 | BYTE DataLen; 97 | BYTE Data[8]; 98 | BYTE Reserved[3]; 99 | }VCI_CAN_OBJ,*PVCI_CAN_OBJ; 100 | 101 | //3.定义CAN控制器状态的数据类型。 102 | typedef struct _VCI_CAN_STATUS{ 103 | UCHAR ErrInterrupt; 104 | UCHAR regMode; 105 | UCHAR regStatus; 106 | UCHAR regALCapture; 107 | UCHAR regECCapture; 108 | UCHAR regEWLimit; 109 | UCHAR regRECounter; 110 | UCHAR regTECounter; 111 | DWORD Reserved; 112 | }VCI_CAN_STATUS,*PVCI_CAN_STATUS; 113 | 114 | //4.定义错误信息的数据类型。 115 | typedef struct _VCI_ERR_INFO{ 116 | UINT ErrCode; 117 | BYTE Passive_ErrData[3]; 118 | BYTE ArLost_ErrData; 119 | } VCI_ERR_INFO,*PVCI_ERR_INFO; 120 | 121 | //5.定义初始化CAN的数据类型 122 | typedef struct _VCI_INIT_CONFIG{ 123 | DWORD AccCode; 124 | DWORD AccMask; 125 | DWORD Reserved; 126 | UCHAR Filter; 127 | UCHAR Timing0; 128 | UCHAR Timing1; 129 | UCHAR Mode; 130 | }VCI_INIT_CONFIG,*PVCI_INIT_CONFIG; 131 | 132 | typedef struct _tagChgDesIPAndPort 133 | { 134 | char szpwd[10]; 135 | char szdesip[20]; 136 | int desport; 137 | BYTE blistenonly; 138 | }CHGDESIPANDPORT; 139 | 140 | ///////// new add struct for filter ///////// 141 | typedef struct _VCI_FILTER_RECORD{ 142 | DWORD ExtFrame; //是否为扩展帧 143 | DWORD Start; 144 | DWORD End; 145 | }VCI_FILTER_RECORD,*PVCI_FILTER_RECORD; 146 | 147 | 148 | #define EXTERNC extern "C" 149 | 150 | EXTERNC DWORD __stdcall VCI_OpenDevice(DWORD DeviceType,DWORD DeviceInd,DWORD Reserved); 151 | EXTERNC DWORD __stdcall VCI_CloseDevice(DWORD DeviceType,DWORD DeviceInd); 152 | EXTERNC DWORD __stdcall VCI_InitCAN(DWORD DeviceType, DWORD DeviceInd, DWORD CANInd, PVCI_INIT_CONFIG pInitConfig); 153 | 154 | EXTERNC DWORD __stdcall VCI_ReadBoardInfo(DWORD DeviceType,DWORD DeviceInd,PVCI_BOARD_INFO pInfo); 155 | EXTERNC DWORD __stdcall VCI_ReadErrInfo(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_ERR_INFO pErrInfo); 156 | EXTERNC DWORD __stdcall VCI_ReadCANStatus(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_STATUS pCANStatus); 157 | 158 | EXTERNC DWORD __stdcall VCI_GetReference(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,DWORD RefType,PVOID pData); 159 | EXTERNC DWORD __stdcall VCI_SetReference(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,DWORD RefType,PVOID pData); 160 | 161 | EXTERNC ULONG __stdcall VCI_GetReceiveNum(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd); 162 | EXTERNC DWORD __stdcall VCI_ClearBuffer(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd); 163 | 164 | EXTERNC DWORD __stdcall VCI_StartCAN(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd); 165 | EXTERNC DWORD __stdcall VCI_ResetCAN(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd); 166 | 167 | EXTERNC ULONG __stdcall VCI_Transmit(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pSend,ULONG Len); 168 | EXTERNC ULONG __stdcall VCI_Receive(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pReceive,ULONG Len,INT WaitTime=-1); 169 | 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /ControlCAN.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/ControlCAN.lib -------------------------------------------------------------------------------- /IMUFilter.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2013-11-15T10:24:08 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = IMUFilter 12 | TEMPLATE = app 13 | 14 | 15 | SOURCES += main.cpp\ 16 | mainwindow.cpp \ 17 | usbcan.cpp \ 18 | IMUfilter.cpp \ 19 | devicefilter.cpp \ 20 | qcustomplot.cpp 21 | 22 | HEADERS += mainwindow.h \ 23 | usbcan.h \ 24 | IMUfilter.h \ 25 | ControlCAN.h \ 26 | macrodefs.h \ 27 | devicefilter.h \ 28 | qcustomplot.h 29 | 30 | FORMS += mainwindow.ui 31 | 32 | unix|win32: LIBS += -L$$PWD/ -lControlCAN 33 | 34 | INCLUDEPATH += $$PWD/ 35 | DEPENDPATH += $$PWD/ 36 | -------------------------------------------------------------------------------- /IMUFilter.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ProjectExplorer.Project.ActiveTarget 7 | 0 8 | 9 | 10 | ProjectExplorer.Project.EditorSettings 11 | 12 | true 13 | false 14 | true 15 | 16 | Cpp 17 | 18 | CppGlobal 19 | 20 | 21 | 22 | QmlJS 23 | 24 | QmlJSGlobal 25 | 26 | 27 | 2 28 | UTF-8 29 | false 30 | 4 31 | false 32 | true 33 | 1 34 | true 35 | 0 36 | true 37 | 0 38 | 8 39 | true 40 | 1 41 | true 42 | true 43 | true 44 | false 45 | 46 | 47 | 48 | ProjectExplorer.Project.PluginSettings 49 | 50 | 51 | 52 | ProjectExplorer.Project.Target.0 53 | 54 | Desktop Qt 5.1.1 MSVC2012 32bit 55 | Desktop Qt 5.1.1 MSVC2012 32bit 56 | qt.511.win32_msvc2012.essentials_kit 57 | 1 58 | 0 59 | 0 60 | 61 | 62 | 63 | true 64 | qmake 65 | 66 | QtProjectManager.QMakeBuildStep 67 | false 68 | true 69 | 70 | false 71 | 72 | 73 | true 74 | Make 75 | 76 | Qt4ProjectManager.MakeStep 77 | 78 | false 79 | 80 | 81 | 82 | 2 83 | Build 84 | 85 | ProjectExplorer.BuildSteps.Build 86 | 87 | 88 | 89 | true 90 | Make 91 | 92 | Qt4ProjectManager.MakeStep 93 | 94 | true 95 | clean 96 | 97 | 98 | 1 99 | Clean 100 | 101 | ProjectExplorer.BuildSteps.Clean 102 | 103 | 2 104 | false 105 | 106 | Debug 107 | 108 | Qt4ProjectManager.Qt4BuildConfiguration 109 | 2 110 | G:/CAS/NLPR/Projects/IMU-F100A5/ZLG/DataProcesser/build-IMUFilter-Desktop_Qt_5_1_1_MSVC2012_32bit-Debug 111 | true 112 | 113 | 114 | 115 | 116 | true 117 | qmake 118 | 119 | QtProjectManager.QMakeBuildStep 120 | false 121 | true 122 | 123 | false 124 | 125 | 126 | true 127 | Make 128 | 129 | Qt4ProjectManager.MakeStep 130 | 131 | false 132 | 133 | 134 | 135 | 2 136 | Build 137 | 138 | ProjectExplorer.BuildSteps.Build 139 | 140 | 141 | 142 | true 143 | Make 144 | 145 | Qt4ProjectManager.MakeStep 146 | 147 | true 148 | clean 149 | 150 | 151 | 1 152 | Clean 153 | 154 | ProjectExplorer.BuildSteps.Clean 155 | 156 | 2 157 | false 158 | 159 | Release 160 | 161 | Qt4ProjectManager.Qt4BuildConfiguration 162 | 0 163 | G:/CAS/NLPR/Projects/IMU-F100A5/ZLG/DataProcesser/build-IMUFilter-Desktop_Qt_5_1_1_MSVC2012_32bit-Release 164 | true 165 | 166 | 2 167 | 168 | 169 | 0 170 | Deploy 171 | 172 | ProjectExplorer.BuildSteps.Deploy 173 | 174 | 1 175 | Deploy locally 176 | 177 | ProjectExplorer.DefaultDeployConfiguration 178 | 179 | 1 180 | 181 | 182 | true 183 | 184 | false 185 | false 186 | false 187 | false 188 | true 189 | 0.01 190 | 10 191 | true 192 | 25 193 | 194 | true 195 | valgrind 196 | 197 | 0 198 | 1 199 | 2 200 | 3 201 | 4 202 | 5 203 | 6 204 | 7 205 | 8 206 | 9 207 | 10 208 | 11 209 | 12 210 | 13 211 | 14 212 | 213 | 2 214 | 215 | IMUFilter 216 | 217 | Qt4ProjectManager.Qt4RunConfiguration:G:/CAS/NLPR/Projects/IMU-F100A5/ZLG/DataProcesser/IMUFilter/IMUFilter.pro 218 | 219 | IMUFilter.pro 220 | false 221 | false 222 | 223 | 3768 224 | true 225 | false 226 | false 227 | false 228 | true 229 | 230 | 1 231 | 232 | 233 | 234 | ProjectExplorer.Project.TargetCount 235 | 1 236 | 237 | 238 | ProjectExplorer.Project.Updater.EnvironmentId 239 | {85f47755-6752-4b55-9938-afe90e95b9c6} 240 | 241 | 242 | ProjectExplorer.Project.Updater.FileVersion 243 | 14 244 | 245 | 246 | -------------------------------------------------------------------------------- /IMUfilter.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Aaron Berk 3 | * 4 | * @section LICENSE 5 | * 6 | * Copyright (c) 2010 ARM Limited 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | * 26 | * @section DESCRIPTION 27 | * 28 | * IMU orientation filter developed by Sebastian Madgwick. 29 | * 30 | * Find more details about his paper here: 31 | * 32 | * http://code.google.com/p/imumargalgorithm30042010sohm/ 33 | */ 34 | 35 | /** 36 | * Includes 37 | */ 38 | #include "IMUfilter.h" 39 | 40 | IMUfilter::IMUfilter(double rate, double gyroscopeMeasurementError){ 41 | 42 | firstUpdate = 0; 43 | 44 | //Quaternion orientation of earth frame relative to auxiliary frame. 45 | AEq_1 = 1; 46 | AEq_2 = 0; 47 | AEq_3 = 0; 48 | AEq_4 = 0; 49 | 50 | //Estimated orientation quaternion elements with initial conditions. 51 | SEq_1 = 1; 52 | SEq_2 = 0; 53 | SEq_3 = 0; 54 | SEq_4 = 0; 55 | 56 | //Sampling period (typical value is ~0.1s). 57 | deltat = rate; 58 | 59 | //Gyroscope measurement error (in degrees per second). 60 | gyroMeasError = gyroscopeMeasurementError; 61 | 62 | //Compute beta. 63 | beta = sqrt(3.0 / 4.0) * (PI * (gyroMeasError / 180.0)); 64 | 65 | } 66 | 67 | void IMUfilter::updateFilter(double w_x, double w_y, double w_z, double a_x, double a_y, double a_z) { 68 | 69 | //Local system variables. 70 | 71 | //Vector norm. 72 | double norm; 73 | //Quaternion rate from gyroscope elements. 74 | double SEqDot_omega_1; 75 | double SEqDot_omega_2; 76 | double SEqDot_omega_3; 77 | double SEqDot_omega_4; 78 | //Objective function elements. 79 | double f_1; 80 | double f_2; 81 | double f_3; 82 | //Objective function Jacobian elements. 83 | double J_11or24; 84 | double J_12or23; 85 | double J_13or22; 86 | double J_14or21; 87 | double J_32; 88 | double J_33; 89 | //Objective function gradient elements. 90 | double nablaf_1; 91 | double nablaf_2; 92 | double nablaf_3; 93 | double nablaf_4; 94 | 95 | //Auxiliary variables to avoid reapeated calcualtions. 96 | double halfSEq_1 = 0.5 * SEq_1; 97 | double halfSEq_2 = 0.5 * SEq_2; 98 | double halfSEq_3 = 0.5 * SEq_3; 99 | double halfSEq_4 = 0.5 * SEq_4; 100 | double twoSEq_1 = 2.0 * SEq_1; 101 | double twoSEq_2 = 2.0 * SEq_2; 102 | double twoSEq_3 = 2.0 * SEq_3; 103 | 104 | //Compute the quaternion rate measured by gyroscopes. 105 | SEqDot_omega_1 = -halfSEq_2 * w_x - halfSEq_3 * w_y - halfSEq_4 * w_z; 106 | SEqDot_omega_2 = halfSEq_1 * w_x + halfSEq_3 * w_z - halfSEq_4 * w_y; 107 | SEqDot_omega_3 = halfSEq_1 * w_y - halfSEq_2 * w_z + halfSEq_4 * w_x; 108 | SEqDot_omega_4 = halfSEq_1 * w_z + halfSEq_2 * w_y - halfSEq_3 * w_x; 109 | 110 | //Normalise the accelerometer measurement. 111 | norm = sqrt(a_x * a_x + a_y * a_y + a_z * a_z); 112 | a_x /= norm; 113 | a_y /= norm; 114 | a_z /= norm; 115 | 116 | //Compute the objective function and Jacobian. 117 | f_1 = twoSEq_2 * SEq_4 - twoSEq_1 * SEq_3 - a_x; 118 | f_2 = twoSEq_1 * SEq_2 + twoSEq_3 * SEq_4 - a_y; 119 | f_3 = 1.0 - twoSEq_2 * SEq_2 - twoSEq_3 * SEq_3 - a_z; 120 | //J_11 negated in matrix multiplication. 121 | J_11or24 = twoSEq_3; 122 | J_12or23 = 2 * SEq_4; 123 | //J_12 negated in matrix multiplication 124 | J_13or22 = twoSEq_1; 125 | J_14or21 = twoSEq_2; 126 | //Negated in matrix multiplication. 127 | J_32 = 2 * J_14or21; 128 | //Negated in matrix multiplication. 129 | J_33 = 2 * J_11or24; 130 | 131 | //Compute the gradient (matrix multiplication). 132 | nablaf_1 = J_14or21 * f_2 - J_11or24 * f_1; 133 | nablaf_2 = J_12or23 * f_1 + J_13or22 * f_2 - J_32 * f_3; 134 | nablaf_3 = J_12or23 * f_2 - J_33 * f_3 - J_13or22 * f_1; 135 | nablaf_4 = J_14or21 * f_1 + J_11or24 * f_2; 136 | 137 | //Normalise the gradient. 138 | norm = sqrt(nablaf_1 * nablaf_1 + nablaf_2 * nablaf_2 + nablaf_3 * nablaf_3 + nablaf_4 * nablaf_4); 139 | nablaf_1 /= norm; 140 | nablaf_2 /= norm; 141 | nablaf_3 /= norm; 142 | nablaf_4 /= norm; 143 | 144 | //Compute then integrate the estimated quaternion rate. 145 | SEq_1 += (SEqDot_omega_1 - (beta * nablaf_1)) * deltat; 146 | SEq_2 += (SEqDot_omega_2 - (beta * nablaf_2)) * deltat; 147 | SEq_3 += (SEqDot_omega_3 - (beta * nablaf_3)) * deltat; 148 | SEq_4 += (SEqDot_omega_4 - (beta * nablaf_4)) * deltat; 149 | 150 | //Normalise quaternion 151 | norm = sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); 152 | SEq_1 /= norm; 153 | SEq_2 /= norm; 154 | SEq_3 /= norm; 155 | SEq_4 /= norm; 156 | 157 | if (firstUpdate == 0) { 158 | //Store orientation of auxiliary frame. 159 | AEq_1 = SEq_1; 160 | AEq_2 = SEq_2; 161 | AEq_3 = SEq_3; 162 | AEq_4 = SEq_4; 163 | firstUpdate = 1; 164 | } 165 | 166 | } 167 | 168 | void IMUfilter::computeEuler(void){ 169 | 170 | //Quaternion describing orientation of sensor relative to earth. 171 | double ESq_1, ESq_2, ESq_3, ESq_4; 172 | //Quaternion describing orientation of sensor relative to auxiliary frame. 173 | double ASq_1, ASq_2, ASq_3, ASq_4; 174 | 175 | //Compute the quaternion conjugate. 176 | ESq_1 = SEq_1; 177 | ESq_2 = -SEq_2; 178 | ESq_3 = -SEq_3; 179 | ESq_4 = -SEq_4; 180 | 181 | //Compute the quaternion product. 182 | ASq_1 = ESq_1 * AEq_1 - ESq_2 * AEq_2 - ESq_3 * AEq_3 - ESq_4 * AEq_4; 183 | ASq_2 = ESq_1 * AEq_2 + ESq_2 * AEq_1 + ESq_3 * AEq_4 - ESq_4 * AEq_3; 184 | ASq_3 = ESq_1 * AEq_3 - ESq_2 * AEq_4 + ESq_3 * AEq_1 + ESq_4 * AEq_2; 185 | ASq_4 = ESq_1 * AEq_4 + ESq_2 * AEq_3 - ESq_3 * AEq_2 + ESq_4 * AEq_1; 186 | 187 | //Compute the Euler angles from the quaternion. 188 | phi = atan2(2 * ASq_3 * ASq_4 - 2 * ASq_1 * ASq_2, 2 * ASq_1 * ASq_1 + 2 * ASq_4 * ASq_4 - 1); 189 | theta = asin(2 * ASq_2 * ASq_3 - 2 * ASq_1 * ASq_3); 190 | psi = atan2(2 * ASq_2 * ASq_3 - 2 * ASq_1 * ASq_4, 2 * ASq_1 * ASq_1 + 2 * ASq_2 * ASq_2 - 1); 191 | 192 | } 193 | 194 | double IMUfilter::getRoll(void){ 195 | 196 | return phi; 197 | 198 | } 199 | 200 | double IMUfilter::getPitch(void){ 201 | 202 | return theta; 203 | 204 | } 205 | 206 | double IMUfilter::getYaw(void){ 207 | 208 | return psi; 209 | 210 | } 211 | 212 | // Degrees 213 | double IMUfilter::getRollInDegrees(void){ 214 | 215 | return toDegrees(phi); 216 | 217 | } 218 | 219 | double IMUfilter::getPitchInDegrees(void){ 220 | 221 | return toDegrees(theta); 222 | 223 | } 224 | 225 | double IMUfilter::getYawInDegrees(void){ 226 | 227 | return toDegrees(psi); 228 | 229 | } 230 | 231 | void IMUfilter::reset(void) { 232 | 233 | firstUpdate = 0; 234 | 235 | //Quaternion orientation of earth frame relative to auxiliary frame. 236 | AEq_1 = 1; 237 | AEq_2 = 0; 238 | AEq_3 = 0; 239 | AEq_4 = 0; 240 | 241 | //Estimated orientation quaternion elements with initial conditions. 242 | SEq_1 = 1; 243 | SEq_2 = 0; 244 | SEq_3 = 0; 245 | SEq_4 = 0; 246 | 247 | } 248 | -------------------------------------------------------------------------------- /IMUfilter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Aaron Berk 3 | * 4 | * @section LICENSE 5 | * 6 | * Copyright (c) 2010 ARM Limited 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | * 26 | * @section DESCRIPTION 27 | * 28 | * IMU orientation filter developed by Sebastian Madgwick. 29 | * 30 | * Find more details about his paper here: 31 | * 32 | * http://code.google.com/p/imumargalgorithm30042010sohm/ 33 | */ 34 | 35 | #ifndef IMU_FILTER_H 36 | #define IMU_FILTER_H 37 | 38 | /** 39 | * Includes 40 | */ 41 | 42 | #include 43 | #include "macrodefs.h" 44 | 45 | /** 46 | * Defines 47 | */ 48 | #define PI 3.1415926536 49 | 50 | /** 51 | * IMU orientation filter. 52 | */ 53 | class IMUfilter { 54 | 55 | public: 56 | 57 | /** 58 | * Constructor. 59 | * 60 | * Initializes filter variables. 61 | * 62 | * @param rate The rate at which the filter should be updated. 63 | * @param gyroscopeMeasurementError The error of the gyroscope in degrees 64 | * per second. This used to calculate a tuning constant for the filter. 65 | * Try changing this value if there are jittery readings, or they change 66 | * too much or too fast when rotating the IMU. 67 | */ 68 | IMUfilter(double rate, double gyroscopeMeasurementError); 69 | 70 | /** 71 | * Update the filter variables. 72 | * 73 | * @param w_x X-axis gyroscope reading in rad/s. 74 | * @param w_y Y-axis gyroscope reading in rad/s. 75 | * @param w_z Z-axis gyroscope reading in rad/s. 76 | * @param a_x X-axis accelerometer reading in m/s/s. 77 | * @param a_y Y-axis accelerometer reading in m/s/s. 78 | * @param a_z Z-axis accelerometer reading in m/s/s. 79 | */ 80 | void updateFilter(double w_x, double w_y, double w_z, 81 | double a_x, double a_y, double a_z); 82 | 83 | /** 84 | * Compute the Euler angles based on the current filter data. 85 | */ 86 | void computeEuler(void); 87 | 88 | /** 89 | * Get the current roll. 90 | * 91 | * @return The current roll angle in radians. 92 | */ 93 | double getRoll(void); 94 | 95 | /** 96 | * Get the current roll. 97 | * 98 | * @return The current roll angle in degrees. 99 | */ 100 | double getRollInDegrees(void); 101 | 102 | /** 103 | * Get the current pitch. 104 | * 105 | * @return The current pitch angle in radians. 106 | */ 107 | double getPitch(void); 108 | 109 | /** 110 | * Get the current pitch. 111 | * 112 | * @return The current pitch angle in degrees. 113 | */ 114 | double getPitchInDegrees(void); 115 | 116 | /** 117 | * Get the current yaw. 118 | * 119 | * @return The current yaw angle in radians. 120 | */ 121 | double getYaw(void); 122 | 123 | /** 124 | * Get the current yaw. 125 | * 126 | * @return The current yaw angle in degrees. 127 | */ 128 | double getYawInDegrees(void); 129 | 130 | /** 131 | * Reset the filter. 132 | */ 133 | void reset(void); 134 | 135 | private: 136 | 137 | int firstUpdate; 138 | 139 | //Quaternion orientation of earth frame relative to auxiliary frame. 140 | double AEq_1; 141 | double AEq_2; 142 | double AEq_3; 143 | double AEq_4; 144 | 145 | //Estimated orientation quaternion elements with initial conditions. 146 | double SEq_1; 147 | double SEq_2; 148 | double SEq_3; 149 | double SEq_4; 150 | 151 | //Sampling period 152 | double deltat; 153 | 154 | //Gyroscope measurement error (in degrees per second). 155 | double gyroMeasError; 156 | 157 | //Compute beta (filter tuning constant.. 158 | double beta; 159 | 160 | double phi; 161 | double theta; 162 | double psi; 163 | 164 | }; 165 | 166 | #endif /* IMU_FILTER_H */ 167 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Lihang Li 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OpenIMUFilter 2 | ============= 3 | 4 | A Project aimed to demo filters for IMU(the complementary filter, the Kalman filter and the Mahony&Madgwick filter) with lots of references and tutorials. 5 | 6 | ## References 7 | ### IMU 8 | #### Tutorials And Algorithms 9 | * [A Guide To using IMU (Accelerometer and Gyroscope Devices) in Embedded Applications](http://www.starlino.com/imu_guide.html) 10 | * [Arduino code for IMU Guide algorithm. Using a 5DOF IMU (accelerometer and gyroscope combo)](http://www.starlino.com/imu_kalman_arduino.html) 11 | * [DCM Tutorial – An Introduction to Orientation Kinematics](http://www.starlino.com/dcm_tutorial.html) 12 | * [IMU Data Fusing: Complementary, Kalman, and Mahony Filter](http://www.olliw.eu/2013/imu-data-fusing/) 13 | 14 | #### IMU Products 15 | * [x-IMU From X-IO Technologies](http://www.x-io.co.uk/products/x-imu/#!prettyPhoto) 16 | * [IMU Brick - TinkerForge](http://www.tinkerforge.com/en/doc/Hardware/Bricks/IMU_Brick.html) 17 | * [New Open source IMU - PIXHAWK](https://pixhawk.ethz.ch/blog/new_open_source_imu_inertial_measurement_unit) 18 | * [mbed cookbook for IMU](http://mbed.org/cookbook/IMU) 19 | 20 | #### Source Code 21 | * [Open source IMU and AHRS algorithms From X-IO Technologies](http://www.x-io.co.uk/open-source-imu-and-ahrs-algorithms/) 22 | * [Orientation estimation algorithms for IMUs (accelerometers and gyroscopes) and MARG sensor arrays (accelerometers, gyroscopes and magnetometers)](https://code.google.com/p/imumargalgorithm30042010sohm/) 23 | * [mbed IMUfilter](http://mbed.org/users/aberk/code/IMUfilter/) 24 | * [Example-Sketch-for-IMU-including-Kalman-filter From TKJElectronics](https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter) 25 | * [KalmanFilter From TKJElectronics](https://github.com/TKJElectronics/KalmanFilter) 26 | * [openahrs](https://github.com/cbecker/openahrs) 27 | 28 | #### Calibration 29 | * [Industrial Grade Sensor Calibration From VectorNav](http://www.vectornav.com/support/library?id=86) 30 | 31 | ### Qt 32 | #### Timers 33 | * [Timers - Qt 4.8 Docs](http://qt-project.org/doc/qt-4.8/timers.html) 34 | 35 | #### QThread 36 | * [How To Really, Truly Use QThreads; The Full Explanation](http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/) 37 | * [How to Use QThread in the Right Way (Part 1)](http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/) 38 | * [How to Use QThread in the Right Way (Part 2)](http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-2/) 39 | * [Qt thread: simple, complete and stable (with full sources on GitHub)](http://fabienpn.wordpress.com/2013/05/01/qt-thread-simple-and-stable-with-sources/) 40 | * [纠正你的QThread 的使用方法](http://blog.csdn.net/hustyangju/article/details/9491639) 41 | 42 | #### Plotter 43 | * [QCustomPlot](http://www.qcustomplot.com/index.php/introduction) 44 | 45 | #### Console Application 46 | * [QT Console Application Template Tutorial](http://treyweaver.blogspot.com/2013/02/qt-console-application-template-tutorial.html) 47 | * [How to write a nice console application with Qt and Qt Creator](http://www.lubby.org/ebooks/qtconsoleapp2/qtconsoleapp2.html) 48 | * [A non-GUI example - Qt Docs](http://doc.qt.digia.com/solutions/4/qtsingleapplication/qtsinglecoreapplication-example-console.html) 49 | 50 | ### C++ 51 | #### Exception Handling 52 | * [Understanding C++ Exception Handling](http://www.gamedev.net/page/resources/_/technical/general-programming/understanding-c-exception-handling-r953) 53 | * [C++处理异常技巧-try,catch,throw,finally](http://blog.csdn.net/renwotao2009/article/details/6751687) 54 | 55 | #### Floating Number Exception 56 | * [打印浮点数输出 1.#IND 1.#INF nan inf 1.#QNAN SNaN等解决](http://hayyoungsue.blog.163.com/blog/static/12384097720123662438501/) 57 | * [浮点异常值:NAN,QNAN,SNAN](http://www.cnblogs.com/konlil/archive/2011/07/06/2099646.html) 58 | -------------------------------------------------------------------------------- /devicefilter.cpp: -------------------------------------------------------------------------------- 1 | #include "devicefilter.h" 2 | 3 | deviceFilter::deviceFilter() 4 | { 5 | // Initialization for variables 6 | showVerboseInfo = FALSE; 7 | 8 | totalReceivedFrames = 0; 9 | totalReceivedID66 = 0; 10 | totalReceivedID67 = 0; 11 | totalReceivedID69 = 0; 12 | 13 | // Initialization for Accel and Gyro 14 | std::cout << "Now Initializing Accel..." << std::endl; 15 | initializeAcceleromter(); 16 | std::cout << "Done!" << endl; 17 | 18 | std::cout << "Now Initializing Gyro..." << std::endl; 19 | initializeGyroscope(); 20 | std::cout << "Done!" << std::endl; 21 | 22 | std::cout << "Now calibrating Gyro and Accel for Zeor Offset.." << std::endl; 23 | //calibrateGyroAndAccel(); 24 | std::cout << "Done!" << std::endl; 25 | 26 | _sampleTimer = new QTimer(this); 27 | connect(_sampleTimer, SIGNAL(timeout()), this, SLOT(sampleGyroAndAccel())); 28 | //connect(_sampleTimer, SIGNAL(timeout()), this, SLOT(testSampleTimer())); 29 | 30 | _filterTimer = new QTimer(this); 31 | //connect(_filterTimer, SIGNAL(timeout()), this, SLOT(naiveIntegrationFilter())); 32 | connect(_filterTimer, SIGNAL(timeout()), this, SLOT(filterUpdateAndCalc())); 33 | //connect(_filterTimer, SIGNAL(timeout()), this, SLOT(testFilterTimer())); 34 | 35 | _sampleTimer->start(TIMER_INTERVAL); 36 | _filterTimer->start(TIMER_INTERVAL); 37 | } 38 | 39 | deviceFilter::~deviceFilter() 40 | { 41 | if(_sampleTimer){ 42 | delete _sampleTimer; 43 | } 44 | 45 | if(_filterTimer){ 46 | delete _filterTimer; 47 | } 48 | 49 | if(_usbCANDevice){ 50 | if(_usbCANDevice->closeDevice()){ 51 | std::cout << "Device Closed!" << endl; 52 | } 53 | else{ 54 | _usbCANDevice->showErrorInfo(); 55 | } 56 | 57 | delete _usbCANDevice; 58 | } 59 | if(_imuFilter){ 60 | delete _imuFilter; 61 | } 62 | } 63 | 64 | void deviceFilter::sampleGyroAndAccel() 65 | { 66 | w_xAccumulator = 0.0; 67 | w_yAccumulator = 0.0; 68 | w_zAccumulator = 0.0; 69 | 70 | a_xAccumulator = 0.0; 71 | a_yAccumulator = 0.0; 72 | a_zAccumulator = 0.0; 73 | 74 | totalReceivedID66 = 0; 75 | totalReceivedID67 = 0; 76 | totalReceivedID69 = 0; 77 | 78 | if(_usbCANDevice->getReceiveNumber()){ 79 | recNumber = _usbCANDevice->getUnreadFramesNumber(); 80 | } 81 | else{ 82 | _usbCANDevice->showErrorInfo(); 83 | } 84 | 85 | if(_usbCANDevice->receiveData(vco, recNumber)){ 86 | receivedFrames = _usbCANDevice->getReveivedFramsNumber(); 87 | totalReceivedFrames += receivedFrames; 88 | 89 | for(unsigned int i = 0; i < receivedFrames; i++){ 90 | if(vco[i].ID == GYRO_X_Y){ 91 | totalReceivedID66++; 92 | 93 | // Gyro X and Y Rate in Raw format 94 | gyroXLong = vco[i].Data[3] << 24 | vco[i].Data[2] << 16 | vco[i].Data[1] << 8 | vco[i].Data[0]; 95 | gyroYLong = vco[i].Data[7] << 24 | vco[i].Data[6] << 16 | vco[i].Data[5] << 8 | vco[i].Data[4]; 96 | 97 | // Real Gyro X and Y Rate 98 | gyroRateX = gyroXLong * GYRO_RATE_LSB; 99 | gyroRateY = gyroYLong * GYRO_RATE_LSB; 100 | 101 | // Accumulator 102 | w_xAccumulator += gyroRateX; 103 | w_yAccumulator += gyroRateY; 104 | 105 | //w_xAccumulator += gyroRateX - w_xBias; 106 | //w_yAccumulator += gyroRateY - w_yBias; 107 | } 108 | else if(vco[i].ID == GYRO_Z_Temp){ 109 | totalReceivedID67++; 110 | 111 | // Gyro Z Rate in Raw format 112 | gyroZLong = vco[i].Data[3] << 24 | vco[i].Data[2] << 16 | vco[i].Data[1] << 8 | vco[i].Data[0]; 113 | tempOfIMULong = vco[i].Data[7]; 114 | 115 | // Real Gyro Z Rate 116 | gyroRateZ = gyroZLong * GYRO_RATE_LSB; 117 | tempIMU = tempOfIMULong * TEMP_IMU_LSB; 118 | 119 | // Accumulator 120 | w_zAccumulator += gyroRateZ; 121 | 122 | //w_zAccumulator += gyroRateZ - w_zBias; 123 | } 124 | else if(vco[i].ID == ACCEL_X_Y_Z){ 125 | totalReceivedID69++; 126 | 127 | // Accel X, Y, Z Rate in Raw format 128 | accelXLong = vco[i].Data[1] << 8 | vco[i].Data[0]; 129 | accelYLong = vco[i].Data[3] << 8 | vco[i].Data[2]; 130 | accelZLong = vco[i].Data[5] << 8 | vco[i].Data[4]; 131 | 132 | // Real Accel X, Y, Z Rate 133 | accelRateX = accelXLong * ACCEL_RATE_LSB; 134 | accelRateY = accelYLong * ACCEL_RATE_LSB; 135 | accelRateZ = accelZLong * ACCEL_RATE_LSB; 136 | 137 | // Accumulator 138 | a_xAccumulator += accelRateX; 139 | a_yAccumulator += accelRateY; 140 | a_zAccumulator += accelRateZ; 141 | 142 | //a_xAccumulator += accelRateX - a_xBias; 143 | //a_yAccumulator += accelRateY - a_yBias; 144 | //a_zAccumulator += accelRateZ - a_zBias; 145 | } 146 | else{ 147 | std::cout << "No defined frame ID received!" << std::endl; 148 | } 149 | } 150 | 151 | // Return the averaged rates 152 | 153 | // degree/s 154 | if(totalReceivedID66 != 0){ 155 | w_x = w_xAccumulator/totalReceivedID66; 156 | w_y = w_yAccumulator/totalReceivedID66; 157 | 158 | w_x_last = w_x; 159 | w_y_last = w_y; 160 | } 161 | else{ 162 | w_x = w_x_last; 163 | w_y = w_y_last; 164 | } 165 | 166 | if(totalReceivedID67 != 0){ 167 | w_z = w_zAccumulator/totalReceivedID67; 168 | 169 | w_z_last = w_z; 170 | } 171 | else{ 172 | w_z = w_z_last; 173 | } 174 | 175 | // rad/s 176 | w_x_rad_s = toRadians(w_x); 177 | w_y_rad_s = toRadians(w_y); 178 | w_z_rad_s = toRadians(w_z); 179 | 180 | // g 181 | if(totalReceivedID69 != 0){ 182 | a_x = a_xAccumulator/totalReceivedID69; 183 | a_y = a_yAccumulator/totalReceivedID69; 184 | a_z = a_zAccumulator/totalReceivedID69; 185 | } 186 | else{ 187 | a_x = a_x_last; 188 | a_y = a_y_last; 189 | a_z = a_z_last; 190 | } 191 | 192 | // m/s/s 193 | a_x_m_ss = a_x * g0; 194 | a_y_m_ss = a_y * g0; 195 | a_z_m_ss = a_z * g0; 196 | 197 | /* 198 | cout << w_x << " " 199 | << w_y << " " 200 | << w_z << " " 201 | << a_x << " " 202 | << a_y << " " 203 | << a_z << endl; 204 | */ 205 | 206 | emit postGyroAndAccelData(w_x, w_y, w_z, a_x, a_y, a_z); 207 | 208 | } 209 | else{ 210 | _usbCANDevice->showErrorInfo(); 211 | } 212 | } 213 | 214 | void deviceFilter::filterUpdateAndCalc() 215 | { 216 | //Sample Gyro and Accel Data 217 | //sampleGyroAndAccel(); 218 | 219 | // Update the filter variables 220 | _imuFilter->updateFilter(w_x_rad_s, w_y_rad_s, w_z_rad_s, a_x_m_ss, a_y_m_ss, a_z_m_ss); 221 | _imuFilter->computeEuler(); 222 | showVerboseInfo && 223 | std::cout << "Pitch: " << _imuFilter->getPitch() << " " 224 | << "Yaw: " << _imuFilter->getYaw() << " " 225 | << "Roll: " << _imuFilter->getRoll() << std::endl; 226 | 227 | emit postFilterOrientationData(_imuFilter->getPitchInDegrees(), _imuFilter->getYawInDegrees(), _imuFilter->getRollInDegrees()); 228 | } 229 | 230 | void deviceFilter::naiveIntegrationFilter() 231 | { 232 | // Just do simple and stupid integration 233 | gyroOrientationX = gyroOrientationX + w_x * FILTER_RATE; 234 | gyroOrientationY = gyroOrientationY + w_y * FILTER_RATE; 235 | gyroOrientationZ = gyroOrientationZ + w_z * FILTER_RATE; 236 | 237 | // Debug for NAN 238 | //gyroOrientationX = gyroOrientationY = gyroOrientationZ = 90.0; 239 | 240 | cout << gyroOrientationX << " " << gyroOrientationY << " " << gyroOrientationZ << endl; 241 | emit postFilterOrientationData(gyroOrientationX, gyroOrientationY, gyroOrientationZ); 242 | 243 | } 244 | 245 | void deviceFilter::attachUsbCANDevice(USBCAN* usbCANDevice) 246 | { 247 | this->_usbCANDevice = usbCANDevice; 248 | } 249 | 250 | void deviceFilter::attachImuFilter(IMUfilter* imuFilter) 251 | { 252 | this->_imuFilter = imuFilter; 253 | } 254 | 255 | void deviceFilter::testSampleTimer() 256 | { 257 | std::cout << "sampleTimer Triggered!" << std::endl; 258 | } 259 | 260 | void deviceFilter::testFilterTimer() 261 | { 262 | std::cout << "filterTimer Triggered!" << std::endl; 263 | } 264 | 265 | void deviceFilter::initializeAcceleromter() 266 | { 267 | // Initialization of Accel 268 | 269 | a_x = 0.0; 270 | a_y = 0.0; 271 | a_z = 0.0; 272 | 273 | a_x_last = 0.0; 274 | a_y_last = 0.0; 275 | a_z_last = 0.0; 276 | 277 | a_x_m_ss = 0.0; 278 | a_y_m_ss = 0.0; 279 | a_z_m_ss = 0.0; 280 | 281 | a_xBias = 0.0; 282 | a_yBias = 0.0; 283 | a_zBias = 0.0; 284 | 285 | a_xAccumulator = 0.0; 286 | a_yAccumulator = 0.0; 287 | a_zAccumulator = 0.0; 288 | 289 | accelXLong = 0; 290 | accelYLong = 0; 291 | accelZLong = 0; 292 | 293 | accelRateX = 0.0; 294 | accelRateY = 0.0; 295 | accelRateZ = 0.0; 296 | } 297 | 298 | void deviceFilter::calibrateAccelerometer() 299 | { 300 | // Calibration of Accel to calculate the Bias 301 | std::cout << "Please use calibrateGyroAndAccel instead!" << std::endl; 302 | } 303 | 304 | void deviceFilter::initializeGyroscope() 305 | { 306 | // Initialization of Gyro 307 | 308 | w_x = 0.0; 309 | w_y = 0.0; 310 | w_z = 0.0; 311 | 312 | 313 | w_x_last = 0.0; 314 | w_y_last = 0.0; 315 | w_z_last = 0.0; 316 | 317 | w_x_rad_s = 0.0; 318 | w_y_rad_s = 0.0; 319 | w_z_rad_s = 0.0; 320 | 321 | w_xBias = 0; 322 | w_yBias = 0; 323 | w_zBias = 0; 324 | 325 | w_xAccumulator = 0.0; 326 | w_yAccumulator = 0.0; 327 | w_zAccumulator = 0.0; 328 | 329 | gyroXLong = 0.0; 330 | gyroYLong = 0.0; 331 | gyroZLong = 0.0; 332 | 333 | gyroRateX = 0.0; 334 | gyroRateY = 0.0; 335 | gyroRateZ = 0.0; 336 | 337 | gyroOrientationX = 0.0; 338 | gyroOrientationY = 0.0; 339 | gyroOrientationZ = 0.0; 340 | } 341 | 342 | void deviceFilter::calibrateGyroscope() 343 | { 344 | // Calibration of Gyro to calculate the Bias 345 | std::cout << "Please use calibrateGyroAndAccel instead!" << std::endl; 346 | } 347 | 348 | void deviceFilter::calibrateGyroAndAccel() 349 | { 350 | 351 | w_xAccumulator = 0.0; 352 | w_yAccumulator = 0.0; 353 | w_zAccumulator = 0.0; 354 | 355 | a_xAccumulator = 0.0; 356 | a_yAccumulator = 0.0; 357 | a_zAccumulator = 0.0; 358 | 359 | w_xBias = 0.0; 360 | w_yBias = 0.0; 361 | w_zBias = 0.0; 362 | 363 | a_xBias = 0.0; 364 | a_yBias = 0.0; 365 | a_zBias = 0.0; 366 | 367 | totalReceivedID66 = 0; 368 | totalReceivedID67 = 0; 369 | totalReceivedID69 = 0; 370 | 371 | totalReceivedFrames = 0; 372 | 373 | bool calibrationDone = FALSE; 374 | 375 | while(!calibrationDone){ 376 | 377 | 378 | if(_usbCANDevice->getReceiveNumber()){ 379 | recNumber = _usbCANDevice->getUnreadFramesNumber(); 380 | } 381 | else{ 382 | _usbCANDevice->showErrorInfo(); 383 | } 384 | 385 | if(_usbCANDevice->receiveData(vco, recNumber)){ 386 | receivedFrames = _usbCANDevice->getReveivedFramsNumber(); 387 | totalReceivedFrames += receivedFrames; 388 | 389 | for(unsigned int i = 0; i < receivedFrames; i++){ 390 | if(vco[i].ID == GYRO_X_Y){ 391 | totalReceivedID66++; 392 | 393 | // Gyro X and Y Rate in Raw format 394 | gyroXLong = vco[i].Data[3] << 24 | vco[i].Data[2] << 16 | vco[i].Data[1] << 8 | vco[i].Data[0]; 395 | gyroYLong = vco[i].Data[7] << 24 | vco[i].Data[6] << 16 | vco[i].Data[5] << 8 | vco[i].Data[4]; 396 | 397 | // Real Gyro X and Y Rate 398 | gyroRateX = gyroXLong * GYRO_RATE_LSB; 399 | gyroRateY = gyroYLong * GYRO_RATE_LSB; 400 | 401 | // Accumulator 402 | w_xAccumulator += gyroRateX; 403 | w_yAccumulator += gyroRateY; 404 | } 405 | else if(vco[i].ID == GYRO_Z_Temp){ 406 | totalReceivedID67++; 407 | 408 | // Gyro Z Rate in Raw format 409 | gyroZLong = vco[i].Data[3] << 24 | vco[i].Data[2] << 16 | vco[i].Data[1] << 8 | vco[i].Data[0]; 410 | tempOfIMULong = vco[i].Data[7]; 411 | 412 | // Real Gyro Z Rate 413 | gyroRateZ = gyroZLong * GYRO_RATE_LSB; 414 | tempIMU = tempOfIMULong * TEMP_IMU_LSB; 415 | 416 | // Accumulator 417 | w_zAccumulator += gyroRateZ; 418 | } 419 | else if(vco[i].ID == ACCEL_X_Y_Z){ 420 | totalReceivedID69++; 421 | 422 | // Accel X, Y, Z Rate in Raw format 423 | accelXLong = vco[i].Data[1] << 8 | vco[i].Data[0]; 424 | accelYLong = vco[i].Data[3] << 8 | vco[i].Data[2]; 425 | accelZLong = vco[i].Data[5] << 8 | vco[i].Data[4]; 426 | 427 | // Real Accel X, Y, Z Rate 428 | accelRateX = accelXLong * ACCEL_RATE_LSB; 429 | accelRateY = accelYLong * ACCEL_RATE_LSB; 430 | accelRateZ = accelZLong * ACCEL_RATE_LSB; 431 | 432 | // Accumulator 433 | a_xAccumulator += accelRateX; 434 | a_yAccumulator += accelRateY; 435 | a_zAccumulator += accelRateZ; 436 | } 437 | else{ 438 | std::cout << "No defined frame ID received!" << std::endl; 439 | } 440 | } 441 | 442 | } 443 | else{ 444 | _usbCANDevice->showErrorInfo(); 445 | } 446 | 447 | // Return the averaged rates 448 | if(totalReceivedFrames >= SAMPLE_FRAMES_FOR_CALIBRATION){ 449 | // Jump out of While Loop 450 | calibrationDone = TRUE; 451 | } 452 | else{ 453 | // Go on sampling 454 | } 455 | 456 | } 457 | 458 | // degree/s 459 | if(totalReceivedID66 != 0){ 460 | w_xBias = w_xAccumulator/totalReceivedID66; 461 | w_yBias = w_yAccumulator/totalReceivedID66; 462 | } 463 | else{ 464 | std::cerr << "receive Frames with ID 0x66 Error!" << std::endl; 465 | } 466 | 467 | if(totalReceivedID67 != 0){ 468 | w_zBias = w_zAccumulator/totalReceivedID67; 469 | } 470 | else{ 471 | std::cerr << "receive Frames with ID 0x67 Error!" << std::endl; 472 | } 473 | 474 | // g 475 | if(totalReceivedID69 != 0){ 476 | a_xBias = a_xAccumulator/totalReceivedID69; 477 | a_yBias = a_yAccumulator/totalReceivedID69; 478 | a_zBias = a_zAccumulator/totalReceivedID69; 479 | } 480 | else{ 481 | std::cerr << "receive Frames with ID 0x69 Error!" << std::endl; 482 | } 483 | 484 | std::cout << "Calibration Done and Zero Offset perspectively: " << endl; 485 | 486 | std::cout << "Gyro X Bias: " << w_xBias << endl; 487 | std::cout << "Gyro Y Bias: " << w_yBias << endl; 488 | std::cout << "Gyro Z Bias: " << w_zBias << endl; 489 | 490 | std::cout << "Accel X Bias: " << a_xBias << endl; 491 | std::cout << "Accel Y Bias: " << a_yBias << endl; 492 | std::cout << "Accel Z Bias: " << a_zBias << endl; 493 | } 494 | 495 | void deviceFilter::setBiasForGyroAndAccel(double gyroXBias, double gyroYBias, double gyroZBias, double accelXBias, double accelYBias, double accelZBias) 496 | { 497 | w_xBias = gyroXBias; 498 | w_yBias = gyroYBias; 499 | w_zBias = gyroZBias; 500 | 501 | a_xBias = accelXBias; 502 | a_yBias = accelYBias; 503 | a_zBias = accelZBias; 504 | } 505 | -------------------------------------------------------------------------------- /devicefilter.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICEFILTER_H 2 | #define DEVICEFILTER_H 3 | 4 | #include 5 | #include 6 | #include "usbcan.h" 7 | #include "IMUfilter.h" 8 | #include "macrodefs.h" 9 | 10 | using namespace std; 11 | 12 | class deviceFilter : public QObject 13 | { 14 | Q_OBJECT 15 | public: 16 | deviceFilter(); 17 | ~deviceFilter(); 18 | 19 | signals: 20 | void postGyroAndAccelData(double gyroRateX, double gyroRateY, double gyroRateZ, double accelRateX, double accelRateY, double accelRateZ); 21 | void postFilterOrientationData(double pitch, double yaw, double roll); 22 | 23 | public slots: 24 | void filterUpdateAndCalc(); 25 | void sampleGyroAndAccel(); 26 | 27 | public slots: 28 | void testSampleTimer(); 29 | void testFilterTimer(); 30 | 31 | void naiveIntegrationFilter(); 32 | 33 | private: 34 | QTimer* _sampleTimer; 35 | QTimer* _filterTimer; 36 | 37 | USBCAN* _usbCANDevice; 38 | IMUfilter* _imuFilter; 39 | 40 | public: 41 | void attachUsbCANDevice(USBCAN* usbCANDevice); 42 | void attachImuFilter(IMUfilter *imuFilter); 43 | void setBiasForGyroAndAccel(double gyroXBias, double gyroYBias, double gyroZBias, double accelXBias, double accelYBias, double accelZBias); 44 | 45 | public: 46 | 47 | //Offsets for the gyroscope. 48 | //The readings we take when the gyroscope is stationary won't be 0, so we'll 49 | //average a set of readings we do get when the gyroscope is stationary and 50 | //take those away from subsequent readings to ensure the gyroscope is offset 51 | //or "biased" to 0. 52 | double w_xBias; 53 | double w_yBias; 54 | double w_zBias; 55 | 56 | //Offsets for the accelerometer. 57 | //Same as with the gyroscope. 58 | double a_xBias; 59 | double a_yBias; 60 | double a_zBias; 61 | 62 | //Accumulators used for oversampling and then averaging. 63 | volatile double a_xAccumulator; 64 | volatile double a_yAccumulator; 65 | volatile double a_zAccumulator; 66 | volatile double w_xAccumulator; 67 | volatile double w_yAccumulator; 68 | volatile double w_zAccumulator; 69 | 70 | //Accelerometer and gyroscope readings for x, y, z axes. 71 | volatile double a_x; 72 | volatile double a_y; 73 | volatile double a_z; 74 | volatile double w_x; 75 | volatile double w_y; 76 | volatile double w_z; 77 | 78 | // Last reading 79 | volatile double a_x_last; 80 | volatile double a_y_last; 81 | volatile double a_z_last; 82 | volatile double w_x_last; 83 | volatile double w_y_last; 84 | volatile double w_z_last; 85 | 86 | volatile double a_x_m_ss; 87 | volatile double a_y_m_ss; 88 | volatile double a_z_m_ss; 89 | volatile double w_x_rad_s; 90 | volatile double w_y_rad_s; 91 | volatile double w_z_rad_s; 92 | 93 | //Buffer for accelerometer readings. 94 | int readings[3]; 95 | //Number of accelerometer samples we're on. 96 | int accelerometerSamples; 97 | //Number of gyroscope samples we're on. 98 | int gyroscopeSamples; 99 | 100 | // Orientation for X, Y, Z(Pitch, Yaw and Roll) 101 | double gyroOrientationX; 102 | double gyroOrientationY; 103 | double gyroOrientationZ; 104 | 105 | /** 106 | * Prototypes 107 | */ 108 | //Set up the ADXL345 appropriately. 109 | void initializeAcceleromter(void); 110 | 111 | //Calculate the null bias. 112 | void calibrateAccelerometer(void); 113 | 114 | //Take a set of samples and average them. 115 | void sampleAccelerometer(void); 116 | 117 | //Set up the ITG3200 appropriately. 118 | void initializeGyroscope(void); 119 | 120 | //Calculate the null bias. 121 | void calibrateGyroscope(void); 122 | 123 | //Take a set of samples and average them. 124 | void sampleGyroscope(void); 125 | 126 | // Calculate the null bias for both Gyro and Accel 127 | void calibrateGyroAndAccel(void); 128 | 129 | // Take a set of samples both for Gyro and Accel 130 | //void sampleGyroAndAccel(void); 131 | 132 | //Update the filter and calculate the Euler angles. 133 | //void filterUpdateAndCalc(void); 134 | 135 | public: 136 | 137 | // Variables for calculating IMU-F100A5 angles 138 | unsigned long totalReceivedFrames; 139 | unsigned long totalReceivedID66; 140 | unsigned long totalReceivedID67; 141 | unsigned long totalReceivedID69; 142 | 143 | int iterateTimes; 144 | 145 | signed long gyroXLong; 146 | signed long gyroYLong; 147 | signed long gyroZLong; 148 | 149 | signed long tempOfIMULong; 150 | 151 | signed short accelXLong; 152 | signed short accelYLong; 153 | signed short accelZLong; 154 | double gyroRateX; 155 | double gyroRateY; 156 | double gyroRateZ; 157 | 158 | double accelRateX; 159 | double accelRateY; 160 | double accelRateZ; 161 | 162 | double tempIMU; 163 | 164 | public: 165 | 166 | VCI_CAN_OBJ vco[1000]; 167 | DWORD recNumber; 168 | DWORD receivedFrames; 169 | 170 | public: 171 | bool showVerboseInfo; 172 | }; 173 | 174 | #endif // DEVICEFILTER_H 175 | -------------------------------------------------------------------------------- /kerneldlls/CAN232.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/CAN232.dll -------------------------------------------------------------------------------- /kerneldlls/CANETE.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/CANETE.dll -------------------------------------------------------------------------------- /kerneldlls/CANET_TCP.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/CANET_TCP.dll -------------------------------------------------------------------------------- /kerneldlls/PC104C2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/PC104C2.dll -------------------------------------------------------------------------------- /kerneldlls/PC104CAN.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/PC104CAN.dll -------------------------------------------------------------------------------- /kerneldlls/PCI5121.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/PCI5121.dll -------------------------------------------------------------------------------- /kerneldlls/gisadll.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/gisadll.dll -------------------------------------------------------------------------------- /kerneldlls/gpcidll.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/gpcidll.dll -------------------------------------------------------------------------------- /kerneldlls/isa5420.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/isa5420.dll -------------------------------------------------------------------------------- /kerneldlls/kerneldll.ini: -------------------------------------------------------------------------------- 1 | [KERNELDLL] 2 | COUNT=24 3 | 1=PCI5121.dll 4 | 2=PCI9810B.dll 5 | 3=USBCAN.dll 6 | 4=USBCAN.dll 7 | 5=PCI9820B.dll 8 | 6=CAN232.dll 9 | 7=PCI5121.dll 10 | 8=CANLite.dll 11 | 9=ISA9620B.dll 12 | 10=ISA5420.dll 13 | 11=PC104CAN.dll 14 | 12=CANETE.dll 15 | 13=DNP9810B.dll 16 | 14=PCI9840B.dll 17 | 15=PC104C2.dll 18 | 16=PCI9820I.dll 19 | 17=CANET_TCP.dll 20 | 18=pec9920.dll 21 | 19=pci50xx_u.dll 22 | 20=USBCAN_E.dll 23 | 21=USBCAN_E.dll 24 | 22=pci50xx_u.dll 25 | 23=topcliff_can.dll 26 | 24=pcie9221.dll 27 | -------------------------------------------------------------------------------- /kerneldlls/usbcan.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcalm/OpenIMUFilter/32c89faee3532642f1c7515bf644b8910e4d17d9/kerneldlls/usbcan.dll -------------------------------------------------------------------------------- /macrodefs.h: -------------------------------------------------------------------------------- 1 | #ifndef MACRODEFS_H 2 | #define MACRODEFS_H 3 | 4 | // CAN Frame Micro Defines 5 | #define GYRO_X_Y 0x00000066 6 | #define GYRO_Z_Temp 0x00000067 7 | #define ACCEL_X_Y_Z 0x00000069 8 | 9 | #define GYRO_FULL_32_BIT ((unsigned int)(0xFFFFFFFF)) 10 | #define ACCEL_FULL_16_BIT ((unsigned int)(0xFFFF)) 11 | 12 | #define GYRO_RATE_LSB 0.001 13 | #define ACCEL_RATE_LSB 0.0001 14 | #define TEMP_IMU_LSB 1 15 | 16 | /* Blow macros are imported from http://mbed.org/cookbook/IMU and may not be used 17 | */ 18 | 19 | //Gravity at Earth's surface in m/s/s 20 | #define g0 9.812865328 21 | 22 | //Number of samples to average. 23 | #define SAMPLES 4 24 | 25 | //Number of samples to be averaged for a null bias calculation 26 | //during calibration. 27 | #define CALIBRATION_SAMPLES 128 28 | 29 | //Convert from radians to degrees. 30 | #define toDegrees(x) (x * 57.2957795) 31 | 32 | //Convert from degrees to radians. 33 | #define toRadians(x) (x * 0.01745329252) 34 | 35 | //ITG-3200 sensitivity is 14.375 LSB/(degrees/sec). 36 | #define GYROSCOPE_GAIN (1 / 14.375) 37 | 38 | //Full scale resolution on the ADXL345 is 4mg/LSB. 39 | #define ACCELEROMETER_GAIN (0.004 * g0) 40 | 41 | //Sampling gyroscope at 200Hz. 42 | #define GYRO_RATE 0.005 43 | 44 | //Sampling accelerometer at 200Hz. 45 | #define ACC_RATE 0.005 46 | 47 | //Updating filter at 1/FILTER_RATE Hz. 48 | #define FILTER_RATE 0.01 49 | 50 | // Timer Interval, namely 1000*FILTER_RATE 51 | #define TIMER_INTERVAL 10 52 | 53 | // Sample Frames for Calibration 54 | #define SAMPLE_FRAMES_FOR_CALIBRATION 10000 55 | 56 | #endif // MACRODEFS_H 57 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "devicefilter.h" 10 | 11 | using namespace std; 12 | 13 | // Variables for calculating IMU-F100A5 angles 14 | qint64 totalReceivedFrames = 0; 15 | qint64 totalReceivedID66 = 0; 16 | qint64 totalReceivedID67 = 0; 17 | qint64 totalReceivedID69 = 0; 18 | 19 | int iterateTimes = 100; 20 | 21 | double gyroXAccumulator = 0.0; 22 | double gyroYAccumulator = 0.0; 23 | double gyroZAccumulator = 0.0; 24 | 25 | double gyroXBias = 0.0; 26 | double gyroYBias = 0.0; 27 | double gyroZBias = 0.0; 28 | 29 | double accelXAccumulator = 0.0; 30 | double accelYAccumulator = 0.0; 31 | double accelZAccumulator = 0.0; 32 | 33 | double accelXBias = 0.0; 34 | double accelYBias = 0.0; 35 | double accelZBias = 0.0; 36 | 37 | signed long gyroXLong = 0; 38 | signed long gyroYLong = 0; 39 | signed long gyroZLong = 0; 40 | 41 | signed long tempOfIMULong = 0; 42 | 43 | signed short accelXLong = 0; 44 | signed short accelYLong = 0; 45 | signed short accelZLong = 0; 46 | double gyroRateX = 0; 47 | double gyroRateY = 0; 48 | double gyroRateZ = 0; 49 | 50 | double accelRateX = 0; 51 | double accelRateY = 0; 52 | double accelRateZ = 0; 53 | 54 | double tempIMU = 0; 55 | 56 | IMUfilter *imuFilter; 57 | USBCAN* usbCANDevice; 58 | 59 | int main(int argc, char *argv[]) 60 | { 61 | QApplication a(argc, argv); 62 | MainWindow w; 63 | w.show(); 64 | 65 | cout << "Get Pitch, Yaw, Roll using IMU Filter..." << endl; 66 | 67 | // Open file for log 68 | ofstream outfile("seq_data.txt"); 69 | if(!outfile){ 70 | cerr << "Open Log File Failed!" << endl; 71 | } 72 | else{ 73 | cout << "Log File Ready!" << endl; 74 | } 75 | 76 | // Get USBCAN-I+ to work 77 | usbCANDevice = new USBCAN(USBCAN::_nDefaultDevType, USBCAN::_nDefaultDevIndex, USBCAN::_nDefaultReserved); 78 | 79 | // Open Device 80 | if(usbCANDevice->openDevice()){ 81 | cout << "Device Opened Succesfully!" << endl; 82 | } 83 | else{ 84 | usbCANDevice->showErrorInfo(); 85 | } 86 | 87 | // Initialize Device 88 | PVCI_INIT_CONFIG pInitConfig = new VCI_INIT_CONFIG; 89 | pInitConfig->AccCode = 0; 90 | pInitConfig->AccMask = 0xFFFFFFFF; 91 | pInitConfig->Filter = 1; 92 | pInitConfig->Mode = 0; 93 | pInitConfig->Timing0 = 0x00; 94 | pInitConfig->Timing1 = 0x14; 95 | 96 | if(usbCANDevice->initCAN(pInitConfig)){ 97 | cout << "Device Initialized Successfuly!" << endl; 98 | } 99 | else{ 100 | cout<< "Device Initialized Failed!" << endl; 101 | usbCANDevice->showErrorInfo(); 102 | usbCANDevice->closeDevice(); 103 | } 104 | 105 | // Clear Device buffer first 106 | if(usbCANDevice->clearBuffer()){ 107 | cout << "Device buffer cleard!" << endl; 108 | } 109 | else{ 110 | usbCANDevice->showErrorInfo(); 111 | } 112 | 113 | // Start Communication 114 | VCI_CAN_OBJ vco[1000]; 115 | DWORD recNumber; 116 | DWORD receivedFrames; 117 | 118 | try 119 | { 120 | if(usbCANDevice->startCAN()){ 121 | cout << "Begin to grab Frames..." << endl; 122 | 123 | QElapsedTimer timer; 124 | qint64 nanoSec; 125 | timer.start(); 126 | 127 | while(TRUE && iterateTimes){ 128 | if(usbCANDevice->getReceiveNumber()){ 129 | recNumber = usbCANDevice->getUnreadFramesNumber(); 130 | } 131 | else{ 132 | usbCANDevice->showErrorInfo(); 133 | } 134 | 135 | if(usbCANDevice->receiveData(vco, recNumber)){ 136 | receivedFrames = usbCANDevice->getReveivedFramsNumber(); 137 | totalReceivedFrames += receivedFrames; 138 | 139 | for(unsigned int i = 0; i < receivedFrames; i++){ 140 | if(vco[i].ID == GYRO_X_Y){ 141 | totalReceivedID66++; 142 | 143 | // Gyro X and Y Rate in Raw format 144 | gyroXLong = vco[i].Data[3] << 24 | vco[i].Data[2] << 16 | vco[i].Data[1] << 8 | vco[i].Data[0]; 145 | gyroYLong = vco[i].Data[7] << 24 | vco[i].Data[6] << 16 | vco[i].Data[5] << 8 | vco[i].Data[4]; 146 | 147 | // Real Gyro X and Y Rate 148 | gyroRateX = gyroXLong * GYRO_RATE_LSB; 149 | gyroRateY = gyroYLong * GYRO_RATE_LSB; 150 | 151 | gyroXAccumulator += gyroRateX; 152 | gyroYAccumulator += gyroRateY; 153 | } 154 | else if(vco[i].ID == GYRO_Z_Temp){ 155 | totalReceivedID67++; 156 | 157 | // Gyro Z Rate in Raw format 158 | gyroZLong = vco[i].Data[3] << 24 | vco[i].Data[2] << 16 | vco[i].Data[1] << 8 | vco[i].Data[0]; 159 | tempOfIMULong = vco[i].Data[7]; 160 | 161 | // Real Gyro Z Rate 162 | gyroRateZ = gyroZLong * GYRO_RATE_LSB; 163 | tempIMU = tempOfIMULong * TEMP_IMU_LSB; 164 | 165 | gyroZAccumulator += gyroRateZ; 166 | } 167 | else if(vco[i].ID == ACCEL_X_Y_Z){ 168 | totalReceivedID69++; 169 | 170 | // Accel X, Y, Z Rate in Raw format 171 | accelXLong = vco[i].Data[1] << 8 | vco[i].Data[0]; 172 | accelYLong = vco[i].Data[3] << 8 | vco[i].Data[2]; 173 | accelZLong = vco[i].Data[5] << 8 | vco[i].Data[4]; 174 | 175 | // Real Accel X, Y, Z Rate 176 | accelRateX = accelXLong * ACCEL_RATE_LSB; 177 | accelRateY = accelYLong * ACCEL_RATE_LSB; 178 | accelRateZ = accelZLong * ACCEL_RATE_LSB; 179 | 180 | accelXAccumulator += accelRateX; 181 | accelYAccumulator += accelRateY; 182 | accelZAccumulator += accelRateZ; 183 | } 184 | else{ 185 | cout << "No defined frame ID received!" << endl; 186 | } 187 | } 188 | 189 | // Output Data Every Iteration 190 | FALSE && 191 | cout << "Rates: " << gyroRateX << " " << gyroRateY << " " << gyroRateZ << " " 192 | << accelRateX << " " << accelRateY << " " << accelRateZ << " " 193 | << endl; 194 | } 195 | else{ 196 | usbCANDevice->showErrorInfo(); 197 | } 198 | 199 | if(totalReceivedFrames >= SAMPLE_FRAMES_FOR_CALIBRATION){ 200 | break; 201 | } 202 | else{ 203 | // Go On Sampling 204 | } 205 | } 206 | 207 | nanoSec = timer.nsecsElapsed(); 208 | cout << "Grabbed " << totalReceivedFrames << " in " << nanoSec << " nano seconds!" << endl; 209 | cout << "Grabbed " << totalReceivedID66 << " Frames with ID " << "0x66" << endl; 210 | cout << "Grabbed " << totalReceivedID67 << " Frames with ID " << "0x67" << endl; 211 | cout << "Grabbed " << totalReceivedID69 << " Frames with ID " << "0x69" << endl; 212 | cout << "Frame rates is " << totalReceivedFrames * 1000000000 / nanoSec << endl; 213 | 214 | 215 | 216 | gyroXBias = gyroXAccumulator/totalReceivedID66; 217 | gyroYBias = gyroYAccumulator/totalReceivedID66; 218 | gyroZBias = gyroYAccumulator/totalReceivedID67; 219 | 220 | accelXBias = accelXAccumulator/totalReceivedID69; 221 | accelYBias = accelYAccumulator/totalReceivedID69; 222 | accelZBias = accelYAccumulator/totalReceivedID69; 223 | 224 | std::cout << "Calibration Done and Zero Offset perspectively: " << endl; 225 | 226 | std::cout << "Gyro X Bias: " << gyroXBias << endl; 227 | std::cout << "Gyro Y Bias: " << gyroYBias << endl; 228 | std::cout << "Gyro Z Bias: " << gyroZBias << endl; 229 | 230 | std::cout << "Accel X Bias: " << accelXBias << endl; 231 | std::cout << "Accel Y Bias: " << accelYBias << endl; 232 | std::cout << "Accel Z Bias: " << accelZBias << endl; 233 | } 234 | else{ 235 | usbCANDevice->showErrorInfo(); 236 | } 237 | } 238 | catch(std::exception& e){ 239 | qDebug()<attachUsbCANDevice(usbCANDevice); 249 | imuDeviceFilter->attachImuFilter(imuFilter); 250 | imuDeviceFilter->setBiasForGyroAndAccel(gyroXBias, gyroYBias, gyroZBias, accelXBias, accelYBias, accelZBias); 251 | 252 | QObject::connect(imuDeviceFilter, SIGNAL(postGyroAndAccelData(double,double,double,double,double,double)), &w, SLOT(updateGyroAndAccelData(double,double,double,double,double,double))); 253 | QObject::connect(imuDeviceFilter, SIGNAL(postFilterOrientationData(double,double,double)), &w, SLOT(updateFilterOrientationData(double,double,double))); 254 | 255 | imuDeviceFilter->moveToThread(imuDeviceFilterThread); 256 | imuDeviceFilterThread->start(); 257 | 258 | // Check if we have unread frames 259 | if(usbCANDevice->getReceiveNumber()){ 260 | cout << "Have " << usbCANDevice->getUnreadFramesNumber() << " unread frames left!" << endl; 261 | } 262 | else{ 263 | usbCANDevice->showErrorInfo(); 264 | } 265 | 266 | // Close Device 267 | /* 268 | if(usbCANDevice->closeDevice()){ 269 | cout << "Device Closed!" << endl; 270 | } 271 | else{ 272 | usbCANDevice->showErrorInfo(); 273 | } 274 | */ 275 | 276 | return a.exec(); 277 | } 278 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | #include 4 | #include 5 | 6 | MainWindow::MainWindow(QWidget *parent) : 7 | QMainWindow(parent), 8 | ui(new Ui::MainWindow) 9 | { 10 | ui->setupUi(this); 11 | 12 | QTimer* timeUpdater = new QTimer(this); 13 | connect(timeUpdater, SIGNAL(timeout()), this, SLOT(updateCurrentTime())); 14 | timeUpdater->start(1000); 15 | } 16 | 17 | MainWindow::~MainWindow() 18 | { 19 | delete ui; 20 | } 21 | 22 | void MainWindow::updateCurrentTime() 23 | { 24 | QDateTime currentTime = QDateTime::currentDateTime(); 25 | QString currentTimeString = currentTime.toString("yyyy-MM-dd hh:mm:ss dddd"); 26 | ui->label_currentTime->setText(currentTimeString); 27 | } 28 | 29 | void MainWindow::updateGyroAndAccelData(double gyroRateX, double gyroRateY, double gyroRateZ, double accelRateX, double accelRateY, double accelRateZ) 30 | { 31 | ui->lineEdit_Gyro_X->setText(QString::number(gyroRateX)); 32 | ui->lineEdit_Gyro_Y->setText(QString::number(gyroRateY)); 33 | ui->lineEdit_Gyro_Z->setText(QString::number(gyroRateZ)); 34 | 35 | ui->lineEdit_Accel_X->setText(QString::number(accelRateX)); 36 | ui->lineEdit_Accel_Y->setText(QString::number(accelRateY)); 37 | ui->lineEdit_Accel_Z->setText(QString::number(accelRateZ)); 38 | } 39 | 40 | void MainWindow::updateFilterOrientationData(double pitch, double yaw, double roll) 41 | { 42 | ui->lineEdit_Gyro_Orientation_X->setText(QString::number(pitch)); 43 | ui->lineEdit_Gyro_Orientation_Y->setText(QString::number(yaw)); 44 | ui->lineEdit_Gyro_Orientation_Z->setText(QString::number(roll)); 45 | } 46 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class MainWindow; 8 | } 9 | 10 | class MainWindow : public QMainWindow 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit MainWindow(QWidget *parent = 0); 16 | ~MainWindow(); 17 | 18 | private: 19 | Ui::MainWindow *ui; 20 | 21 | private slots: 22 | void updateCurrentTime(); 23 | 24 | public slots: 25 | void updateGyroAndAccelData(double gyroRateX, double gyroRateY, double gyroRateZ, double accelRateX, double accelRateY, double accelRateZ); 26 | void updateFilterOrientationData(double pitch, double yaw, double roll); 27 | }; 28 | 29 | #endif // MAINWINDOW_H 30 | -------------------------------------------------------------------------------- /mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 719 10 | 518 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 40 21 | 30 22 | 46 23 | 13 24 | 25 | 26 | 27 | 加速度计 28 | 29 | 30 | 31 | 32 | 33 | 220 34 | 30 35 | 46 36 | 13 37 | 38 | 39 | 40 | 陀螺仪 41 | 42 | 43 | 44 | 45 | 46 | 220 47 | 160 48 | 46 49 | 13 50 | 51 | 52 | 53 | 角度 54 | 55 | 56 | 57 | 58 | 59 | 40 60 | 160 61 | 46 62 | 13 63 | 64 | 65 | 66 | 位移 67 | 68 | 69 | 70 | 71 | 72 | 20 73 | 180 74 | 16 75 | 71 76 | 77 | 78 | 79 | 80 | 81 | 82 | X 83 | 84 | 85 | 86 | 87 | 88 | 89 | Y 90 | 91 | 92 | 93 | 94 | 95 | 96 | Z 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 190 106 | 181 107 | 16 108 | 71 109 | 110 | 111 | 112 | 113 | 114 | 115 | X 116 | 117 | 118 | 119 | 120 | 121 | 122 | Y 123 | 124 | 125 | 126 | 127 | 128 | 129 | Z 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 208 139 | 181 140 | 135 141 | 74 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 40 160 | 180 161 | 135 162 | 74 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 20 181 | 430 182 | 281 183 | 16 184 | 185 | 186 | 187 | TextLabel 188 | 189 | 190 | 191 | 192 | 193 | 208 194 | 51 195 | 135 196 | 74 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 190 215 | 51 216 | 16 217 | 71 218 | 219 | 220 | 221 | 222 | 223 | 224 | X 225 | 226 | 227 | 228 | 229 | 230 | 231 | Y 232 | 233 | 234 | 235 | 236 | 237 | 238 | Z 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 40 248 | 50 249 | 135 250 | 74 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 20 269 | 50 270 | 16 271 | 71 272 | 273 | 274 | 275 | 276 | 277 | 278 | X 279 | 280 | 281 | 282 | 283 | 284 | 285 | Y 286 | 287 | 288 | 289 | 290 | 291 | 292 | Z 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 0 303 | 0 304 | 719 305 | 21 306 | 307 | 308 | 309 | 310 | 311 | TopToolBarArea 312 | 313 | 314 | false 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | -------------------------------------------------------------------------------- /usbcan.cpp: -------------------------------------------------------------------------------- 1 | #include "usbcan.h" 2 | 3 | USBCAN::USBCAN() 4 | { 5 | // Default constructor, doing nothing 6 | } 7 | 8 | USBCAN::USBCAN(DWORD nDevType, DWORD nDevIndex, DWORD nReserved) 9 | { 10 | // Constructor 11 | //std::cout << "Constructing USBCAN Device..." << std::endl; 12 | 13 | this->_nDevType = nDevType; 14 | this->_nDevIndex = nDevIndex; 15 | this->_nCANIndex = USBCAN::_nDefaultCANIndex; 16 | this->_nReserved = nReserved; 17 | this->_isOpened = FALSE; 18 | this->_isErrorInfoReady = FALSE; 19 | 20 | // Pointer of varies of structures 21 | this->_pInitConfig = NULL; 22 | this->_pBoardInfo = NULL; 23 | this->_pCANStatus = NULL; 24 | this->_pErrorInfo = NULL; 25 | this->_pFilterRecord = NULL; 26 | 27 | // Need memory for Error Report 28 | this->_pErrorInfo = new VCI_ERR_INFO; 29 | 30 | // Pointer to the data buffer 31 | this->_pVCO = NULL; 32 | 33 | //std::cout << "Device construct complete!" << std::endl; 34 | } 35 | 36 | bool USBCAN::openDevice() 37 | { 38 | 39 | if(this->_isOpened){ 40 | return TRUE; 41 | } 42 | else{ 43 | DWORD dwRet; 44 | dwRet = VCI_OpenDevice(this->_nDevType, this->_nDevIndex, this->_nReserved); 45 | this->_retCode = dwRet; 46 | if(dwRet == STATUS_OK){ 47 | this->_isOpened = true; 48 | this->_nCANIndex += 1; 49 | 50 | /* 51 | std::cout << "Device Opened Successfully!" << std::endl; 52 | std::cout << "Device Type: " << this->_nDevType << std::endl; 53 | std::cout << "Device Index: " << this->_nDevIndex << std::endl; 54 | std::cout << "CAN Index: " << this->_nCANIndex<< std::endl; 55 | */ 56 | 57 | return true; 58 | } 59 | else{ 60 | this->readErrorInfo(this->_pErrorInfo); 61 | return FALSE; 62 | } 63 | } 64 | } 65 | 66 | bool USBCAN::initCAN(PVCI_INIT_CONFIG pInitConfig) 67 | { 68 | if(this->_isOpened){ 69 | DWORD dwRet; 70 | this->_pInitConfig = pInitConfig; 71 | std::cout << this->_pInitConfig << std::endl; 72 | std::cout << this->_pInitConfig->AccCode << std::endl; 73 | std::cout << this->_pInitConfig->AccMask << std::endl; 74 | 75 | dwRet = VCI_InitCAN(this->_nDevType, this->_nDevIndex, this->_nCANIndex, this->_pInitConfig); 76 | this->_retCode = dwRet; 77 | if(dwRet == STATUS_OK){ 78 | //std::cout << "Device initialized successfully!" << std::endl; 79 | this->_isInitialized = TRUE; 80 | return TRUE; 81 | } 82 | else{ 83 | this->readErrorInfo(this->_pErrorInfo); 84 | return FALSE; 85 | } 86 | } 87 | else{ 88 | std::cout << "Please open the device before initializing!" << std::endl; 89 | return FALSE; 90 | } 91 | } 92 | 93 | bool USBCAN::startCAN() 94 | { 95 | if(this->_isInitialized){ 96 | DWORD dwRet; 97 | dwRet = VCI_StartCAN(this->_nDevType, this->_nDevIndex, this->_nCANIndex); 98 | this->_retCode = dwRet; 99 | if(dwRet == STATUS_OK){ 100 | this->_isStarted = TRUE; 101 | return TRUE; 102 | } 103 | else{ 104 | this->readErrorInfo(this->_pErrorInfo); 105 | return FALSE; 106 | } 107 | } 108 | else{ 109 | return FALSE; 110 | } 111 | } 112 | 113 | bool USBCAN::getReceiveNumber() 114 | { 115 | if(this->_isInitialized){ 116 | DWORD dwRet; 117 | dwRet = VCI_GetReceiveNum(this->_nDevType, this->_nDevIndex, this->_nCANIndex); 118 | this->_retCode = dwRet; 119 | this->_unReadFramesNumber = dwRet; 120 | return TRUE; 121 | } 122 | else{ 123 | return FALSE; 124 | } 125 | } 126 | 127 | bool USBCAN::receiveData(PVCI_CAN_OBJ pReceive, ULONG len, INT waitTime) 128 | { 129 | if(this->_isStarted){ 130 | DWORD dwRet; 131 | dwRet = VCI_Receive(this->_nDevType, this->_nDevIndex, this->_nCANIndex, pReceive, len, waitTime); 132 | this->_retCode = dwRet; 133 | if(dwRet == 0xFFFFFFFF){ 134 | return FALSE; 135 | } 136 | else{ 137 | this->_receivedFramesNumber = dwRet; 138 | return TRUE; 139 | } 140 | } 141 | else{ 142 | return FALSE; 143 | } 144 | } 145 | 146 | bool USBCAN::clearBuffer() 147 | { 148 | if(this->_isInitialized){ 149 | DWORD dwRet; 150 | dwRet = VCI_ClearBuffer(this->_nDevType, this->_nDevIndex, this->_nCANIndex); 151 | this->_retCode = dwRet; 152 | if(dwRet){ 153 | return TRUE; 154 | } 155 | else{ 156 | return FALSE; 157 | } 158 | } 159 | else{ 160 | return FALSE; 161 | } 162 | } 163 | 164 | bool USBCAN::resetCAN() 165 | { 166 | if(this->_isStarted){ 167 | DWORD dwRet; 168 | dwRet = VCI_ResetCAN(this->_nDevType, this->_nDevIndex, this->_nCANIndex); 169 | this->_retCode = dwRet; 170 | if(dwRet){ 171 | return TRUE; 172 | } 173 | else{ 174 | return FALSE; 175 | } 176 | } 177 | else{ 178 | return FALSE; 179 | } 180 | } 181 | 182 | bool USBCAN::closeDevice() 183 | { 184 | if(this->_isClosed){ 185 | return TRUE; 186 | } 187 | else{ 188 | DWORD dwRet; 189 | dwRet = VCI_CloseDevice(this->_nDevType, this->_nDevIndex); 190 | this->_retCode = dwRet; 191 | if(dwRet){ 192 | this->_isClosed = TRUE; 193 | this->_nDevIndex = USBCAN::_nDefaultCANIndex; 194 | return TRUE; 195 | } 196 | else{ 197 | return FALSE; 198 | } 199 | } 200 | } 201 | 202 | bool USBCAN::readBoardInfo(PVCI_BOARD_INFO pInfo) 203 | { 204 | if(this->_isInitialized){ 205 | DWORD dwRet; 206 | dwRet = VCI_ReadBoardInfo(this->_nDevType, this->_nDevIndex, pInfo); 207 | this->_retCode = dwRet; 208 | if(dwRet){ 209 | return TRUE; 210 | } 211 | else{ 212 | return FALSE; 213 | } 214 | } 215 | else{ 216 | return FALSE; 217 | } 218 | } 219 | 220 | bool USBCAN::readCANStatus(PVCI_CAN_STATUS pCANStatus) 221 | { 222 | if(this->_isInitialized){ 223 | DWORD dwRet; 224 | dwRet = VCI_ReadCANStatus(this->_nDevType, this->_nDevIndex, this->_nCANIndex, pCANStatus); 225 | this->_retCode = dwRet; 226 | if(dwRet){ 227 | return TRUE; 228 | } 229 | else{ 230 | return FALSE; 231 | } 232 | } 233 | else{ 234 | return FALSE; 235 | } 236 | } 237 | 238 | bool USBCAN::getReference(DWORD refType, PVOID pData) 239 | { 240 | if(this->_isInitialized){ 241 | DWORD dwRet; 242 | dwRet = VCI_GetReference(this->_nDevType, this->_nDevIndex, this->_nCANIndex, refType, pData); 243 | this->_retCode = dwRet; 244 | if(dwRet){ 245 | return TRUE; 246 | } 247 | else{ 248 | return FALSE; 249 | } 250 | } 251 | else{ 252 | return FALSE; 253 | } 254 | } 255 | 256 | bool USBCAN::setReference(DWORD refType, PVOID pData) 257 | { 258 | if(this->_isInitialized){ 259 | DWORD dwRet; 260 | dwRet = VCI_SetReference(this->_nDevType, this->_nDevIndex, this->_nCANIndex, refType, pData); 261 | this->_retCode = dwRet; 262 | if(dwRet){ 263 | return TRUE; 264 | } 265 | else{ 266 | return FALSE; 267 | } 268 | } 269 | else{ 270 | return FALSE; 271 | } 272 | } 273 | 274 | bool USBCAN::readErrorInfo(PVCI_ERR_INFO pErrInfo) 275 | { 276 | DWORD dwRet; 277 | dwRet = VCI_ReadErrInfo(this->_nDevType, this->_nDevIndex, this->_nCANIndex, pErrInfo); 278 | this->_retCode = dwRet; 279 | if(dwRet){ 280 | this->_isErrorInfoReady = TRUE; 281 | return TRUE; 282 | } 283 | else{ 284 | this->_isErrorInfoReady = FALSE; 285 | return FALSE; 286 | } 287 | } 288 | 289 | void USBCAN::showErrorInfo() 290 | { 291 | std::cout << "Last return code: " << this->_retCode; 292 | std::cout << " Error code: " << this->_pErrorInfo->ErrCode; 293 | std::cout << std::endl; 294 | } 295 | 296 | void USBCAN::showBoardInfo() 297 | { 298 | // Show basic information about USBCAN-I+ 299 | } 300 | 301 | void USBCAN::showCANStatus() 302 | { 303 | // Show current status of USBCAN-I+ 304 | } 305 | 306 | USBCAN::~USBCAN() 307 | { 308 | if(this->_pVCO){ 309 | delete this->_pVCO; 310 | this->_pVCO = NULL; 311 | } 312 | 313 | if(this->_pBoardInfo){ 314 | delete this->_pBoardInfo; 315 | this->_pBoardInfo = NULL; 316 | } 317 | 318 | if(this->_pCANStatus){ 319 | delete this->_pCANStatus; 320 | this->_pCANStatus = NULL; 321 | } 322 | 323 | if(this->_pErrorInfo){ 324 | delete this->_pErrorInfo; 325 | this->_pErrorInfo = NULL; 326 | } 327 | 328 | if(this->_pFilterRecord){ 329 | delete this->_pFilterRecord; 330 | this->_pFilterRecord = NULL; 331 | } 332 | 333 | if(this->_pInitConfig){ 334 | delete this->_pInitConfig; 335 | this->_pInitConfig = NULL; 336 | } 337 | } 338 | -------------------------------------------------------------------------------- /usbcan.h: -------------------------------------------------------------------------------- 1 | #ifndef USBCAN_H 2 | #define USBCAN_H 3 | 4 | #include 5 | //#include 6 | //#include 7 | #include 8 | #include "ControlCAN.h" 9 | 10 | class USBCAN 11 | { 12 | public: 13 | USBCAN(); 14 | ~USBCAN(); 15 | 16 | USBCAN(DWORD nDevType, DWORD nDevIndex, DWORD nReserved); 17 | 18 | /** 19 | * @brief openDevice 20 | * @param nDevType 21 | * @param nDevIndex 22 | * @param reserved 23 | * @return 24 | */ 25 | bool openDevice(); 26 | 27 | /** 28 | * @brief closeDevice 29 | * @param nDevType 30 | * @param DevIndex 31 | * @return 32 | */ 33 | bool closeDevice(); 34 | 35 | /** 36 | * @brief initCAN 37 | * @param nDevType 38 | * @param nDevIndex 39 | * @param nCANIndex 40 | * @param pInitConfig 41 | * @return 42 | */ 43 | bool initCAN(PVCI_INIT_CONFIG pInitConfig); 44 | 45 | /** 46 | * @brief startCAN 47 | * @param nDevType 48 | * @param nDevIndex 49 | * @param nCANIndex 50 | * @return 51 | */ 52 | bool startCAN(); 53 | 54 | /** 55 | * @brief getReceiveNumber 56 | * @param nDevType 57 | * @param nDevIndex 58 | * @param nCANIndex 59 | * @return 60 | */ 61 | bool getReceiveNumber(); 62 | 63 | /** 64 | * @brief clearBuffer 65 | * @param nDevType 66 | * @param nDevIndex 67 | * @param nCANIndex 68 | * @return 69 | */ 70 | bool clearBuffer(); 71 | 72 | /** 73 | * @brief transmitData 74 | * @param nDevType 75 | * @param nDevIndex 76 | * @param nCANIndex 77 | * @param pSend 78 | * @param len 79 | * @return 80 | */ 81 | bool transmitData(PVCI_CAN_OBJ pSend, ULONG len); 82 | 83 | /** 84 | * @brief transmitData 85 | * @param nDevType 86 | * @param nDevIndex 87 | * @param nCANIndex 88 | * @param pReceive 89 | * @param len 90 | * @param waitTime 91 | * @return 92 | */ 93 | bool receiveData(PVCI_CAN_OBJ pReceive, ULONG len, INT waitTime=-1); 94 | 95 | /** 96 | * @brief resetCAN 97 | * @param nDevType 98 | * @param nDevIndex 99 | * @param nCANIndex 100 | * @return 101 | */ 102 | bool resetCAN(); 103 | 104 | /** 105 | * @brief readBoardInfo 106 | * @param nDevType 107 | * @param nDevIndex 108 | * @param nCANIndex 109 | * @param pInfo 110 | * @return 111 | */ 112 | bool readBoardInfo(PVCI_BOARD_INFO pInfo); 113 | 114 | /** 115 | * @brief readErrorInfo 116 | * @param nDevType 117 | * @param nDevIndex 118 | * @param nCANIndex 119 | * @param pErrInfo 120 | * @return 121 | */ 122 | bool readErrorInfo(PVCI_ERR_INFO pErrInfo); 123 | 124 | /** 125 | * @brief readCANStatus 126 | * @param nDevType 127 | * @param nDevIndex 128 | * @param nCANIndex 129 | * @return 130 | */ 131 | bool readCANStatus(PVCI_CAN_STATUS pCANStatus); 132 | 133 | /** 134 | * @brief getReference 135 | * @param nDevType 136 | * @param nDevIndex 137 | * @param nCANIndex 138 | * @param refType 139 | * @param pData 140 | * @return 141 | */ 142 | bool getReference(DWORD refType, PVOID pData); 143 | 144 | /** 145 | * @brief setReference 146 | * @param nDevType 147 | * @param nDevIndex 148 | * @param nCANIndex 149 | * @param refType 150 | * @param pData 151 | * @return 152 | */ 153 | bool setReference(DWORD refType, PVOID pData); 154 | 155 | /** 156 | * @brief showErrorInfo 157 | */ 158 | void showErrorInfo(); 159 | 160 | /** 161 | * @brief showBoardInfo 162 | */ 163 | void showBoardInfo(); 164 | 165 | /** 166 | * @brief showCANStatus 167 | */ 168 | void showCANStatus(); 169 | 170 | /** 171 | * @brief getUnreadFramesNumber 172 | * @return 173 | */ 174 | ULONG getUnreadFramesNumber(){ 175 | return this->_unReadFramesNumber; 176 | } 177 | 178 | /** 179 | * @brief getTransmittedFramesNumber 180 | * @return 181 | */ 182 | ULONG getTransmittedFramesNumber(){ 183 | return this->_transmittedFramesNumber; 184 | } 185 | 186 | /** 187 | * @brief getReveivedFramsNumber 188 | * @return 189 | */ 190 | ULONG getReveivedFramsNumber(){ 191 | return this->_receivedFramesNumber; 192 | } 193 | 194 | /** 195 | * @brief getLastReturnCode 196 | * @return 197 | */ 198 | DWORD getLastReturnCode(){ 199 | return this->_retCode; 200 | } 201 | 202 | public: 203 | // Device Index 204 | const static DWORD _nDefaultDevType = VCI_USBCAN1; 205 | const static DWORD _nDefaultDevIndex = 0; 206 | const static DWORD _nDefaultCANIndex = -1; 207 | const static DWORD _nDefaultReserved = 0; 208 | 209 | private: 210 | DWORD _nDevType; 211 | DWORD _nDevIndex; 212 | DWORD _nCANIndex; 213 | // Varies of Structures 214 | PVCI_BOARD_INFO _pBoardInfo; 215 | PVCI_INIT_CONFIG _pInitConfig; 216 | PVCI_CAN_STATUS _pCANStatus; 217 | PVCI_ERR_INFO _pErrorInfo; 218 | PVCI_FILTER_RECORD _pFilterRecord; 219 | 220 | // Reference Type for setReference & getReference 221 | DWORD _nRefType; 222 | 223 | // Buffer for receiving and sending CAN Frames 224 | PVCI_CAN_OBJ _pVCO; 225 | VCI_CAN_OBJ _vco[1000]; 226 | 227 | // Check if the USBCAN device is opened or closed 228 | bool _isOpened; 229 | bool _isClosed; 230 | 231 | // Check if the USBCAN device is initialized 232 | bool _isInitialized; 233 | 234 | // Check if the USBCAN device is started 235 | bool _isStarted; 236 | 237 | // Check if the last read Error Info call is successful 238 | bool _isErrorInfoReady; 239 | 240 | // Number of frames unread in the USBCAN device 241 | ULONG _unReadFramesNumber; 242 | 243 | // Number of frames reveived in one receive call 244 | ULONG _receivedFramesNumber; 245 | 246 | // Number of frames transmitted in one receive call 247 | ULONG _transmittedFramesNumber; 248 | 249 | // Return code of normal API invokes 250 | DWORD _retCode; 251 | 252 | // Reseverd 253 | DWORD _nReserved; 254 | 255 | }; 256 | 257 | #endif // USBCAN_H 258 | --------------------------------------------------------------------------------