first commit
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
build/
|
||||
bin/
|
||||
.vscode/
|
||||
@@ -0,0 +1,213 @@
|
||||
#***********************************************************************
|
||||
#* Copyright (C) 2019 LP-Research
|
||||
#* All rights reserved.
|
||||
#* Contact: LP-Research (info@lp-research.com)
|
||||
#*
|
||||
#* This file is part of the Open Motion Analysis Toolkit (OpenMAT).
|
||||
#*
|
||||
#* Redistribution and use in source and binary forms, with
|
||||
#* or without modification, are permitted provided that the
|
||||
#* following conditions are met:
|
||||
#*
|
||||
#* Redistributions of source code must retain the above copyright
|
||||
#* notice, this list of conditions and the following disclaimer.
|
||||
#* Redistributions in binary form must reproduce the above copyright
|
||||
#* notice, this list of conditions and the following disclaimer in
|
||||
#* the documentation and/or other materials provided with the
|
||||
#* distribution.
|
||||
#*
|
||||
#* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
#* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
#* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
#* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
#* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
#* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
#* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
#* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
#* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
#* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
#* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#**********************************************************************/
|
||||
|
||||
cmake_minimum_required(VERSION 2.4.6)
|
||||
|
||||
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release" )
|
||||
|
||||
set(BUILD_ARCHITECTURE "32-bit" CACHE STRING "")
|
||||
#set(BUILD_ARCHITECTURE "64-bit" CACHE STRING "")
|
||||
set_property(CACHE BUILD_ARCHITECTURE PROPERTY STRINGS "32-bit" "64-bit")
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
project (LpmsIG1_OpenSourceLib)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
project (LpmsIG1_OpenSourceLibD)
|
||||
endif()
|
||||
|
||||
if(COMMAND cmake_policy)
|
||||
cmake_policy(SET CMP0003 NEW)
|
||||
cmake_policy(SET CMP0015 NEW)
|
||||
cmake_policy(SET CMP0040 NEW)
|
||||
endif(COMMAND cmake_policy)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
# Windows SDK
|
||||
set(WINDOWS_SDK_PATH "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A" CACHE STRING "")
|
||||
|
||||
# LpmsIG1
|
||||
include_directories("./")
|
||||
|
||||
ADD_DEFINITIONS(-DUSE_EIGEN)
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
ADD_DEFINITIONS(-DEIGEN_DONT_ALIGN_STATICALLY)
|
||||
ADD_DEFINITIONS(-D_WIN32_WINNT=0x05010200)
|
||||
ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
|
||||
ADD_DEFINITIONS(-DPLATFORM_X86)
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
ADD_DEFINITIONS(-DDLL_EXPORT)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast /O2")
|
||||
endif()
|
||||
|
||||
#link_directories("${WINDOWS_SDK_PATH}/Lib")
|
||||
endif()
|
||||
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(sources
|
||||
MicroMeasureWindows.cpp
|
||||
SerialPort.cpp
|
||||
LpmsIG1.cpp
|
||||
LpMatrix.c
|
||||
LpUtil.cpp
|
||||
version.rc
|
||||
)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(sources
|
||||
MicroMeasure.cpp
|
||||
SerialPortLinux.cpp
|
||||
LpmsIG1.cpp
|
||||
LpMatrix.c
|
||||
LpUtil.cpp
|
||||
version.rc
|
||||
)
|
||||
set(headers_linux_install
|
||||
LpMatrix.h
|
||||
LpmsIG1Registers.h
|
||||
SensorDataI.h
|
||||
LpmsIG1I.h
|
||||
LpLog.h
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
set(headers
|
||||
MicroMeasure.h
|
||||
SerialPort.h
|
||||
SensorData.h
|
||||
SensorDataI.h
|
||||
LpUtil.h
|
||||
LpmsIG1.h
|
||||
LpmsIG1I.h
|
||||
LpmsIG1Registers.h
|
||||
LpMatrix.h
|
||||
LpLog.h
|
||||
)
|
||||
|
||||
|
||||
# Silicon labs
|
||||
set(WINDOWS_SL_PATH "E:/openSourceLibSiliconLabs/MCU/USBXpress_SDK/Library/Host/Windows" CACHE STRING "")
|
||||
include_directories("${WINDOWS_SL_PATH}")
|
||||
link_directories("${WINDOWS_SL_PATH}/x86")
|
||||
find_library(SILABS_LIB SiUSBXp.lib PATHS "${WINDOWS_SL_PATH}/x86")
|
||||
|
||||
if (BUILD_ARCHITECTURE STREQUAL "32-bit")
|
||||
set(LIBRARY_OUTPUT_PATH ./ CACHE STRING "")
|
||||
set(EXECUTABLE_OUTPUT_PATH ./ CACHE STRING "")
|
||||
endif()
|
||||
|
||||
if (BUILD_ARCHITECTURE STREQUAL "64-bit")
|
||||
set(LIBRARY_OUTPUT_PATH ./ CACHE STRING "")
|
||||
set(EXECUTABLE_OUTPUT_PATH ./ CACHE STRING "")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -std=gnu++11")
|
||||
#SET ( CMAKE_CXX_FLAGS "-D_GLIBCXX_USE_CXX11_ABI=1" )
|
||||
endif()
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
if (BUILD_ARCHITECTURE STREQUAL "32-bit")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED ${sources} ${headers})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} Ws2_32.lib)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} SiUSBXp.lib)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED ${sources} ${headers})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} Ws2_32.lib)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} SiUSBXp.lib)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (BUILD_ARCHITECTURE STREQUAL "64-bit")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED ${sources} ${headers})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} Ws2_32.lib)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} SiUSBXp.lib)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED ${sources} ${headers})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} Ws2_32.lib)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} SiUSBXp.lib)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
||||
include(InstallRequiredSystemLibraries)
|
||||
set(MAJOR_VERSION "0")
|
||||
set(MINOR_VERSION "3")
|
||||
set(PATCH_VERSION "0")
|
||||
SET(CPACK_GENERATOR "DEB")
|
||||
SET(CPACK_PACKAGE_NAME "libLpmsIG1_OpenSource")
|
||||
set(CPACK_PACKAGE_VENDOR "LP-Research Inc. <www.lp-research.com>")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Library for communicating and interfacing with LP-Research sensors.")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/SUMMARY.txt")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${MAJOR_VERSION}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${MINOR_VERSION}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${PATCH_VERSION}")
|
||||
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "H.E. YAP <yap@lp-research.com>") #required
|
||||
|
||||
include(CPack)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED ${sources} ${headers})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} pthread)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} rt)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} udev)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED ${sources} ${headers})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} pthread)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} rt)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} udev)
|
||||
endif()
|
||||
|
||||
install(FILES ${headers_linux_install} DESTINATION include/lpsensor)
|
||||
|
||||
install(TARGETS ${CMAKE_PROJECT_NAME}
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,27 @@
|
||||
Copyright (C) 2019 LP-Research Inc.
|
||||
All rights reserved.
|
||||
Contact: LP-Research Inc.(info@lp-research.com)
|
||||
Homepage: http://www.lp-research.com
|
||||
|
||||
This file is part of the Open Motion Analysis Toolkit (OpenMAT).
|
||||
Redistribution and use in source and binary forms, with
|
||||
or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef LPLOG_H
|
||||
#define LPLOG_H
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <sstream>
|
||||
|
||||
// Verbose level
|
||||
enum {
|
||||
VERBOSE_NONE,
|
||||
VERBOSE_INFO,
|
||||
VERBOSE_DEBUG
|
||||
};
|
||||
|
||||
class LpLog
|
||||
{
|
||||
int verboseLevel;
|
||||
|
||||
public:
|
||||
static LpLog& getInstance()
|
||||
{
|
||||
static LpLog instance; // Guaranteed to be destroyed.
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
LpLog() {
|
||||
verboseLevel = VERBOSE_INFO;
|
||||
};
|
||||
|
||||
public:
|
||||
LpLog(LpLog const&) = delete;
|
||||
void operator=(LpLog const&) = delete;
|
||||
|
||||
void setVerbose(int level)
|
||||
{
|
||||
verboseLevel = level;
|
||||
}
|
||||
|
||||
void d(std::string tag, const char* str, ...)
|
||||
{
|
||||
if (verboseLevel < VERBOSE_DEBUG)
|
||||
return;
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %4s] [ %-8s]: ", "DBUG", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
|
||||
void i(std::string tag, const char* str, ...)
|
||||
{
|
||||
if (verboseLevel < VERBOSE_INFO)
|
||||
return;
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %4s] [ %-8s]: ", "INFO", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
|
||||
void e(std::string tag, const char* str, ...)
|
||||
{
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %4s] [ %-8s]: ", "ERR", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,134 @@
|
||||
/***********************************************************************
|
||||
** Copyright (C) 2019 LP-Research
|
||||
** All rights reserved.
|
||||
** Contact: LP-Research (info@lp-research.com)
|
||||
***********************************************************************/
|
||||
|
||||
#include "LpMatrix.h"
|
||||
|
||||
void createIdentity3x3(LpMatrix3x3f* dest)
|
||||
{
|
||||
matZero3x3(dest);
|
||||
|
||||
dest->data[0][0] = 1;
|
||||
dest->data[1][1] = 1;
|
||||
dest->data[2][2] = 1;
|
||||
}
|
||||
|
||||
void createIdentity4x4(LpMatrix4x4f* dest)
|
||||
{
|
||||
matZero4x4(dest);
|
||||
|
||||
dest->data[0][0] = 1;
|
||||
dest->data[1][1] = 1;
|
||||
dest->data[2][2] = 1;
|
||||
dest->data[3][3] = 1;
|
||||
}
|
||||
|
||||
void matZero3x3(LpMatrix3x3f* dest)
|
||||
{
|
||||
dest->data[0][0] = 0;
|
||||
dest->data[0][1] = 0;
|
||||
dest->data[0][2] = 0;
|
||||
|
||||
dest->data[1][0] = 0;
|
||||
dest->data[1][1] = 0;
|
||||
dest->data[1][2] = 0;
|
||||
|
||||
dest->data[2][0] = 0;
|
||||
dest->data[2][1] = 0;
|
||||
dest->data[2][2] = 0;
|
||||
}
|
||||
|
||||
void matZero3x4(LpMatrix3x4f* dest)
|
||||
{
|
||||
dest->data[0][0] = 0;
|
||||
dest->data[0][1] = 0;
|
||||
dest->data[0][2] = 0;
|
||||
dest->data[0][3] = 0;
|
||||
|
||||
dest->data[1][0] = 0;
|
||||
dest->data[1][1] = 0;
|
||||
dest->data[1][2] = 0;
|
||||
dest->data[1][3] = 0;
|
||||
|
||||
dest->data[2][0] = 0;
|
||||
dest->data[2][1] = 0;
|
||||
dest->data[2][2] = 0;
|
||||
dest->data[2][3] = 0;
|
||||
}
|
||||
|
||||
void matZero4x3(LpMatrix4x3f* dest)
|
||||
{
|
||||
dest->data[0][0] = 0;
|
||||
dest->data[0][1] = 0;
|
||||
dest->data[0][2] = 0;
|
||||
|
||||
dest->data[1][0] = 0;
|
||||
dest->data[1][1] = 0;
|
||||
dest->data[1][2] = 0;
|
||||
|
||||
dest->data[2][0] = 0;
|
||||
dest->data[2][1] = 0;
|
||||
dest->data[2][2] = 0;
|
||||
|
||||
dest->data[3][0] = 0;
|
||||
dest->data[3][1] = 0;
|
||||
dest->data[3][2] = 0;
|
||||
}
|
||||
|
||||
void matZero4x4(LpMatrix4x4f* dest)
|
||||
{
|
||||
dest->data[0][0] = 0;
|
||||
dest->data[0][1] = 0;
|
||||
dest->data[0][2] = 0;
|
||||
dest->data[0][3] = 0;
|
||||
|
||||
dest->data[1][0] = 0;
|
||||
dest->data[1][1] = 0;
|
||||
dest->data[1][2] = 0;
|
||||
dest->data[1][3] = 0;
|
||||
|
||||
dest->data[2][0] = 0;
|
||||
dest->data[2][1] = 0;
|
||||
dest->data[2][2] = 0;
|
||||
dest->data[2][3] = 0;
|
||||
|
||||
dest->data[3][0] = 0;
|
||||
dest->data[3][1] = 0;
|
||||
dest->data[3][2] = 0;
|
||||
dest->data[3][3] = 0;
|
||||
}
|
||||
|
||||
void vectZero3x1(LpVector3f* dest)
|
||||
{
|
||||
dest->data[0] = 0;
|
||||
dest->data[1] = 0;
|
||||
dest->data[2] = 0;
|
||||
}
|
||||
|
||||
void vectZero4x1(LpVector4f* dest)
|
||||
{
|
||||
dest->data[0] = 0;
|
||||
dest->data[1] = 0;
|
||||
dest->data[2] = 0;
|
||||
dest->data[3] = 0;
|
||||
}
|
||||
|
||||
#ifdef __WIN32
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
void print4x4(LpMatrix4x4f m)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
printf("%f, ", m.data[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
/***********************************************************************
|
||||
** Copyright (C) 2019 LP-Research
|
||||
** All rights reserved.
|
||||
** Contact: LP-Research (info@lp-research.com)
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef LP_MATRIX
|
||||
#define LP_MATRIX
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union _float2int {
|
||||
uint32_t u32_val;
|
||||
float float_val;
|
||||
} float2int;
|
||||
#endif
|
||||
|
||||
typedef struct _LpMatrix3x3f {
|
||||
float data[3][3];
|
||||
} LpMatrix3x3f;
|
||||
|
||||
typedef struct _LpMatrix3x4f {
|
||||
float data[3][4];
|
||||
} LpMatrix3x4f;
|
||||
|
||||
typedef struct _LpMatrix4x3f {
|
||||
float data[4][3];
|
||||
} LpMatrix4x3f;
|
||||
|
||||
typedef struct _LpMatrix4x4f {
|
||||
float data[4][4];
|
||||
} LpMatrix4x4f;
|
||||
|
||||
typedef struct _LpVector3f {
|
||||
float data[3];
|
||||
} LpVector3f;
|
||||
|
||||
typedef struct _LpVector4f {
|
||||
float data[4];
|
||||
} LpVector4f;
|
||||
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
typedef struct _LpVector3i {
|
||||
int16_t data[3];
|
||||
} LpVector3i;
|
||||
|
||||
typedef struct _LpVector4i {
|
||||
int16_t data[4];
|
||||
} LpVector4i;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void createIdentity3x3(LpMatrix3x3f* dest);
|
||||
void createIdentity4x4(LpMatrix4x4f* dest);
|
||||
void matZero3x3(LpMatrix3x3f* dest);
|
||||
void matZero4x4(LpMatrix4x4f* dest);
|
||||
void matZero3x4(LpMatrix3x4f* dest);
|
||||
void matZero4x3(LpMatrix4x3f* dest);
|
||||
void vectZero3x1(LpVector3f* dest);
|
||||
void vectZero4x1(LpVector4f* dest);
|
||||
|
||||
#ifdef __WIN32
|
||||
void print4x4(LpMatrix4x4f m)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "LpUtil.h"
|
||||
#include <iomanip>
|
||||
|
||||
/*
|
||||
void logd(std::string tag, const char* str, ...)
|
||||
{
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %-8s] ", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
*/
|
||||
|
||||
const std::string currentDateTime(const char* format)
|
||||
{
|
||||
time_t now = time(0);
|
||||
struct tm tstruct;
|
||||
char buf[80];
|
||||
tstruct = *localtime(&now);
|
||||
// Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
|
||||
// for more information about date/time format
|
||||
strftime(buf, sizeof(buf), format, &tstruct);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
const int currentDateTimeInt()
|
||||
{
|
||||
time_t now = time(0);
|
||||
struct tm tstruct;
|
||||
tstruct = *localtime(&now);
|
||||
// Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
|
||||
// for more information about date/time format
|
||||
int ret = (2000+tstruct.tm_year-100) * 10000 + (tstruct.tm_mon+1) * 100 + tstruct.tm_mday;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::string trimString(std::string s)
|
||||
{
|
||||
std::string ret = s;
|
||||
//ret.resize(ret.find('\0'));
|
||||
ret.erase(std::find(ret.begin(), ret.end(), '\0'), ret.end());
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "LpMatrix.h"
|
||||
|
||||
#define FORMAT_SPACE 0
|
||||
#define FORMAT_CSV 1
|
||||
#define FORMAT_YAML 2
|
||||
|
||||
|
||||
union float2char {
|
||||
float float_val;
|
||||
uint8_t c[4];
|
||||
};
|
||||
|
||||
|
||||
union double2char {
|
||||
double double_val;
|
||||
uint8_t c[8];
|
||||
};
|
||||
|
||||
union uint2char {
|
||||
uint32_t int_val;
|
||||
uint8_t c[4];
|
||||
};
|
||||
|
||||
union uint162char {
|
||||
uint16_t int_val;
|
||||
uint8_t c[2];
|
||||
};
|
||||
|
||||
union int2char {
|
||||
int int_val;
|
||||
uint8_t c[4];
|
||||
};
|
||||
|
||||
union cArray2intArray
|
||||
{
|
||||
int16_t int_val[5];
|
||||
uint8_t c[10];
|
||||
};
|
||||
|
||||
union floatArray2char {
|
||||
float float_val[6];
|
||||
uint32_t uint32_val[6];
|
||||
uint8_t c[24];
|
||||
};
|
||||
|
||||
//void logd(std::string tag, const char* str, ...);
|
||||
|
||||
const std::string currentDateTime(const char* format);
|
||||
const int currentDateTimeInt();
|
||||
|
||||
struct MyException : public std::exception
|
||||
{
|
||||
std::string s;
|
||||
MyException(std::string ss) : s(ss) {}
|
||||
~MyException() throw () {} // Updated
|
||||
const char* what() const throw() { return s.c_str(); }
|
||||
};
|
||||
|
||||
|
||||
std::string trimString(std::string s);
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,830 @@
|
||||
#ifndef LPMSIG1_H
|
||||
#define LPMSIG1_H
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#ifdef _WIN32
|
||||
#include <comutil.h>
|
||||
#endif
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "SerialPort.h"
|
||||
#include "MicroMeasure.h"
|
||||
#include "SensorData.h"
|
||||
#include "LpmsIG1Registers.h"
|
||||
|
||||
#include "LpmsIG1I.h"
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// LPMod bus
|
||||
///////////////////////////////////////
|
||||
#define LPPACKET_MAX_BUFFER 512
|
||||
enum {
|
||||
PACKET_START,
|
||||
PACKET_ADDRESS0,
|
||||
PACKET_ADDRESS1,
|
||||
PACKET_FUNCTION0,
|
||||
PACKET_FUNCTION1,
|
||||
PACKET_LENGTH0,
|
||||
PACKET_LENGTH1,
|
||||
PACKET_RAW_DATA,
|
||||
PACKET_LRC_CHECK0,
|
||||
PACKET_LRC_CHECK1,
|
||||
PACKET_END0,
|
||||
PACKET_END1
|
||||
};
|
||||
struct LPPacket
|
||||
{
|
||||
int rxState;
|
||||
uint16_t address;
|
||||
uint16_t length;
|
||||
uint16_t function;
|
||||
uint8_t data[LPPACKET_MAX_BUFFER];
|
||||
uint16_t rawDataIndex;
|
||||
uint16_t chksum;
|
||||
uint16_t cs;
|
||||
|
||||
|
||||
LPPacket()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
rxState = PACKET_START;
|
||||
address = 0;
|
||||
length = 0;
|
||||
function = 0;
|
||||
rawDataIndex = 0;
|
||||
chksum = 0;
|
||||
memset(data, 0, LPPACKET_MAX_BUFFER);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
CONNECTION_STATE_DISCONNECTED,
|
||||
CONNECTION_STATE_GET_SENSOR_INFO,
|
||||
CONNECTION_STATE_WAITING_SENSOR_INFO,
|
||||
CONNECTION_STATE_VALID_SENSOR_INFO,
|
||||
CONNECTION_STATE_TDR_ERROR,
|
||||
CONNECTION_STATE_FIRMWARE_UPDATE,
|
||||
CONNECTION_STATE_CONNECTED
|
||||
};
|
||||
|
||||
#define BYTE_START 0x3A
|
||||
#define BYTE_END0 0x0D
|
||||
#define BYTE_END1 0x0A
|
||||
|
||||
#define TDR_INVALID 0
|
||||
#define TDR_VALID 1
|
||||
#define TDR_UPDATING 2
|
||||
#define TDR_ERROR 3
|
||||
|
||||
// Others
|
||||
#define SAVE_DATA_LIMIT 720000 //2 hours at 100hz
|
||||
#define SENSOR_DATA_QUEUE_SIZE 10
|
||||
#define SENSOR_RESPONSE_QUEUE_SIZE 50
|
||||
#define FIRMWARE_PACKET_LENGTH 256
|
||||
|
||||
// Timeout settings (us)
|
||||
#define TIMEOUT_COMMAND_TIMER 10000 // 0.01 secs
|
||||
#define TIMEOUT_TDR_STATUS 5000000 // 5 secs
|
||||
#define TIMEOUT_FIRMWARE_UPDATE 2000000 // 2 secs
|
||||
#define TIMEOUT_IDLE 5000000 // 5 secs
|
||||
|
||||
// sensor response logic
|
||||
enum {
|
||||
WAIT_IGNORE ,
|
||||
WAIT_FOR_ACKNACK ,
|
||||
WAIT_FOR_DATA ,
|
||||
WAIT_FOR_TRANSMIT_DATA_REGISTER ,
|
||||
WAIT_FOR_CALIBRATION_DATA ,
|
||||
WAIT_FOR_SENSOR_SETTINGS ,
|
||||
WAIT_FOR_LPBUS_DATA_PRECISION ,
|
||||
WAIT_FOR_DEGRAD_OUTPUT ,
|
||||
|
||||
// Sensor Info
|
||||
WAIT_FOR_SERIAL_NUMBER,
|
||||
WAIT_FOR_SENSOR_MODEL,
|
||||
WAIT_FOR_FIRMWARE_INFO,
|
||||
WAIT_FOR_FILTER_VERSION,
|
||||
WAIT_FOR_IAP_CHECKSTATUS,
|
||||
|
||||
// Sensor Settings
|
||||
WAIT_INTERNAL_PROCESSING_FREQ
|
||||
};
|
||||
|
||||
#define SYSFS_GPIO_DIR "/sys/class/gpio"
|
||||
#define DEFAULT_GPIO_TOGGLE_WAIT_MS 400 //at 230400 bps
|
||||
#define MAX_BUF 64
|
||||
|
||||
struct IG1Command
|
||||
{
|
||||
short command;
|
||||
union Data {
|
||||
uint32_t i[64];
|
||||
float f[64];
|
||||
unsigned char c[256];
|
||||
} data;
|
||||
int dataLength;
|
||||
|
||||
int expectedResponse;
|
||||
int retryCount;
|
||||
bool sent;
|
||||
bool processed;
|
||||
|
||||
IG1Command(short cmd = 0, int response = WAIT_FOR_ACKNACK)
|
||||
{
|
||||
command = cmd;
|
||||
dataLength = 0;
|
||||
memset(data.c, 0, 256);
|
||||
expectedResponse = response;
|
||||
retryCount = 0;
|
||||
processed = false;
|
||||
sent = false;
|
||||
}
|
||||
|
||||
void setData(const LpVector3f &d)
|
||||
{
|
||||
dataLength = 12;
|
||||
memcpy(data.c, &d, dataLength);
|
||||
}
|
||||
|
||||
void setData(const LpMatrix3x3f &d)
|
||||
{
|
||||
dataLength = 36;
|
||||
memcpy(data.c, &d, dataLength);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class IG1 : public IG1I
|
||||
{
|
||||
public:
|
||||
/////////////////////////////////////////////
|
||||
// Constructor/Destructor
|
||||
/////////////////////////////////////////////
|
||||
IG1(void);
|
||||
//IG1(int portno, int baudrate);
|
||||
IG1(const IG1 &obj);
|
||||
~IG1(void);
|
||||
void init();
|
||||
void release() { disconnect(); delete this; };
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Connection
|
||||
/////////////////////////////////////////////
|
||||
void setPCBaudrate(int baud);
|
||||
#ifdef _WIN32
|
||||
void setPCPort(int port);
|
||||
int connect(int _portno, int _baudrate);
|
||||
int connect(std::string sensorName, int _baudrate);
|
||||
#else
|
||||
void setPCPort(std::string port);
|
||||
int connect(std::string _portno, int _baudrate);
|
||||
//int connect(std::string sensorName);
|
||||
#endif
|
||||
|
||||
bool disconnect();
|
||||
int getReconnectCount();
|
||||
|
||||
void setConnectionMode(int mode);
|
||||
void setConnectionInterface(int interface);
|
||||
void setControlGPIOForRs485(int gpio);
|
||||
void setControlGPIOToggleWaitMs(unsigned int ms);
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Commands:
|
||||
// - send command to sensor
|
||||
// - commandXXX functions will add appropriate commands to command queue
|
||||
// and processed in the internal thread
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Function: set sensor to command mode
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
void commandGotoCommandMode(void);
|
||||
|
||||
/*
|
||||
Function: set sensor to streaming mode
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
void commandGotoStreamingMode(void);
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get sensor ID
|
||||
Parameters: none
|
||||
Returns: int32
|
||||
*/
|
||||
void commandGetSensorID(void);
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to set sensor ID
|
||||
Parameters: int32
|
||||
Returns: none
|
||||
*/
|
||||
void commandSetSensorID(uint32_t id);
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get sensor Frenquency
|
||||
- hasInfo() will return true once sensor info is available
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
void commandGetSensorFrequency(void);
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to set sensor Frenquency
|
||||
Parameters: int32
|
||||
Returns: none
|
||||
*/
|
||||
void commandSetSensorFrequency(uint32_t freq);
|
||||
|
||||
|
||||
void commandGetSensorGyroRange(void);
|
||||
void commandSetSensorGyroRange(uint32_t range);
|
||||
|
||||
void commandStartGyroCalibration(void);
|
||||
|
||||
void commandGetSensorAccRange(void);
|
||||
void commandSetSensorAccRange(uint32_t range);
|
||||
|
||||
void commandGetSensorMagRange(void);
|
||||
void commandSetSensorMagRange(uint32_t range);
|
||||
|
||||
void commandGetSensorUseRadianOutput(void);
|
||||
void commandSetSensorUseRadianOutput(bool b);
|
||||
|
||||
void commandStartMagCalibration(void);
|
||||
void commandStopMagCalibration(void);
|
||||
|
||||
void commandGetMagRefrence(void);
|
||||
void commandSetMagRefrence(uint32_t reference);
|
||||
|
||||
void commandGetSensorMagCalibrationTimeout(void);
|
||||
void commandSetSensorMagCalibrationTimeout(float second);
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get sensor info
|
||||
- hasInfo() will return true once sensor info is available
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
void commandGetSensorInfo(void);
|
||||
|
||||
void commandSaveParameters(void);
|
||||
|
||||
void commandResetFactory(void);
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to set transmit data
|
||||
Parameters: as defined in transmit data register TDR
|
||||
#define TDR_XXX_ENABLED
|
||||
Returns: none
|
||||
*/
|
||||
void commandSetTransmitData(uint32_t config);
|
||||
|
||||
// CAN
|
||||
void commandGetCanStartId(void);
|
||||
void commandSetCanStartId(uint32_t data);
|
||||
|
||||
void commandGetCanBaudrate(void);
|
||||
void commandSetCanBaudrate(uint32_t baudrate);
|
||||
|
||||
void commandGetCanDataPrecision(void);
|
||||
void commandSetCanDataPrecision(uint32_t data);
|
||||
|
||||
void commandGetCanChannelMode(void);
|
||||
void commandSetCanChannelMode(uint32_t data);
|
||||
|
||||
void commandGetCanMapping(void);
|
||||
void commandSetCanMapping(uint32_t map[16]);
|
||||
|
||||
void commandGetCanHeartbeat(void);
|
||||
void commandSetCanHeartbeat(uint32_t data);
|
||||
|
||||
//Filter
|
||||
void commandSetFilterMode(uint32_t data);
|
||||
void commandGetFilterMode(void);
|
||||
|
||||
void commandSetGyroAutoCalibration(bool enable);
|
||||
void commandGetGyroAutoCalibration(void);
|
||||
|
||||
void commandSetOffsetMode(uint32_t data);
|
||||
void commandResetOffsetMode(void);
|
||||
|
||||
//GPS
|
||||
void commandSaveGPSState(void);
|
||||
void commandClearGPSState(void);
|
||||
|
||||
void commandSetGpsTransmitData(uint32_t data, uint32_t data1);
|
||||
void commandGetGpsTransmitData(void);
|
||||
|
||||
// Uart
|
||||
void commandSetUartBaudRate(uint32_t data);
|
||||
void commandGetUartBaudRate(void);
|
||||
|
||||
void commandSetUartDataFormat(uint32_t data);
|
||||
void commandGetUartDataFormat(void);
|
||||
|
||||
void commandSetUartDataPrecision(uint32_t data);
|
||||
void commandGetUartDataPrecision(void);
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor directly bypassing internal command queue
|
||||
Parameters:
|
||||
- cmd: command register
|
||||
- length: length of data to send
|
||||
- data: pointer to data buffer
|
||||
Returns: none
|
||||
*/
|
||||
void sendCommand(uint16_t cmd, uint16_t length, uint8_t* data);
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Sensor interface
|
||||
/////////////////////////////////////////////
|
||||
// General
|
||||
|
||||
/*
|
||||
Function: Specify sensor to streaming or command mode after connect
|
||||
Parameters:
|
||||
- SENSOR_MODE_COMMAND: start up in command mode
|
||||
- SENSOR_MODE_STREAMING: start up in streaming mode
|
||||
Returns: none
|
||||
*/
|
||||
void setStartupSensorMode(int mode);
|
||||
|
||||
/*
|
||||
Function: enable auto reconnection
|
||||
Parameters:
|
||||
- true: enable
|
||||
- false: disable
|
||||
Returns: none
|
||||
*/
|
||||
void setAutoReconnectStatus(bool b);
|
||||
|
||||
/*
|
||||
Function: get enable auto reconnection status
|
||||
Parameters: none
|
||||
Returns:
|
||||
- true: enable
|
||||
- false: disable
|
||||
*/
|
||||
bool getAutoReconnectStatus(void);
|
||||
|
||||
|
||||
/*
|
||||
Function: get status of sensor
|
||||
Parameters:none
|
||||
Returns: as defined in STATUS_XXX
|
||||
#define STATUS_DISCONNECTED 0
|
||||
#define STATUS_CONNECTING 1
|
||||
#define STATUS_CONNECTED 2
|
||||
#define STATUS_CONNECTION_ERROR 3
|
||||
#define STATUS_DATA_TIMEOUT 4
|
||||
#define STATUS_UPDATING 5
|
||||
*/
|
||||
int getStatus(void);
|
||||
|
||||
/*
|
||||
Function: get frequency of incoming data
|
||||
Parameters:none
|
||||
Returns: data frequency in Hz
|
||||
*/
|
||||
float getDataFrequency(void);
|
||||
|
||||
// info
|
||||
/*
|
||||
Function: has new sensor info. consume once
|
||||
Parameters:none
|
||||
Returns:
|
||||
- true: new sensor info available
|
||||
- false: no new sensor info available
|
||||
*/
|
||||
bool hasInfo(void);
|
||||
|
||||
/*
|
||||
Function: get sensor info
|
||||
Parameters: reference IG1Info
|
||||
Returns: none
|
||||
*/
|
||||
void getInfo(IG1InfoI &info);
|
||||
|
||||
// settings
|
||||
/*
|
||||
Function: has new sensor settings. consume once
|
||||
Parameters:none
|
||||
Returns:
|
||||
- true: new sensor settings available
|
||||
- false: no new sensor settings available
|
||||
*/
|
||||
bool hasSettings(void);
|
||||
|
||||
/*
|
||||
Function: get sensor settings
|
||||
Parameters: reference IG1Settings
|
||||
Returns: none
|
||||
*/
|
||||
void getSettings(IG1SettingsI &settings);
|
||||
|
||||
// response from sensor
|
||||
/*
|
||||
Function: has feedback from sensor after command sent
|
||||
Parameters : none
|
||||
Returns : number of feedback in queue
|
||||
*/
|
||||
int hasResponse(void);
|
||||
|
||||
/*
|
||||
Function: get feedback from internal response queue
|
||||
Parameters : string reference
|
||||
Returns :
|
||||
- true : feedback valid and available
|
||||
- false : no feedback available
|
||||
*/
|
||||
bool getResponse(std::string &s);
|
||||
|
||||
// Imu data
|
||||
/*
|
||||
Function: has new imu data
|
||||
Parameters:none
|
||||
Returns: number of imu data available in queue
|
||||
*/
|
||||
int hasImuData(void);
|
||||
|
||||
/*
|
||||
Function: get imu data from queue
|
||||
Parameters : IG1ImuData reference
|
||||
Returns :
|
||||
- true : data pop from queue
|
||||
- false : queue is empty, return latest imu data
|
||||
*/
|
||||
bool getImuData(IG1ImuDataI &sd);
|
||||
|
||||
// gps data
|
||||
/*
|
||||
Function: has new gps data
|
||||
Parameters:none
|
||||
Returns: number of gps data available in queue
|
||||
*/
|
||||
int hasGpsData();
|
||||
|
||||
/*
|
||||
Function: get gps data from queue
|
||||
Parameters : IG1ImuData reference
|
||||
Returns :
|
||||
- true : data pop from queue
|
||||
- false : queue is empty, return latest gps data
|
||||
*/
|
||||
bool getGpsData(IG1GpsDataI &data);
|
||||
|
||||
// Sensor data
|
||||
/*
|
||||
Function: is acc raw data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isAccRawEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is calibrated acc data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isAccCalibratedEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is gyro raw (high accuracy) data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isGyroIRawEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is bias calibrated gyro (high accuracy) data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isGyroIBiasCalibratedEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is alignment + bias calibrated gyro (high accuracy) data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isGyroIAlignCalibratedEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is gyro raw data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isGyroIIRawEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is bias calibrated gyro data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isGyroIIBiasCalibratedEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is alignment + bias calibrated gyro data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isGyroIIAlignCalibratedEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is mag raw data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isMagRawEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is calibrated mag data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isMagCalibratedEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is angular velocity data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isAngularVelocityEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is quaternion data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isQuaternionEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is euler data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isEulerEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is linear acceleration data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isLinearAccelerationEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is pressure data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isPressureEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is altitude data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isAltitudeEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is temperature data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
bool isTemperatureEnabled(void);
|
||||
|
||||
/*
|
||||
Function: is useRadianOutput
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: use radian output
|
||||
- false: use degree output
|
||||
*/
|
||||
bool isUseRadianOutput(void);
|
||||
|
||||
void setSensorDataQueueSize(unsigned int size);
|
||||
int getSensorDataQueueSize(void);
|
||||
|
||||
int getFilePages();
|
||||
bool getIsUpdatingStatus();
|
||||
|
||||
// Error
|
||||
std::string getLastErrMsg();
|
||||
|
||||
/*
|
||||
Function: Set library verbosity output
|
||||
Parameters:
|
||||
- VERBOSE_NONE
|
||||
- VERBOSE_INFO
|
||||
- VERBOSE_DEBUG
|
||||
Returns: void
|
||||
*/
|
||||
void setVerbose(int level);
|
||||
|
||||
///////////////////////////////////////////
|
||||
//Data saving
|
||||
///////////////////////////////////////////
|
||||
bool startDataSaving();
|
||||
bool stopDataSaving();
|
||||
|
||||
// imu
|
||||
int getSavedImuDataCount();
|
||||
IG1ImuData getSavedImuData(int i);
|
||||
|
||||
// gps
|
||||
int getSavedGpsDataCount();
|
||||
IG1GpsData getSavedGpsData(int i);
|
||||
|
||||
private:
|
||||
void triggerRS485CommandMode();
|
||||
|
||||
void processCommandQueue();
|
||||
void processIncomingData();
|
||||
|
||||
void clearSensorDataQueue();
|
||||
void updateData();
|
||||
bool parseModbusByte(int n);
|
||||
bool parseASCII(int n);
|
||||
bool parseSensorData(const LPPacket &p);
|
||||
void addSensorResponseToQueue(std::string);
|
||||
|
||||
void addCommandQueue(IG1Command cmd);
|
||||
void clearCommandQueue();
|
||||
|
||||
|
||||
void gpioInit();
|
||||
void gpioDeinit();
|
||||
int gpioExport(unsigned int gpio);
|
||||
int gpioUnexport(unsigned int gpio);
|
||||
int gpioSetDirection(unsigned int gpio, unsigned int out_flag);
|
||||
int gpioSetValue(unsigned int gpio, unsigned int value);
|
||||
int gpioGetValue(unsigned int gpio, unsigned int *value);
|
||||
|
||||
void cleanup();
|
||||
private:
|
||||
// General settings
|
||||
bool autoReconnect;
|
||||
int reconnectCount;
|
||||
|
||||
// Serial settings
|
||||
Serial sp;
|
||||
#ifdef _WIN32
|
||||
int portno;
|
||||
#else
|
||||
std::string portno;
|
||||
#endif
|
||||
int baudrate;
|
||||
std::string sensorId;
|
||||
int connectionMode; // VCP / USB Xpress
|
||||
int connectionInterface; // 232-TTL/485
|
||||
|
||||
// RS485 settings
|
||||
int ctrlGpio;
|
||||
unsigned int ctrlGpioToggleWaitMs;
|
||||
|
||||
// LPBus
|
||||
LPPacket packet;
|
||||
bool ackReceived;
|
||||
bool nackReceived;
|
||||
bool dataReceived;
|
||||
|
||||
// Internal thread
|
||||
std::thread *t;
|
||||
bool isStopThread;
|
||||
int connectionState;
|
||||
MicroMeasure mmDataFreq;
|
||||
MicroMeasure mmDataIdle;
|
||||
MicroMeasure mmUpdating;
|
||||
|
||||
// Sensor
|
||||
int startupSensorMode;
|
||||
int currentSensorMode;
|
||||
int sensorStatus;
|
||||
std::string errMsg;
|
||||
long long timeoutThreshold;
|
||||
unsigned char incomingData[INCOMING_DATA_MAX_LENGTH];
|
||||
|
||||
// Stats
|
||||
float incomingDataRate;
|
||||
|
||||
// Command queue
|
||||
std::mutex mLockCommandQueue;
|
||||
std::queue<IG1Command> commandQueue; //TODO use custom object to accomodate command data
|
||||
MicroMeasure mmCommandTimer;
|
||||
long long lastSendCommandTime;
|
||||
|
||||
// Response
|
||||
std::mutex mLockSensorResponseQueue;
|
||||
std::queue<std::string> sensorResponseQueue;
|
||||
|
||||
// Info
|
||||
bool hasNewInfo;
|
||||
IG1Info sensorInfo;
|
||||
|
||||
// Sensor settings
|
||||
bool hasNewSettings;
|
||||
IG1AdvancedSettings sensorSettings;
|
||||
MicroMeasure mmTransmitDataRegisterStatus;
|
||||
bool useNewChecksum;
|
||||
|
||||
// Imu data
|
||||
IG1ImuData latestImuData;
|
||||
std::mutex mLockImuDataQueue;
|
||||
std::queue<IG1ImuData> imuDataQueue;
|
||||
unsigned int sensorDataQueueSize;
|
||||
|
||||
// Gps data
|
||||
IG1GpsData latestGpsData;
|
||||
std::mutex mLockGpsDataQueue;
|
||||
std::queue<IG1GpsData> gpsDataQueue;
|
||||
|
||||
// Firmware update
|
||||
std::ifstream ifs;
|
||||
long long firmwarePages;
|
||||
int firmwarePageSize;
|
||||
unsigned long firmwareRemainder;
|
||||
uint32_t fileCheckSum;
|
||||
uint16_t updateCommand;
|
||||
unsigned char cBuffer[1024];
|
||||
|
||||
// Data saving
|
||||
// Imu
|
||||
bool isDataSaving;
|
||||
std::mutex mLockSavedImuDataQueue;
|
||||
std::vector<IG1ImuData> savedImuDataBuffer;
|
||||
int savedImuDataCount;
|
||||
|
||||
// GPS
|
||||
std::mutex mLockSavedGpsDataQueue;
|
||||
std::vector<IG1GpsData> savedGpsDataBuffer;
|
||||
int savedGpsDataCount;
|
||||
|
||||
|
||||
// debug
|
||||
MicroMeasure mmDebug;
|
||||
LpLog& log = LpLog::getInstance();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,803 @@
|
||||
#ifndef LPMSIG1_I_H
|
||||
#define LPMSIG1_I_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "windows.h"
|
||||
#endif
|
||||
#include "SensorDataI.h"
|
||||
#include "LpLog.h"
|
||||
|
||||
// Note: To be deprecated
|
||||
#define COMMUNICATION_INTERFACE_232 0
|
||||
#define COMMUNICATION_INTERFACE_485 1
|
||||
|
||||
// Connection Interface
|
||||
#define CONNECTION_INTERFACE_RS232_USB 0
|
||||
#define CONNECTION_INTERFACE_RS485 1
|
||||
|
||||
// Sensor status
|
||||
#define STATUS_DISCONNECTED 0
|
||||
#define STATUS_CONNECTING 1
|
||||
#define STATUS_CONNECTED 2
|
||||
#define STATUS_CONNECTION_ERROR 3
|
||||
#define STATUS_DATA_TIMEOUT 4
|
||||
#define STATUS_UPDATING 5
|
||||
|
||||
// Sensor mode
|
||||
#define SENSOR_MODE_COMMAND 0
|
||||
#define SENSOR_MODE_STREAMING 1
|
||||
|
||||
class IG1I
|
||||
{
|
||||
public:
|
||||
const std::string TAG = "IG1";
|
||||
/////////////////////////////////////////////
|
||||
// Constructor/Destructor
|
||||
/////////////////////////////////////////////
|
||||
~IG1I(void) {};
|
||||
virtual void release() = 0;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Connection
|
||||
/////////////////////////////////////////////
|
||||
virtual void setPCBaudrate(int baud) =0;
|
||||
#ifdef _WIN32
|
||||
virtual void setPCPort(int port) =0;
|
||||
#else
|
||||
virtual void setPCPort(std::string port) = 0;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
Function: Connect to sensor
|
||||
Parameters:
|
||||
- _portno: In windows, this the number attached to COM port. eg 3 for COM3
|
||||
- baudrate: serial baudrate
|
||||
Returns: sensor status
|
||||
- STATUS_DISCONNECTED
|
||||
- STATUS_CONNECTING
|
||||
- STATUS_CONNECTED
|
||||
- STATUS_CONNECTION_ERROR
|
||||
- STATUS_DATA_TIMEOUT
|
||||
- STATUS_UPDATING
|
||||
*/
|
||||
virtual int connect(int _portno, int _baudrate) = 0;
|
||||
|
||||
/*
|
||||
Function: Connect to sensor
|
||||
Parameters:
|
||||
- sensorName: sensor ID
|
||||
- baudrate: serial baudrate
|
||||
Returns: sensor status
|
||||
- STATUS_DISCONNECTED
|
||||
- STATUS_CONNECTING
|
||||
- STATUS_CONNECTED
|
||||
- STATUS_CONNECTION_ERROR
|
||||
- STATUS_DATA_TIMEOUT
|
||||
- STATUS_UPDATING
|
||||
*/
|
||||
virtual int connect(std::string sensorName, int _baudrate) = 0;
|
||||
#else
|
||||
|
||||
/*
|
||||
Function: Connect to sensor
|
||||
Parameters:
|
||||
- _portno: In linux, this value can be serial mount point /dev/ttyXXX
|
||||
or sensor ID
|
||||
- baudrate: serial baudrate
|
||||
Returns: sensor status
|
||||
- STATUS_DISCONNECTED
|
||||
- STATUS_CONNECTING
|
||||
- STATUS_CONNECTED
|
||||
- STATUS_CONNECTION_ERROR
|
||||
- STATUS_DATA_TIMEOUT
|
||||
- STATUS_UPDATING
|
||||
*/
|
||||
virtual int connect(std::string _portno, int _baudrate) = 0;
|
||||
#endif
|
||||
|
||||
virtual bool disconnect() = 0;
|
||||
virtual int getReconnectCount() = 0;
|
||||
/*
|
||||
Function: Set connection interface
|
||||
Parameters:
|
||||
- interface:
|
||||
CONNECTION_INTERFACE_RS232_USB for USB/RS232 connection
|
||||
CONNECTION_INTERFACE_RS485 for RS485 connection
|
||||
*/
|
||||
virtual void setConnectionInterface(int interface) = 0;
|
||||
|
||||
/*
|
||||
Function: Set gpio control pin
|
||||
Parameters:
|
||||
- interface:
|
||||
CONNECTION_INTERFACE_RS232_USB for USB/RS232 connection
|
||||
CONNECTION_INTERFACE_RS485 for RS485 connection
|
||||
*/
|
||||
virtual void setControlGPIOForRs485(int gpio) = 0;
|
||||
|
||||
/*
|
||||
Function: Set time to wait before toggling io pin during host TX transfer.
|
||||
Only applies to RS485 connection
|
||||
Parameters: wait time in ms
|
||||
Return: none
|
||||
*/
|
||||
virtual void setControlGPIOToggleWaitMs(unsigned int ms) = 0;
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Commands:
|
||||
// - send command to sensor
|
||||
// - commandXXX functions will add appropriate commands to command queue
|
||||
// and processed in the internal thread
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Function: set sensor to command mode
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGotoCommandMode(void) = 0;
|
||||
|
||||
/*
|
||||
Function: set sensor to streaming mode
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGotoStreamingMode(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get sensor ID
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetSensorID(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to set sensor ID
|
||||
Parameters: int32
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSetSensorID(uint32_t id) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor Frenquency
|
||||
- hasInfo() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define DATA_STREAM_FREQ_5HZ 5
|
||||
#define DATA_STREAM_FREQ_10HZ 10
|
||||
#define DATA_STREAM_FREQ_50HZ 50
|
||||
#define DATA_STREAM_FREQ_100HZ 100
|
||||
#define DATA_STREAM_FREQ_250HZ 250
|
||||
#define DATA_STREAM_FREQ_500HZ 500
|
||||
#define DATA_STREAM_FREQ_1000HZ 1000
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetSensorFrequency(void) = 0;
|
||||
virtual void commandSetSensorFrequency(uint32_t freq) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor gyro range
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define GYR_RANGE_400DPS 400
|
||||
#define GYR_RANGE_1000DPS 1000
|
||||
#define GYR_RANGE_2000DPS 2000
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetSensorGyroRange(void) = 0;
|
||||
virtual void commandSetSensorGyroRange(uint32_t range) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to start calibration static gyro
|
||||
Please keep imu still 4 seconds.
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandStartGyroCalibration(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor acc range
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define ACC_RANGE_2G 2
|
||||
#define ACC_RANGE_4G 4
|
||||
#define ACC_RANGE_8G 8
|
||||
#define ACC_RANGE_16G 16
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetSensorAccRange(void) = 0;
|
||||
virtual void commandSetSensorAccRange(uint32_t range) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor mag range
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define MAG_RANGE_2GUASS 2
|
||||
#define MAG_RANGE_8GUASS 8
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetSensorMagRange(void) = 0;
|
||||
virtual void commandSetSensorMagRange(uint32_t range) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to start/stop sensor mag calibration
|
||||
You can set the time for the magnetometer calibration use commandSetSensorMagCalibrationTimeout(second)
|
||||
[Default is 20 seconds]
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandStartMagCalibration(void) = 0;
|
||||
virtual void commandStopMagCalibration(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor mag refrence
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
//virtual void commandGetMagRefrence(void) = 0;
|
||||
//virtual void commandSetMagRefrence(uint32_t reference) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor mag calibration time
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetSensorMagCalibrationTimeout(void) = 0;
|
||||
virtual void commandSetSensorMagCalibrationTimeout(float second) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get sensor info
|
||||
- hasInfo() will return true once sensor info is available
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetSensorInfo(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to save sensor parameters to flash
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSaveParameters(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to reset factory
|
||||
Parameters: none
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandResetFactory(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to set transmit data
|
||||
Parameters: as defined in transmit data register TDR
|
||||
#define TDR_XXX_ENABLED
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSetTransmitData(uint32_t config) = 0;
|
||||
|
||||
// CAN
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor can id
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:int32
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetCanStartId(void) = 0;
|
||||
virtual void commandSetCanStartId(uint32_t data) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor can baudrate
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_CAN_BAUDRATE_125K 125
|
||||
#define LPMS_CAN_BAUDRATE_250K 250
|
||||
#define LPMS_CAN_BAUDRATE_500K 500
|
||||
#define LPMS_CAN_BAUDRATE_800K 800
|
||||
#define LPMS_CAN_BAUDRATE_1M 1000
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetCanBaudrate(void) = 0;
|
||||
virtual void commandSetCanBaudrate(uint32_t baudrate) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor can precision (16/32 bit)
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_CAN_DATA_PRECISION_FIXED_POINT 0
|
||||
#define LPMS_CAN_DATA_PRECISION_FLOATING_POINT 1
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetCanDataPrecision(void) = 0;
|
||||
virtual void commandSetCanDataPrecision(uint32_t data) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor can mode
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_CAN_MODE_CANOPEN 0
|
||||
#define LPMS_CAN_MODE_SEQUENTIAL 1
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetCanChannelMode(void) = 0;
|
||||
virtual void commandSetCanChannelMode(uint32_t data) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor can mapping
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
each can channel is a (uint32_t)CanMapping.
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetCanMapping(void) = 0;
|
||||
virtual void commandSetCanMapping(uint32_t map[16]) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor can heartbeat freq
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_CAN_HEARTBEAT_005 0
|
||||
#define LPMS_CAN_HEARTBEAT_010 1
|
||||
#define LPMS_CAN_HEARTBEAT_020 2
|
||||
#define LPMS_CAN_HEARTBEAT_050 5
|
||||
#define LPMS_CAN_HEARTBEAT_100 10
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetCanHeartbeat(void) = 0;
|
||||
virtual void commandSetCanHeartbeat(uint32_t data) = 0;
|
||||
|
||||
//Filter
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set sensor filter mode
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_FILTER_GYR 0
|
||||
#define LPMS_FILTER_KALMAN_GYR_ACC 1
|
||||
#define LPMS_FILTER_KALMAN_GYR_ACC_MAG 2
|
||||
#define LPMS_FILTER_DCM_GYR_ACC 3
|
||||
#define LPMS_FILTER_DCM_GYR_ACC_MAG 4
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandGetFilterMode(void) = 0;
|
||||
virtual void commandSetFilterMode(uint32_t data) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to enable/disable gyro auto calibraiton
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters: bool
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSetGyroAutoCalibration(bool enable) = 0;
|
||||
virtual void commandGetGyroAutoCalibration(void) = 0;
|
||||
|
||||
//Offset Mode
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to set offset
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_OFFSET_MODE_OBJECT 0
|
||||
#define LPMS_OFFSET_MODE_HEADING 1
|
||||
#define LPMS_OFFSET_MODE_ALIGNMENT 2
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSetOffsetMode(uint32_t data) = 0;
|
||||
virtual void commandResetOffsetMode(void) = 0;
|
||||
|
||||
//GPS
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to save/clear gps flash
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSaveGPSState(void) = 0;
|
||||
virtual void commandClearGPSState(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set GPS transmit data.
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSetGpsTransmitData(uint32_t data, uint32_t data1) = 0;
|
||||
virtual void commandGetGpsTransmitData(void) = 0;
|
||||
|
||||
// Uart
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set uart baudrate
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_UART_BAUDRATE_xxxxx
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSetUartBaudRate(uint32_t data) = 0;
|
||||
virtual void commandGetUartBaudRate(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set uart data format
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_UART_DATA_FORMAT_LPBUS 0
|
||||
#define LPMS_UART_DATA_FORMAT_ASCII 1
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSetUartDataFormat(uint32_t data) = 0;
|
||||
virtual void commandGetUartDataFormat(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor to get/set uart data precision
|
||||
- hasSettings() will return true once sensor info is available
|
||||
Parameters:
|
||||
#define LPMS_UART_DATA_PRECISION_FIXED_POINT 0
|
||||
#define LPMS_UART_DATA_PRECISION_FLOATING_POINT 1
|
||||
Returns: none
|
||||
*/
|
||||
virtual void commandSetUartDataPrecision(uint32_t data) = 0;
|
||||
virtual void commandGetUartDataPrecision(void) = 0;
|
||||
|
||||
/*
|
||||
Function:
|
||||
- send command to sensor directly bypassing internal command queue
|
||||
Parameters:
|
||||
- cmd: command register
|
||||
- length: length of data to send
|
||||
- data: pointer to data buffer
|
||||
Returns: none
|
||||
*/
|
||||
virtual void sendCommand(uint16_t cmd, uint16_t length, uint8_t* data) = 0;
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Sensor interface
|
||||
/////////////////////////////////////////////
|
||||
// General
|
||||
/*
|
||||
Function: Specify sensor to streaming or command mode after connect
|
||||
Parameters:
|
||||
- SENSOR_MODE_COMMAND: start up in command mode
|
||||
- SENSOR_MODE_STREAMING: start up in streaming mode
|
||||
Returns: none
|
||||
*/
|
||||
virtual void setStartupSensorMode(int mode) = 0;
|
||||
/*
|
||||
Function: set auto reconnection status
|
||||
Parameters:
|
||||
- true: enable
|
||||
- false: disable
|
||||
Returns: none
|
||||
*/
|
||||
virtual void setAutoReconnectStatus(bool b) = 0;
|
||||
|
||||
/*
|
||||
Function: get enable auto reconnection status
|
||||
Parameters: none
|
||||
Returns:
|
||||
- true: enable
|
||||
- false: disable
|
||||
*/
|
||||
virtual bool getAutoReconnectStatus(void) = 0;
|
||||
|
||||
/*
|
||||
Function: get status of sensor
|
||||
Parameters:none
|
||||
Returns: as defined in STATUS_XXX
|
||||
#define STATUS_DISCONNECTED 0
|
||||
#define STATUS_CONNECTING 1
|
||||
#define STATUS_CONNECTED 2
|
||||
#define STATUS_CONNECTION_ERROR 3
|
||||
#define STATUS_DATA_TIMEOUT 4
|
||||
#define STATUS_UPDATING 5
|
||||
*/
|
||||
virtual int getStatus(void) = 0;
|
||||
|
||||
/*
|
||||
Function: get frequency of incoming data
|
||||
Parameters:none
|
||||
Returns: data frequency in Hz
|
||||
*/
|
||||
virtual float getDataFrequency(void) = 0;
|
||||
|
||||
// info
|
||||
/*
|
||||
Function: has new sensor info. consume once
|
||||
Parameters:none
|
||||
Returns:
|
||||
- true: new sensor info available
|
||||
- false: no new sensor info available
|
||||
*/
|
||||
virtual bool hasInfo(void) = 0;
|
||||
|
||||
/*
|
||||
Function: get sensor info
|
||||
Parameters: reference IG1Info
|
||||
Returns: none
|
||||
*/
|
||||
virtual void getInfo(IG1InfoI &info) = 0;
|
||||
|
||||
// settings
|
||||
/*
|
||||
Function: has new sensor settings. consume once
|
||||
Parameters:none
|
||||
Returns:
|
||||
- true: new sensor settings available
|
||||
- false: no new sensor settings available
|
||||
*/
|
||||
virtual bool hasSettings(void) = 0;
|
||||
|
||||
/*
|
||||
Function: get sensor settings
|
||||
Parameters: reference IG1Settings
|
||||
Returns: none
|
||||
*/
|
||||
virtual void getSettings(IG1SettingsI &settings) = 0;
|
||||
|
||||
// response from sensor
|
||||
/*
|
||||
Function: has feedback from sensor after command sent
|
||||
Parameters : none
|
||||
Returns : number of feedback in queue
|
||||
*/
|
||||
virtual int hasResponse(void) = 0;
|
||||
|
||||
/*
|
||||
Function: get feedback from internal response queue
|
||||
Parameters : string reference
|
||||
Returns :
|
||||
- true : feedback valid and available
|
||||
- false : no feedback available
|
||||
*/
|
||||
virtual bool getResponse(std::string &s) = 0;
|
||||
|
||||
// Imu data
|
||||
/*
|
||||
Function: has new imu data
|
||||
Parameters:none
|
||||
Returns: number of imu data available in queue
|
||||
*/
|
||||
virtual int hasImuData(void) = 0;
|
||||
|
||||
/*
|
||||
Function: get imu data from queue
|
||||
Parameters : IG1ImuData reference
|
||||
Returns :
|
||||
- true : data pop from queue
|
||||
- false : queue is empty, return latest imu data
|
||||
*/
|
||||
virtual bool getImuData(IG1ImuDataI &sd) = 0;
|
||||
|
||||
// gps data
|
||||
/*
|
||||
Function: has new gps data
|
||||
Parameters:none
|
||||
Returns: number of gps data available in queue
|
||||
*/
|
||||
virtual int hasGpsData() = 0;
|
||||
|
||||
/*
|
||||
Function: get gps data from queue
|
||||
Parameters : IG1ImuData reference
|
||||
Returns :
|
||||
- true : data pop from queue
|
||||
- false : queue is empty, return latest gps data
|
||||
*/
|
||||
virtual bool getGpsData(IG1GpsDataI &data) = 0;
|
||||
|
||||
// Sensor data
|
||||
/*
|
||||
Function: is acc raw data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isAccRawEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is calibrated acc data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isAccCalibratedEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is gyro raw (high accuracy) data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isGyroIRawEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is bias calibrated gyro (high accuracy) data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isGyroIBiasCalibratedEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is alignment + bias calibrated gyro (high accuracy) data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isGyroIAlignCalibratedEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is gyro raw data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isGyroIIRawEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is bias calibrated gyro data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isGyroIIBiasCalibratedEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is alignment + bias calibrated gyro data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isGyroIIAlignCalibratedEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is mag raw data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isMagRawEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is calibrated mag data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isMagCalibratedEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is angular velocity data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isAngularVelocityEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is quaternion data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isQuaternionEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is euler data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isEulerEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is linear acceleration data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isLinearAccelerationEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is pressure data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isPressureEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is altitude data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isAltitudeEnabled(void) = 0;
|
||||
|
||||
/*
|
||||
Function: is temperature data enabled
|
||||
Parameters: void
|
||||
Returns:
|
||||
- true: enabled
|
||||
- false: disabled
|
||||
*/
|
||||
virtual bool isTemperatureEnabled(void) = 0;
|
||||
|
||||
/**
|
||||
* Get current data queue size (default: 10)
|
||||
*/
|
||||
virtual int getSensorDataQueueSize(void) = 0;
|
||||
|
||||
// Error
|
||||
virtual std::string getLastErrMsg() = 0;
|
||||
|
||||
/*
|
||||
Function: Set library verbosity output
|
||||
Parameters:
|
||||
- VERBOSE_NONE
|
||||
- VERBOSE_INFO
|
||||
- VERBOSE_DEBUG
|
||||
Returns: void
|
||||
*/
|
||||
virtual void setVerbose(int verboseLevel) = 0;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef DLL_EXPORT
|
||||
#define LPMS_IG1_API __declspec(dllexport)
|
||||
#else
|
||||
#define LPMS_IG1_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
extern "C" LPMS_IG1_API IG1I* APIENTRY IG1Factory();
|
||||
|
||||
#else
|
||||
#define LPMS_IG1_API
|
||||
extern "C" LPMS_IG1_API IG1I* IG1Factory();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,403 @@
|
||||
#ifndef LPMSIG1_REGISTERS_H
|
||||
#define LPMSIG1_REGISTERS_H
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Essentials - should not change over time
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Commands start address
|
||||
#define COMMAND_START_ADDRESS 0
|
||||
|
||||
// Acknowledged and Not-acknowledged identifier
|
||||
#define REPLY_ACK (COMMAND_START_ADDRESS + 0)
|
||||
#define REPLY_NACK (COMMAND_START_ADDRESS + 1)
|
||||
|
||||
// Firmware update and in-application-programmer upload
|
||||
#define UPDATE_FIRMWARE (COMMAND_START_ADDRESS + 2)
|
||||
#define UPDATE_IAP (COMMAND_START_ADDRESS + 3)
|
||||
|
||||
// Register value save and reset
|
||||
#define WRITE_REGISTERS (COMMAND_START_ADDRESS + 4)
|
||||
#define RESTORE_FACTORY_VALUE (COMMAND_START_ADDRESS + 5)
|
||||
|
||||
// Mode switching
|
||||
#define GOTO_COMMAND_MODE (COMMAND_START_ADDRESS + 6)
|
||||
#define GOTO_STREAM_MODE (COMMAND_START_ADDRESS + 7)
|
||||
|
||||
// Sensor status
|
||||
#define GET_SENSOR_STATUS (COMMAND_START_ADDRESS + 8) // streaming/command
|
||||
|
||||
// Data
|
||||
#define GET_IMU_DATA (COMMAND_START_ADDRESS + 9) // Todo
|
||||
#define GET_GPS_DATA (COMMAND_START_ADDRESS + 10) // Todo
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Sensor Info
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
#define GET_SENSOR_MODEL (COMMAND_START_ADDRESS + 20)
|
||||
#define GET_FIRMWARE_INFO (COMMAND_START_ADDRESS + 21)
|
||||
#define GET_SERIAL_NUMBER (COMMAND_START_ADDRESS + 22)
|
||||
#define GET_FILTER_VERSION (COMMAND_START_ADDRESS + 23)
|
||||
#define GET_IAP_CHECKSTATUS (COMMAND_START_ADDRESS + 24)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// General
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Transmit data
|
||||
#define SET_IMU_TRANSMIT_DATA (COMMAND_START_ADDRESS + 30)
|
||||
#define GET_IMU_TRANSMIT_DATA (COMMAND_START_ADDRESS + 31)
|
||||
|
||||
// IMU ID setting
|
||||
#define SET_IMU_ID (COMMAND_START_ADDRESS + 32)
|
||||
#define GET_IMU_ID (COMMAND_START_ADDRESS + 33)
|
||||
|
||||
// Stream frequency
|
||||
#define SET_STREAM_FREQ (COMMAND_START_ADDRESS + 34)
|
||||
#define GET_STREAM_FREQ (COMMAND_START_ADDRESS + 35)
|
||||
|
||||
// Deg/Rad output
|
||||
#define SET_DEGRAD_OUTPUT (COMMAND_START_ADDRESS + 36)
|
||||
#define GET_DEGRAD_OUTPUT (COMMAND_START_ADDRESS + 37)
|
||||
|
||||
// Reference setting and offset reset
|
||||
#define SET_ORIENTATION_OFFSET (COMMAND_START_ADDRESS + 38)
|
||||
#define RESET_ORIENTATION_OFFSET (COMMAND_START_ADDRESS + 39)
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Accelerometer
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Accelerometer settings
|
||||
#define SET_ACC_RANGE (COMMAND_START_ADDRESS + 50)
|
||||
#define GET_ACC_RANGE (COMMAND_START_ADDRESS + 51)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Gyro
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Gyroscope settings
|
||||
#define SET_GYR_RANGE (COMMAND_START_ADDRESS + 60)
|
||||
#define GET_GYR_RANGE (COMMAND_START_ADDRESS + 61)
|
||||
|
||||
#define START_GYR_CALIBRATION (COMMAND_START_ADDRESS + 62)
|
||||
|
||||
#define SET_ENABLE_GYR_AUTOCALIBRATION (COMMAND_START_ADDRESS + 64)
|
||||
#define GET_ENABLE_GYR_AUTOCALIBRATION (COMMAND_START_ADDRESS + 65)
|
||||
|
||||
#define SET_GYR_THRESHOLD (COMMAND_START_ADDRESS + 66)
|
||||
#define GET_GYR_THRESHOLD (COMMAND_START_ADDRESS + 67)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Magnetometer
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Magnetometer settings
|
||||
#define SET_MAG_RANGE (COMMAND_START_ADDRESS + 70)
|
||||
#define GET_MAG_RANGE (COMMAND_START_ADDRESS + 71)
|
||||
|
||||
#define SET_HARD_IRON_OFFSET (COMMAND_START_ADDRESS + 72)
|
||||
#define GET_HARD_IRON_OFFSET (COMMAND_START_ADDRESS + 73)
|
||||
|
||||
#define SET_SOFT_IRON_MATRIX (COMMAND_START_ADDRESS + 74)
|
||||
#define GET_SOFT_IRON_MATRIX (COMMAND_START_ADDRESS + 75)
|
||||
|
||||
#define SET_FIELD_ESTIMATE (COMMAND_START_ADDRESS + 76)
|
||||
#define GET_FIELD_ESTIMATE (COMMAND_START_ADDRESS + 77)
|
||||
|
||||
#define SET_MAG_ALIGNMENT_MATRIX (COMMAND_START_ADDRESS + 78)
|
||||
#define GET_MAG_ALIGNMENT_MATRIX (COMMAND_START_ADDRESS + 79)
|
||||
|
||||
#define SET_MAG_ALIGNMENT_BIAS (COMMAND_START_ADDRESS + 80)
|
||||
#define GET_MAG_ALIGNMENT_BIAS (COMMAND_START_ADDRESS + 81)
|
||||
|
||||
#define SET_MAG_REFERENCE (COMMAND_START_ADDRESS + 82)
|
||||
#define GET_MAG_REFERENCE (COMMAND_START_ADDRESS + 83)
|
||||
|
||||
#define START_MAG_CALIBRATION (COMMAND_START_ADDRESS + 84)
|
||||
#define STOP_MAG_CALIBRATION (COMMAND_START_ADDRESS + 85)
|
||||
|
||||
#define SET_MAG_CALIBRATION_TIMEOUT (COMMAND_START_ADDRESS + 86)
|
||||
#define GET_MAG_CALIBRATION_TIMEOUT (COMMAND_START_ADDRESS + 87)
|
||||
|
||||
#define SET_ENABLE_MAG_AUTOCALIBRATION (COMMAND_START_ADDRESS + 88) // Not implemented yet
|
||||
#define GET_ENABLE_MAG_AUTOCALIBRATION (COMMAND_START_ADDRESS + 89) // Not implemented yet
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Filter
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Filter settings
|
||||
#define SET_FILTER_MODE (COMMAND_START_ADDRESS + 90)
|
||||
#define GET_FILTER_MODE (COMMAND_START_ADDRESS + 91)
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// CAN
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// CAN settings
|
||||
#define SET_CAN_START_ID (COMMAND_START_ADDRESS + 110)
|
||||
#define GET_CAN_START_ID (COMMAND_START_ADDRESS + 111)
|
||||
#define SET_CAN_BAUDRATE (COMMAND_START_ADDRESS + 112)
|
||||
#define GET_CAN_BAUDRATE (COMMAND_START_ADDRESS + 113)
|
||||
#define SET_CAN_DATA_PRECISION (COMMAND_START_ADDRESS + 114)
|
||||
#define GET_CAN_DATA_PRECISION (COMMAND_START_ADDRESS + 115)
|
||||
#define SET_CAN_MODE (COMMAND_START_ADDRESS + 116)
|
||||
#define GET_CAN_MODE (COMMAND_START_ADDRESS + 117)
|
||||
#define SET_CAN_MAPPING (COMMAND_START_ADDRESS + 118)
|
||||
#define GET_CAN_MAPPING (COMMAND_START_ADDRESS + 119)
|
||||
#define SET_CAN_HEARTBEAT (COMMAND_START_ADDRESS + 120)
|
||||
#define GET_CAN_HEARTBEAT (COMMAND_START_ADDRESS + 121)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// UART/RS232
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// UART
|
||||
#define SET_UART_BAUDRATE (COMMAND_START_ADDRESS + 130)
|
||||
#define GET_UART_BAUDRATE (COMMAND_START_ADDRESS + 131)
|
||||
#define SET_UART_FORMAT (COMMAND_START_ADDRESS + 132)
|
||||
#define GET_UART_FORMAT (COMMAND_START_ADDRESS + 133)
|
||||
#define SET_UART_ASCII_CHARACTER (COMMAND_START_ADDRESS + 134)
|
||||
#define GET_UART_ASCII_CHARACTER (COMMAND_START_ADDRESS + 135)
|
||||
#define SET_LPBUS_DATA_PRECISION (COMMAND_START_ADDRESS + 136)
|
||||
#define GET_LPBUS_DATA_PRECISION (COMMAND_START_ADDRESS + 137)
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Sync
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Software Sync
|
||||
#define START_SYNC (COMMAND_START_ADDRESS + 150) // Todo
|
||||
#define STOP_SYNC (COMMAND_START_ADDRESS + 151) // Todo
|
||||
|
||||
// Timestamp manipulation
|
||||
#define SET_TIMESTAMP (COMMAND_START_ADDRESS + 152) // Todo
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// GPS
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
#define SET_GPS_TRANSMIT_DATA (COMMAND_START_ADDRESS + 160)
|
||||
#define GET_GPS_TRANSMIT_DATA (COMMAND_START_ADDRESS + 161)
|
||||
|
||||
#define SAVE_GPS_STATE (COMMAND_START_ADDRESS + 162)
|
||||
#define CLEAR_GPS_STATE (COMMAND_START_ADDRESS + 163)
|
||||
|
||||
#define SET_GPS_UDR (COMMAND_START_ADDRESS + 164)
|
||||
#define GET_GPS_UDR (COMMAND_START_ADDRESS + 165)
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Transmit data Register
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
#define TDR_ACC_RAW_OUTPUT_ENABLED (uint32_t)(0x00000001 << 0)
|
||||
#define TDR_ACC_CALIBRATED_OUTPUT_ENABLED (uint32_t)(0x00000001 << 1)
|
||||
#define TDR_GYR0_RAW_OUTPUT_ENABLED (uint32_t)(0x00000001 << 2)
|
||||
#define TDR_GYR1_RAW_OUTPUT_ENABLED (uint32_t)(0x00000001 << 3)
|
||||
#define TDR_GYR0_BIAS_CALIBRATED_OUTPUT_ENABLED (uint32_t)(0x00000001 << 4)
|
||||
#define TDR_GYR1_BIAS_CALIBRATED_OUTPUT_ENABLED (uint32_t)(0x00000001 << 5)
|
||||
#define TDR_GYR0_ALIGN_CALIBRATED_OUTPUT_ENABLED (uint32_t)(0x00000001 << 6)
|
||||
#define TDR_GYR1_ALIGN_CALIBRATED_OUTPUT_ENABLED (uint32_t)(0x00000001 << 7)
|
||||
#define TDR_MAG_RAW_OUTPUT_ENABLED (uint32_t)(0x00000001 << 8)
|
||||
#define TDR_MAG_CALIBRATED_OUTPUT_ENABLED (uint32_t)(0x00000001 << 9)
|
||||
#define TDR_ANGULAR_VELOCITY_OUTPUT_ENABLED (uint32_t)(0x00000001 << 10)
|
||||
#define TDR_QUAT_OUTPUT_ENABLED (uint32_t)(0x00000001 << 11)
|
||||
#define TDR_EULER_OUTPUT_ENABLED (uint32_t)(0x00000001 << 12)
|
||||
#define TDR_LINACC_OUTPUT_ENABLED (uint32_t)(0x00000001 << 13)
|
||||
#define TDR_PRESSURE_OUTPUT_ENABLED (uint32_t)(0x00000001 << 14)
|
||||
#define TDR_ALTITUDE_OUTPUT_ENABLED (uint32_t)(0x00000001 << 15)
|
||||
#define TDR_TEMPERATURE_OUTPUT_ENABLED (uint32_t)(0x00000001 << 16)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// GPS TRANSMIT_DATA_CONFIG Register
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// GPS transmit data register0 contents
|
||||
#define GPS_NAV_PVT_ITOW_ENABLE (uint32_t)(0x00000001 << 0)
|
||||
#define GPS_NAV_PVT_YEAR_ENABLE (uint32_t)(0x00000001 << 1)
|
||||
#define GPS_NAV_PVT_MONTH_ENABLE (uint32_t)(0x00000001 << 2)
|
||||
#define GPS_NAV_PVT_DAY_ENABLE (uint32_t)(0x00000001 << 3)
|
||||
#define GPS_NAV_PVT_HOUR_ENABLE (uint32_t)(0x00000001 << 4)
|
||||
#define GPS_NAV_PVT_MIN_ENABLE (uint32_t)(0x00000001 << 5)
|
||||
#define GPS_NAV_PVT_SEC_ENABLE (uint32_t)(0x00000001 << 6)
|
||||
#define GPS_NAV_PVT_VALID_ENABLE (uint32_t)(0x00000001 << 7)
|
||||
#define GPS_NAV_PVT_TACC_ENABLE (uint32_t)(0x00000001 << 8)
|
||||
#define GPS_NAV_PVT_NANO_ENABLE (uint32_t)(0x00000001 << 9)
|
||||
#define GPS_NAV_PVT_FIXTYPE_ENABLE (uint32_t)(0x00000001 << 10)
|
||||
#define GPS_NAV_PVT_FLAGS_ENABLE (uint32_t)(0x00000001 << 11)
|
||||
#define GPS_NAV_PVT_FLAGS2_ENABLE (uint32_t)(0x00000001 << 12)
|
||||
#define GPS_NAV_PVT_NUMSV_ENABLE (uint32_t)(0x00000001 << 13)
|
||||
#define GPS_NAV_PVT_LONGITUDE_ENABLE (uint32_t)(0x00000001 << 14)
|
||||
#define GPS_NAV_PVT_LATITUDE_ENABLE (uint32_t)(0x00000001 << 15)
|
||||
#define GPS_NAV_PVT_HEIGHT_ENABLE (uint32_t)(0x00000001 << 16)
|
||||
#define GPS_NAV_PVT_HMSL_ENABLE (uint32_t)(0x00000001 << 17)
|
||||
#define GPS_NAV_PVT_HACC_ENABLE (uint32_t)(0x00000001 << 18)
|
||||
#define GPS_NAV_PVT_VACC_ENABLE (uint32_t)(0x00000001 << 19)
|
||||
#define GPS_NAV_PVT_VELN_ENABLE (uint32_t)(0x00000001 << 20)
|
||||
#define GPS_NAV_PVT_VELE_ENABLE (uint32_t)(0x00000001 << 21)
|
||||
#define GPS_NAV_PVT_VELD_ENABLE (uint32_t)(0x00000001 << 22)
|
||||
#define GPS_NAV_PVT_GSPEED_ENABLE (uint32_t)(0x00000001 << 23)
|
||||
#define GPS_NAV_PVT_HEADMOT_ENABLE (uint32_t)(0x00000001 << 24)
|
||||
#define GPS_NAV_PVT_SACC_ENABLE (uint32_t)(0x00000001 << 25)
|
||||
#define GPS_NAV_PVT_HEADACC_ENABLE (uint32_t)(0x00000001 << 26)
|
||||
#define GPS_NAV_PVT_PDOP_ENABLE (uint32_t)(0x00000001 << 27)
|
||||
#define GPS_NAV_PVT_HEADVEH_ENABLE (uint32_t)(0x00000001 << 28)
|
||||
|
||||
// GPS transmit data register1 contents
|
||||
#define GPS_NAV_ATT_ITOW_ENABLE (uint32_t)(0x00000001 << 0)
|
||||
#define GPS_NAV_ATT_VERSION_ENABLE (uint32_t)(0x00000001 << 1)
|
||||
#define GPS_NAV_ATT_ROLL_ENABLE (uint32_t)(0x00000001 << 2)
|
||||
#define GPS_NAV_ATT_PITCH_ENABLE (uint32_t)(0x00000001 << 3)
|
||||
#define GPS_NAV_ATT_HEADING_ENABLE (uint32_t)(0x00000001 << 4)
|
||||
#define GPS_NAV_ATT_ACCROLL_ENABLE (uint32_t)(0x00000001 << 5)
|
||||
#define GPS_NAV_ATT_ACCPITCH_ENABLE (uint32_t)(0x00000001 << 6)
|
||||
#define GPS_NAV_ATT_ACCHEADING_ENABLE (uint32_t)(0x00000001 << 7)
|
||||
|
||||
#define GPS_ESF_STATUS_ITOW_ENABLE (uint32_t)(0x00000001 << 8)
|
||||
#define GPS_ESF_STATUS_VERSION_ENABLE (uint32_t)(0x00000001 << 9)
|
||||
#define GPS_ESF_STATUS_INITSTATUS1_ENABLE (uint32_t)(0x00000001 << 10)
|
||||
#define GPS_ESF_STATUS_INITSTATUS2_ENABLE (uint32_t)(0x00000001 << 11)
|
||||
#define GPS_ESF_STATUS_FUSIONMODE_ENABLE (uint32_t)(0x00000001 << 12)
|
||||
#define GPS_ESF_STATUS_NUMSENS_ENABLE (uint32_t)(0x00000001 << 13)
|
||||
#define GPS_ESF_STATUS_SENSSTATUS_ENABLE (uint32_t)(0x00000001 << 14)
|
||||
|
||||
#define GPS_UDR_STATUS_ENABLE (uint32_t)(0x00000001 << 15)
|
||||
|
||||
|
||||
// Data stream frequency
|
||||
#define DATA_STREAM_FREQ_5HZ 5
|
||||
#define DATA_STREAM_FREQ_10HZ 10
|
||||
#define DATA_STREAM_FREQ_50HZ 50
|
||||
#define DATA_STREAM_FREQ_100HZ 100
|
||||
#define DATA_STREAM_FREQ_250HZ 250
|
||||
#define DATA_STREAM_FREQ_500HZ 500
|
||||
#define DATA_STREAM_FREQ_1000HZ 1000
|
||||
|
||||
//Gyro Range
|
||||
#define GYR_RANGE_400DPS 400
|
||||
#define GYR_RANGE_1000DPS 1000
|
||||
#define GYR_RANGE_2000DPS 2000
|
||||
|
||||
//Acc Range
|
||||
#define ACC_RANGE_2G 2
|
||||
#define ACC_RANGE_4G 4
|
||||
#define ACC_RANGE_8G 8
|
||||
#define ACC_RANGE_16G 16
|
||||
|
||||
//Mag Range
|
||||
#define MAG_RANGE_2GUASS 2
|
||||
#define MAG_RANGE_8GUASS 8
|
||||
|
||||
//Filter Mode
|
||||
#define LPMS_FILTER_GYR 0
|
||||
#define LPMS_FILTER_KALMAN_GYR_ACC 1
|
||||
#define LPMS_FILTER_KALMAN_GYR_ACC_MAG 2
|
||||
#define LPMS_FILTER_DCM_GYR_ACC 3
|
||||
#define LPMS_FILTER_DCM_GYR_ACC_MAG 4
|
||||
|
||||
#define LPMS_OFFSET_MODE_OBJECT 0
|
||||
#define LPMS_OFFSET_MODE_HEADING 1
|
||||
#define LPMS_OFFSET_MODE_ALIGNMENT 2
|
||||
|
||||
// UART Settings
|
||||
#define LPMS_UART_DATA_PRECISION_FIXED_POINT 0
|
||||
#define LPMS_UART_DATA_PRECISION_FLOATING_POINT 1
|
||||
|
||||
#define LPMS_UART_BAUDRATE_9600 9600
|
||||
#define LPMS_UART_BAUDRATE_19200 19200
|
||||
#define LPMS_UART_BAUDRATE_38400 38400
|
||||
#define LPMS_UART_BAUDRATE_57600 57600
|
||||
#define LPMS_UART_BAUDRATE_115200 115200
|
||||
#define LPMS_UART_BAUDRATE_230400 230400
|
||||
#define LPMS_UART_BAUDRATE_256000 256000
|
||||
#define LPMS_UART_BAUDRATE_460800 460800
|
||||
#define LPMS_UART_BAUDRATE_921600 921600
|
||||
|
||||
#define LPMS_UART_DATA_FORMAT_LPBUS 0
|
||||
#define LPMS_UART_DATA_FORMAT_ASCII 1
|
||||
|
||||
// CAN bus baudrate values
|
||||
#define LPMS_CAN_BAUDRATE_125K 125
|
||||
#define LPMS_CAN_BAUDRATE_250K 250
|
||||
#define LPMS_CAN_BAUDRATE_500K 500
|
||||
#define LPMS_CAN_BAUDRATE_800K 800
|
||||
#define LPMS_CAN_BAUDRATE_1M 1000
|
||||
|
||||
#define LPMS_CAN_HEARTBEAT_005 0
|
||||
#define LPMS_CAN_HEARTBEAT_010 1
|
||||
#define LPMS_CAN_HEARTBEAT_020 2
|
||||
#define LPMS_CAN_HEARTBEAT_050 5
|
||||
#define LPMS_CAN_HEARTBEAT_100 10
|
||||
|
||||
#define LPMS_CAN_MODE_CANOPEN 0
|
||||
#define LPMS_CAN_MODE_SEQUENTIAL 1
|
||||
|
||||
#define LPMS_CAN_DATA_PRECISION_FIXED_POINT 0
|
||||
#define LPMS_CAN_DATA_PRECISION_FLOATING_POINT 1
|
||||
|
||||
// CAN Mapping
|
||||
enum CanMapping {
|
||||
LPMS_CAN_MAPPING_DISABLE = 0,
|
||||
LPMS_CAN_MAPPING_ACC_RAW_X = 1,
|
||||
LPMS_CAN_MAPPING_ACC_RAW_Y,
|
||||
LPMS_CAN_MAPPING_ACC_RAW_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_ACC_CALIBRATED_X,
|
||||
LPMS_CAN_MAPPING_ACC_CALIBRATED_Y,
|
||||
LPMS_CAN_MAPPING_ACC_CALIBRATED_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_GYR0_RAW_X,
|
||||
LPMS_CAN_MAPPING_GYR0_RAW_Y,
|
||||
LPMS_CAN_MAPPING_GYR0_RAW_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_GYR1_RAW_X,
|
||||
LPMS_CAN_MAPPING_GYR1_RAW_Y,
|
||||
LPMS_CAN_MAPPING_GYR1_RAW_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_GYR0_BIAS_CALIBRATED_X,
|
||||
LPMS_CAN_MAPPING_GYR0_BIAS_CALIBRATED_Y,
|
||||
LPMS_CAN_MAPPING_GYR0_BIAS_CALIBRATED_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_GYR1_BIAS_CALIBRATED_X,
|
||||
LPMS_CAN_MAPPING_GYR1_BIAS_CALIBRATED_Y,
|
||||
LPMS_CAN_MAPPING_GYR1_BIAS_CALIBRATED_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_GYR0_ALIGN_CALIBRATED_X,
|
||||
LPMS_CAN_MAPPING_GYR0_ALIGN_CALIBRATED_Y,
|
||||
LPMS_CAN_MAPPING_GYR0_ALIGN_CALIBRATED_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_GYR1_ALIGN_CALIBRATED_X,
|
||||
LPMS_CAN_MAPPING_GYR1_ALIGN_CALIBRATED_Y,
|
||||
LPMS_CAN_MAPPING_GYR1_ALIGN_CALIBRATED_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_MAG_RAW_X,
|
||||
LPMS_CAN_MAPPING_MAG_RAW_Y,
|
||||
LPMS_CAN_MAPPING_MAG_RAW_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_MAG_CALIBRATED_X,
|
||||
LPMS_CAN_MAPPING_MAG_CALIBRATED_Y,
|
||||
LPMS_CAN_MAPPING_MAG_CALIBRATED_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_ANGULAR_VELOCITY_X,
|
||||
LPMS_CAN_MAPPING_ANGULAR_VELOCITY_Y,
|
||||
LPMS_CAN_MAPPING_ANGULAR_VELOCITY_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_QUAT_W,
|
||||
LPMS_CAN_MAPPING_QUAT_X,
|
||||
LPMS_CAN_MAPPING_QUAT_Y,
|
||||
LPMS_CAN_MAPPING_QUAT_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_EULER_X,
|
||||
LPMS_CAN_MAPPING_EULER_Y,
|
||||
LPMS_CAN_MAPPING_EULER_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_LINACC_X,
|
||||
LPMS_CAN_MAPPING_LINACC_Y,
|
||||
LPMS_CAN_MAPPING_LINACC_Z,
|
||||
|
||||
LPMS_CAN_MAPPING_PRESSURE,
|
||||
LPMS_CAN_MAPPING_TEMPERATURE,
|
||||
LPMS_CAN_MAPPING_MAX
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,95 @@
|
||||
/***********************************************************************
|
||||
** Copyright (C) 2019 LP-Research
|
||||
** All rights reserved.
|
||||
** Contact: LP-Research (info@lp-research.com)
|
||||
**
|
||||
** This file is part of the Open Motion Analysis Toolkit (OpenMAT).
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with
|
||||
** or without modification, are permitted provided that the
|
||||
** following conditions are met:
|
||||
**
|
||||
** Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#include "MicroMeasure.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
static const unsigned usec_per_sec = 1000000;
|
||||
static const unsigned usec_per_msec = 1000;
|
||||
|
||||
bool QueryPerformanceFrequency(long long *frequency)
|
||||
{
|
||||
*frequency = (long long)usec_per_sec;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryPerformanceCounter(long long *performance_count)
|
||||
{
|
||||
struct timeval time;
|
||||
|
||||
assert(performance_count != NULL);
|
||||
|
||||
gettimeofday(&time, NULL);
|
||||
*performance_count = time.tv_usec + time.tv_sec * (long long)usec_per_sec;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MicroMeasure::MicroMeasure()
|
||||
{
|
||||
long long ticksPerSecond;
|
||||
|
||||
QueryPerformanceFrequency(&ticksPerSecond);
|
||||
tpm = ticksPerSecond;
|
||||
start_time = 0LL;
|
||||
}
|
||||
|
||||
void MicroMeasure::reset(void)
|
||||
{
|
||||
long long tick;
|
||||
|
||||
QueryPerformanceCounter(&tick);
|
||||
start_time = tick;
|
||||
}
|
||||
|
||||
long long MicroMeasure::measure(void)
|
||||
{
|
||||
long long tick;
|
||||
|
||||
QueryPerformanceCounter(&tick);
|
||||
|
||||
return (((tick - start_time) * 1000LL * 1000LL) / tpm);
|
||||
}
|
||||
|
||||
void MicroMeasure::sleep(long long s_t)
|
||||
{
|
||||
reset();
|
||||
|
||||
while (measure() < s_t)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/***********************************************************************
|
||||
** Copyright (C) 2019 LP-Research
|
||||
** All rights reserved.
|
||||
** Contact: LP-Research (info@lp-research.com)
|
||||
**
|
||||
** This file is part of the Open Motion Analysis Toolkit (OpenMAT).
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with
|
||||
** or without modification, are permitted provided that the
|
||||
** following conditions are met:
|
||||
**
|
||||
** Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef MICRO_MEASURE
|
||||
#define MICRO_MEASURE
|
||||
|
||||
class MicroMeasure
|
||||
{
|
||||
public:
|
||||
MicroMeasure();
|
||||
void reset(void);
|
||||
long long measure(void);
|
||||
void sleep(long long s_t);
|
||||
|
||||
public:
|
||||
long long start_time;
|
||||
long long tpm;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
/***********************************************************************
|
||||
** Copyright (C) 2013 LP-Research
|
||||
** All rights reserved.
|
||||
** Contact: LP-Research (info@lp-research.com)
|
||||
**
|
||||
** This file is part of the Open Motion Analysis Toolkit (OpenMAT).
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with
|
||||
** or without modification, are permitted provided that the
|
||||
** following conditions are met:
|
||||
**
|
||||
** Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "MicroMeasure.h"
|
||||
|
||||
MicroMeasure::MicroMeasure()
|
||||
{
|
||||
LARGE_INTEGER ticksPerSecond;
|
||||
|
||||
QueryPerformanceFrequency(&ticksPerSecond);
|
||||
|
||||
tpm = ticksPerSecond.QuadPart;
|
||||
|
||||
start_time = 0;
|
||||
}
|
||||
|
||||
void MicroMeasure::reset(void)
|
||||
{
|
||||
LARGE_INTEGER tick;
|
||||
|
||||
QueryPerformanceCounter(&tick);
|
||||
start_time = tick.QuadPart;
|
||||
}
|
||||
|
||||
long long MicroMeasure::measure(void)
|
||||
{
|
||||
LARGE_INTEGER tick;
|
||||
|
||||
QueryPerformanceCounter(&tick);
|
||||
|
||||
return (((tick.QuadPart - start_time) * 1000 * 1000) / tpm);
|
||||
}
|
||||
|
||||
void MicroMeasure::sleep(long long s_t)
|
||||
{
|
||||
reset();
|
||||
|
||||
while (measure() < s_t)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
# LPMS-IG1/BE/NAV3 Series OpenSource Lib
|
||||
|
||||
|
||||
## Usage
|
||||
### 1.Compiling Library programs
|
||||
```bash
|
||||
$ cd ~
|
||||
$ git clone https://bitbucket.org/lpresearch/lpmsig1opensourcelib
|
||||
$ cd lpmsig1opensourcelib
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ make package
|
||||
$ sudo dpkg -i libLpmsIG1_OpenSource-x.y.z-Linux.deb
|
||||
```
|
||||
|
||||
### 2.Compiling Sample programs
|
||||
```bash
|
||||
$ cd linux_example
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ ./LpmsIG1SimpleExample
|
||||
```
|
||||
You might require running command using sudo if current user is not in dialout group. See [Troubleshooting](#troubleshooting)
|
||||
|
||||
### 3.Compiling ROS Example programs
|
||||
```bash
|
||||
# Create ROS workspace.
|
||||
$ mkdir -p ~/catkin_ws/src
|
||||
$ cd ~/catkin_ws/src
|
||||
|
||||
# We suggest to create a symbolic link to ros_example folder instead of copying
|
||||
$ ln -s ~/lpmsig1opensourcelib/ros_example lpms_ig1_ros_example
|
||||
|
||||
# Compiling ROS example programs
|
||||
$ cd ~/catkin_ws
|
||||
$ source ./devel/setup.bash
|
||||
$ catkin_make
|
||||
```
|
||||
|
||||
Open a new terminal window and run roscore
|
||||
```bash
|
||||
$ roscore
|
||||
```
|
||||
Connect `LPMS-IG1/BE/NAV3` sensor to PC.
|
||||
Now you can run lpms_ig1 node on your other terminal windows.
|
||||
The following are some example commands to launch ros lpms_ig1 node. Please change the parameters appropriately according to your sensor settings:
|
||||
|
||||
*IG1*:
|
||||
```bash
|
||||
$ rosrun lpms_ig1 lpms_ig1_node _port:=LPMSIG1000001 _baudrate:=921600
|
||||
```
|
||||
|
||||
*IG1-RS485*:
|
||||
```bash
|
||||
$ rosrun lpms_ig1 lpms_ig1_rs485_node _port:=/dev/ttyTHS2 _baudrate:=115200 _rs485ControlPin:=388 _rs485ControlPinToggleWaitMs:=2
|
||||
|
||||
```
|
||||
|
||||
*BE*:
|
||||
```bash
|
||||
$ rosrun lpms_ig1 lpms_be1_node _port:=/dev/ttyUSB0 _baudrate:=115200
|
||||
```
|
||||
|
||||
*NAV3*:
|
||||
```bash
|
||||
$ rosrun lpms_ig1 lpms_nav3_node _port:=/dev/ttyUSB0 _baudrate:=115200
|
||||
```
|
||||
|
||||
Please refer to [Troubleshooting](#troubleshooting) section is error occurs.
|
||||
|
||||
You can print out the imu data by subscribing to `/imu/data` topic
|
||||
```bash
|
||||
#Show imu message.
|
||||
$ rostopic echo /imu/data
|
||||
#Plot imu message.
|
||||
$ rosrun rqt_plot rqt_plot
|
||||
```
|
||||
|
||||
Alternatively, you can use the sample launch file (lpmsig1.launch) start data acquisition and data plotting:
|
||||
|
||||
*IG1*:
|
||||
```
|
||||
roslaunch lpms_ig1 lpmsig1.launch
|
||||
```
|
||||
|
||||
*IG1-RS485*:
|
||||
```
|
||||
roslaunch lpms_ig1 lpmsig1_rs485.launch
|
||||
```
|
||||
|
||||
*BE1*:
|
||||
```
|
||||
roslaunch lpms_ig1 lpmsbe1.launch
|
||||
```
|
||||
|
||||
*NAV3*:
|
||||
```
|
||||
roslaunch lpms_ig1 lpmsnav3.launch
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Serial connection error
|
||||
If prompted with the following information:
|
||||
```bash
|
||||
$ rosrun lpms_ig1 lpms_ig1_node
|
||||
#Error opening [IG1] COM:/dev/ttyUSB0 disconnected
|
||||
```
|
||||
this error might be due to the fact that the current user does not have sufficient permission to access the device.
|
||||
To allow access to sensors connected via USB, you need to ensure that the user running the ROS sensor node has access to the /dev/ttyUSB devices. You can do this by adding the user to the dialout group. After this call, you should logout and login with this user to ensure the changed permissions are in effect.
|
||||
|
||||
```bash
|
||||
$ sudo adduser <username> dialout
|
||||
```
|
||||
|
||||
|
||||
|
||||
## ROS Package Summary
|
||||
|
||||
### 1. Supported Hardware
|
||||
This driver interfaces with LPMS-IG1 IMU sensor from LP-Research Inc.
|
||||
|
||||
|
||||
### 2.1 lpms_ig1_node / lpms_ig1_rs485_node / lpms_be1_node / lpms_nav3_node
|
||||
lpms_ig1_node is a driver for the LPMS-IG1 Inertial Measurement Unit. It publishes orientation, angular velocity, linear acceleration and magnetometer data (covariances are not yet supported), and complies with the [Sensor message](https://wiki.ros.org/sensor_msgs) for [IMU API](http://docs.ros.org/api/sensor_msgs/html/msg/Imu.html) and [MagneticField](http://docs.ros.org/melodic/api/sensor_msgs/html/msg/MagneticField.html) API.
|
||||
|
||||
Similarly lpms_ig1_rs485_node is a driver for the LPMS-IG1-RS485 Inertial Measurement Unit.
|
||||
|
||||
lpms_be1_node is a driver for the LPMS-BE1/BE2 Inertial Measurement Unit.
|
||||
|
||||
lpms_nav3_node is a driver for the LPMS-NAV3 Inertial Measurement Unit.
|
||||
|
||||
#### 2.1.1 Published Topics
|
||||
/imu/data ([sensor_msgs/Imu](http://docs.ros.org/api/sensor_msgs/html/msg/Imu.html))
|
||||
: Inertial data from the IMU. Includes calibrated acceleration, calibrated angular rates and orientation. The orientation is always unit quaternion.
|
||||
|
||||
/imu/mag ([sensor_msgs/MagneticField](http://docs.ros.org/melodic/api/sensor_msgs/html/msg/MagneticField.html)) *IG1 Series only*
|
||||
: Magnetometer reading from the sensor.
|
||||
|
||||
/imu/is_autocalibration_active ([std_msgs/Bool](http://docs.ros.org/api/std_msgs/html/msg/Bool.html), default: True)
|
||||
: Latched topic indicating if the gyro autocalibration feature is active
|
||||
|
||||
#### 2.1.2 Services
|
||||
/imu/calibrate_gyroscope ([std_srvs/Empty](http://docs.ros.org/api/std_srvs/html/srv/Empty.html))
|
||||
: This service activates the IMU internal gyro bias estimation function. Please make sure the IMU sensor is placed on a stable platform with minimal vibrations before calling the service. Please make sure the sensor is stationary for at least 4 seconds. The service call returns a success response once the calibration procedure is completed.
|
||||
|
||||
/imu/reset_heading ([std_srvs/Empty](http://docs.ros.org/api/std_srvs/html/srv/Empty.html))
|
||||
: This service will reset the heading (yaw) angle of the sensor to zero.
|
||||
|
||||
/imu/enable_gyro_autocalibration ([std_srvs/SetBool](http://docs.ros.org/melodic/api/std_srvs/html/srv/SetBool.html))
|
||||
: Turn on/off autocalibration function in the IMU. The status of autocalibration can be obtained by subscribing to the /imu/is_autocalibration_active topic. A message will published to /imu/is_autocalibration_active for each call to /imu/autocalibrate.
|
||||
|
||||
/imu/enable_auto_reconnect ([std_srvs/SetBool](http://docs.ros.org/melodic/api/std_srvs/html/srv/SetBool.html))
|
||||
: Turn on/off auto reconnect function in the library. When auto reconnect is enabled, the library will reestablish connection to the sensor if it detects no data from the sensor for more than 5 seconds. With auto reconnect enabled, the library will automatically put the sensor into streaming mode. We recommend to disable auto reconnect if user plans to interact with sensor via polling method.
|
||||
|
||||
/imu/get_imu_data ([std_srvs/Empty](http://docs.ros.org/api/std_srvs/html/srv/Empty.html)) *IG1-RS485 only*
|
||||
: Poll imu sensor for latest sensor data. Latest sensor data will be publish to /imu/data topic once the driver received a new data from the sensor.
|
||||
|
||||
/imu/set_streaming_mode ([std_srvs/Empty](http://docs.ros.org/api/std_srvs/html/srv/Empty.html)) *IG1-RS485 only*
|
||||
: Put sensor into streaming mode
|
||||
|
||||
/imu/set_command_mode ([std_srvs/Empty](http://docs.ros.org/api/std_srvs/html/srv/Empty.html)) *IG1-RS485 only*
|
||||
: Put sensor into command mode
|
||||
|
||||
#### 2.1.3 Parameters
|
||||
|
||||
~port (string, default: /dev/ttyUSB0)
|
||||
: The port the IMU is connected to.
|
||||
|
||||
~baudrate (int, default IG1: 921600, IG1-RS485: 115200, BE1: 115200)
|
||||
: Baudrate for the IMU sensor.
|
||||
|
||||
~autoreconnect (bool, default True)
|
||||
: Enable/disable autoreconnect in library
|
||||
|
||||
~frame_id (string, default: imu)
|
||||
: The frame in which imu readings will be returned.
|
||||
|
||||
~data_process_rate (int, default: 200)
|
||||
: Data processing rate of the internal loop. This rate has to be equal or larger than the data streaming frequency of the sensor to prevent internal data queue overflow.
|
||||
|
||||
~rs485ControlPin (int, default: -1 (disabled)) *IG1-RS485 only*
|
||||
: RS485 send/receive control pin. The driver will automatically toggle this pin to HIGH when sending message and set the pin to LOW once data is sent.
|
||||
|
||||
~rs485ControlPinToggleWaitMs (int, default(ms): 1 ) *IG1-RS485 only*
|
||||
: Delay (in millisecond) to wait before rs485ControlPin is toggled before/after sending data.
|
||||
|
||||
For further information on `LP-Research`, please visit our website:
|
||||
|
||||
* http://www.lp-research.com
|
||||
|
||||
* http://www.alubi.cn
|
||||
@@ -0,0 +1,5 @@
|
||||
Library for communicating and interfacing with LP-Research LpmsIG1 sensors. This library contains classes that allow a user to integrate LPMS devices into their own applications.
|
||||
This library provides following features:
|
||||
* Low level configuration of Lpms sensor through LpProtocol
|
||||
* Easy-to-use reader and writer.
|
||||
For more infomation on how to use this library, please visit http://www.lp-research.com
|
||||
@@ -0,0 +1,466 @@
|
||||
/***********************************************************************
|
||||
** Copyright (C) 2019 LP-Research
|
||||
** All rights reserved.
|
||||
** Contact: LP-Research (klaus@lp-research.com)
|
||||
**
|
||||
** This file is part of the Open Motion Analysis Toolkit (OpenMAT).
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with
|
||||
** or without modification, are permitted provided that the
|
||||
** following conditions are met:
|
||||
**
|
||||
** Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SENSOR_DATA
|
||||
#define SENSOR_DATA
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
#include "LpMatrix.h"
|
||||
#include "LpmsIG1Registers.h"
|
||||
#include "LpUtil.h"
|
||||
|
||||
#include "SensorDataI.h"
|
||||
|
||||
struct IG1ImuData :IG1ImuDataI
|
||||
{
|
||||
IG1ImuData()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void setData(uint32_t transmitDataConfig, unsigned char *_data, int length) {
|
||||
|
||||
dataSize = length / 4 -1;
|
||||
memcpy(data, _data+4, dataSize*4);
|
||||
|
||||
uint2char i2c;
|
||||
floatArray2char f2c;
|
||||
|
||||
int dataIdx = 0;
|
||||
|
||||
memcpy(i2c.c, _data, 4);
|
||||
timestamp = i2c.int_val;
|
||||
dataIdx += 4;
|
||||
|
||||
// 32-bit Floating Point
|
||||
if (transmitDataConfig & TDR_ACC_RAW_OUTPUT_ENABLED) {
|
||||
memcpy(accRaw.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
if (transmitDataConfig & TDR_ACC_CALIBRATED_OUTPUT_ENABLED) {
|
||||
memcpy(accCalibrated.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
if (transmitDataConfig & TDR_GYR0_RAW_OUTPUT_ENABLED) {
|
||||
memcpy(gyroIRaw.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
if (transmitDataConfig & TDR_GYR1_RAW_OUTPUT_ENABLED) {
|
||||
memcpy(gyroIIRaw.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_GYR0_BIAS_CALIBRATED_OUTPUT_ENABLED) {
|
||||
memcpy(gyroIBiasCalibrated.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
if (transmitDataConfig & TDR_GYR1_BIAS_CALIBRATED_OUTPUT_ENABLED) {
|
||||
memcpy(gyroIIBiasCalibrated.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_GYR0_ALIGN_CALIBRATED_OUTPUT_ENABLED) {
|
||||
memcpy(gyroIAlignmentCalibrated.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
if (transmitDataConfig & TDR_GYR1_ALIGN_CALIBRATED_OUTPUT_ENABLED) {
|
||||
memcpy(gyroIIAlignmentCalibrated.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_MAG_RAW_OUTPUT_ENABLED) {
|
||||
memcpy(magRaw.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_MAG_CALIBRATED_OUTPUT_ENABLED) {
|
||||
memcpy(f2c.c, _data + dataIdx, 12);
|
||||
memcpy(magCalibrated.data, f2c.float_val, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_ANGULAR_VELOCITY_OUTPUT_ENABLED) {
|
||||
memcpy(angularVelocity.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_QUAT_OUTPUT_ENABLED) {
|
||||
memcpy(quaternion.data, _data + dataIdx, 16);
|
||||
dataIdx += 16;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_EULER_OUTPUT_ENABLED) {
|
||||
memcpy(euler.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_LINACC_OUTPUT_ENABLED) {
|
||||
memcpy(linAcc.data, _data + dataIdx, 12);
|
||||
dataIdx += 12;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_PRESSURE_OUTPUT_ENABLED) {
|
||||
memcpy(f2c.c, _data + dataIdx, 4);
|
||||
pressure = f2c.float_val[0];
|
||||
dataIdx += 4;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_ALTITUDE_OUTPUT_ENABLED) {
|
||||
memcpy(f2c.c, _data + dataIdx, 4);
|
||||
altitude = f2c.float_val[0];
|
||||
dataIdx += 4;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_TEMPERATURE_OUTPUT_ENABLED) {
|
||||
memcpy(f2c.c, _data + dataIdx, 4);
|
||||
temperature = f2c.float_val[0];
|
||||
dataIdx += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void setData16bit(uint32_t useRadianOutput, uint32_t transmitDataConfig, unsigned char *_data) {
|
||||
|
||||
uint2char i2c;
|
||||
int dataIdx = 0;
|
||||
|
||||
memcpy(i2c.c, _data, 4);
|
||||
timestamp = i2c.int_val;
|
||||
dataIdx += 4;
|
||||
|
||||
float useRadianOutputFactor;
|
||||
|
||||
if (useRadianOutput)
|
||||
{
|
||||
useRadianOutputFactor = 100.0f;
|
||||
}
|
||||
else {
|
||||
useRadianOutputFactor = 10.0f;
|
||||
}
|
||||
|
||||
//16-bit fixed point
|
||||
if (transmitDataConfig & TDR_ACC_RAW_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
accRaw.data[i] = ((float)s) / 1000.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_ACC_CALIBRATED_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
accCalibrated.data[i] = ((float)s) / 1000.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
if (transmitDataConfig & TDR_GYR0_RAW_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
gyroIRaw.data[i] = ((float)s) / useRadianOutputFactor;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
if (transmitDataConfig & TDR_GYR1_RAW_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
gyroIIRaw.data[i] = ((float)s) / useRadianOutputFactor;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_GYR0_BIAS_CALIBRATED_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
gyroIBiasCalibrated.data[i] = ((float)s) / useRadianOutputFactor;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
if (transmitDataConfig & TDR_GYR1_BIAS_CALIBRATED_OUTPUT_ENABLED) {
|
||||
//if (useRadianOutput) //100.0f
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
gyroIIBiasCalibrated.data[i] = ((float)s) / useRadianOutputFactor;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_GYR0_ALIGN_CALIBRATED_OUTPUT_ENABLED) {
|
||||
//if (useRadianOutput) //100.0f
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
gyroIAlignmentCalibrated.data[i] = ((float)s) / useRadianOutputFactor;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
if (transmitDataConfig & TDR_GYR1_ALIGN_CALIBRATED_OUTPUT_ENABLED) {
|
||||
//if (useRadianOutput) //100.0f
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
gyroIIAlignmentCalibrated.data[i] = ((float)s) / useRadianOutputFactor;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_MAG_RAW_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
magRaw.data[i] = ((float)s) / 100.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_MAG_CALIBRATED_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
magCalibrated.data[i] = ((float)s) / 100.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_ANGULAR_VELOCITY_OUTPUT_ENABLED) {
|
||||
//if (useRadianOutput)
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
angularVelocity.data[i] = ((float)s) / 100.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_QUAT_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
quaternion.data[i] = ((float)s) / 10000.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_EULER_OUTPUT_ENABLED) {
|
||||
|
||||
if (useRadianOutput) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
euler.data[i] = ((float) s) / 10000.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
euler.data[i] = ((float)s) / 100.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_LINACC_OUTPUT_ENABLED) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
linAcc.data[i] = ((float)s) / 1000.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_PRESSURE_OUTPUT_ENABLED) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
pressure = ((float)s) / 100.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_ALTITUDE_OUTPUT_ENABLED) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
altitude = ((float)s) / 10.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
|
||||
if (transmitDataConfig & TDR_TEMPERATURE_OUTPUT_ENABLED) {
|
||||
int16_t s = _data[dataIdx] + _data[dataIdx + 1] * 256;
|
||||
temperature = ((float)s) / 100.0f;
|
||||
dataIdx += 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct IG1Info : IG1InfoI
|
||||
{
|
||||
|
||||
IG1Info()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct IG1AdvancedSettings : IG1SettingsI
|
||||
{
|
||||
IG1AdvancedSettings()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// GPS Data
|
||||
////////////////////////////////
|
||||
struct IG1GpsData : IG1GpsDataI
|
||||
{
|
||||
IG1GpsData()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void setData(uint32_t gpsPVT_DataConfig, uint32_t gpsATT_DataConfig, unsigned char *_data)
|
||||
{
|
||||
int dataIdx = 0;
|
||||
|
||||
uint2char i2c;
|
||||
memcpy(i2c.c, _data, 4);
|
||||
timestamp = i2c.int_val;
|
||||
dataIdx += 4;
|
||||
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_ITOW_ENABLE) { memcpy(&pvt.iTOW, _data + dataIdx, sizeof(pvt.iTOW)); dataIdx += sizeof(pvt.iTOW); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_YEAR_ENABLE) { memcpy(&pvt.year, _data + dataIdx, sizeof(pvt.year)); dataIdx += sizeof(pvt.year); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_MONTH_ENABLE) { memcpy(&pvt.month, _data + dataIdx, sizeof(pvt.month)); dataIdx += sizeof(pvt.month); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_DAY_ENABLE) { memcpy(&pvt.day, _data + dataIdx, sizeof(pvt.day)); dataIdx += sizeof(pvt.day); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_HOUR_ENABLE) { memcpy(&pvt.hour, _data + dataIdx, sizeof(pvt.hour)); dataIdx += sizeof(pvt.hour); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_MIN_ENABLE) { memcpy(&pvt.min, _data + dataIdx, sizeof(pvt.min)); dataIdx += sizeof(pvt.min); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_SEC_ENABLE) { memcpy(&pvt.sec, _data + dataIdx, sizeof(pvt.sec)); dataIdx += sizeof(pvt.sec); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_VALID_ENABLE) { memcpy(&pvt.valid, _data + dataIdx, sizeof(pvt.valid)); dataIdx += sizeof(pvt.valid); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_TACC_ENABLE) { memcpy(&pvt.tAcc, _data + dataIdx, sizeof(pvt.tAcc)); dataIdx += sizeof(pvt.tAcc); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_NANO_ENABLE) { memcpy(&pvt.nano, _data + dataIdx, sizeof(pvt.nano)); dataIdx += sizeof(pvt.nano); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_FIXTYPE_ENABLE) { memcpy(&pvt.fixType, _data + dataIdx, sizeof(pvt.fixType)); dataIdx += sizeof(pvt.fixType); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_FLAGS_ENABLE) { memcpy(&pvt.flags, _data + dataIdx, sizeof(pvt.flags)); dataIdx += sizeof(pvt.flags); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_FLAGS2_ENABLE) { memcpy(&pvt.flags2, _data + dataIdx, sizeof(pvt.flags2)); dataIdx += sizeof(pvt.flags2); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_NUMSV_ENABLE) { memcpy(&pvt.numSV, _data + dataIdx, sizeof(pvt.numSV)); dataIdx += sizeof(pvt.numSV); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_LONGITUDE_ENABLE) { memcpy(&pvt.longitude, _data + dataIdx, sizeof(pvt.longitude)); dataIdx += sizeof(pvt.longitude); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_LATITUDE_ENABLE) { memcpy(&pvt.latitude, _data + dataIdx, sizeof(pvt.latitude)); dataIdx += sizeof(pvt.latitude); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_HEIGHT_ENABLE) { memcpy(&pvt.height, _data + dataIdx, sizeof(pvt.height)); dataIdx += sizeof(pvt.height); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_HMSL_ENABLE) { memcpy(&pvt.hMSL, _data + dataIdx, sizeof(pvt.hMSL)); dataIdx += sizeof(pvt.hMSL); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_HACC_ENABLE) { memcpy(&pvt.hAcc, _data + dataIdx, sizeof(pvt.hAcc)); dataIdx += sizeof(pvt.hAcc); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_VACC_ENABLE) { memcpy(&pvt.vAcc, _data + dataIdx, sizeof(pvt.vAcc)); dataIdx += sizeof(pvt.vAcc); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_VELN_ENABLE) { memcpy(&pvt.velN, _data + dataIdx, sizeof(pvt.velN)); dataIdx += sizeof(pvt.velN); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_VELE_ENABLE) { memcpy(&pvt.velE, _data + dataIdx, sizeof(pvt.velE)); dataIdx += sizeof(pvt.velE); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_VELD_ENABLE) { memcpy(&pvt.velD, _data + dataIdx, sizeof(pvt.velD)); dataIdx += sizeof(pvt.velD); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_GSPEED_ENABLE) { memcpy(&pvt.gSpeed, _data + dataIdx, sizeof(pvt.gSpeed)); dataIdx += sizeof(pvt.gSpeed); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_HEADMOT_ENABLE) { memcpy(&pvt.headMot, _data + dataIdx, sizeof(pvt.headMot)); dataIdx += sizeof(pvt.headMot); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_SACC_ENABLE) { memcpy(&pvt.sAcc, _data + dataIdx, sizeof(pvt.sAcc)); dataIdx += sizeof(pvt.sAcc); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_HEADACC_ENABLE) { memcpy(&pvt.headAcc, _data + dataIdx, sizeof(pvt.headAcc)); dataIdx += sizeof(pvt.headAcc); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_PDOP_ENABLE) { memcpy(&pvt.pDOP, _data + dataIdx, sizeof(pvt.pDOP)); dataIdx += sizeof(pvt.pDOP); }
|
||||
if (gpsPVT_DataConfig & GPS_NAV_PVT_HEADVEH_ENABLE) { memcpy(&pvt.headVeh, _data + dataIdx, sizeof(pvt.headVeh)); dataIdx += sizeof(pvt.headVeh); }
|
||||
|
||||
if (gpsATT_DataConfig & GPS_NAV_ATT_ITOW_ENABLE) { memcpy(&att.iTOW, _data + dataIdx, sizeof(pvt.iTOW)); dataIdx += sizeof(pvt.iTOW); }
|
||||
if (gpsATT_DataConfig & GPS_NAV_ATT_VERSION_ENABLE) { memcpy(&att.version, _data + dataIdx, sizeof(att.version)); dataIdx += sizeof(att.version); }
|
||||
if (gpsATT_DataConfig & GPS_NAV_ATT_ROLL_ENABLE) { memcpy(&att.roll, _data + dataIdx, sizeof(att.roll)); dataIdx += sizeof(att.roll); }
|
||||
if (gpsATT_DataConfig & GPS_NAV_ATT_PITCH_ENABLE) { memcpy(&att.pitch, _data + dataIdx, sizeof(att.pitch)); dataIdx += sizeof(att.pitch); }
|
||||
if (gpsATT_DataConfig & GPS_NAV_ATT_HEADING_ENABLE) { memcpy(&att.heading, _data + dataIdx, sizeof(att.heading)); dataIdx += sizeof(att.heading); }
|
||||
if (gpsATT_DataConfig & GPS_NAV_ATT_ACCROLL_ENABLE) { memcpy(&att.accRoll, _data + dataIdx, sizeof(att.accRoll)); dataIdx += sizeof(att.accRoll); }
|
||||
if (gpsATT_DataConfig & GPS_NAV_ATT_ACCPITCH_ENABLE) { memcpy(&att.accPitch, _data + dataIdx, sizeof(att.accPitch)); dataIdx += sizeof(att.accPitch); }
|
||||
if (gpsATT_DataConfig & GPS_NAV_ATT_ACCHEADING_ENABLE) { memcpy(&att.accHeading, _data + dataIdx, sizeof(att.accHeading)); dataIdx += sizeof(att.accHeading); }
|
||||
|
||||
if (gpsATT_DataConfig & GPS_ESF_STATUS_ITOW_ENABLE) { memcpy(&esf.iTOW, _data + dataIdx, sizeof(esf.iTOW)); dataIdx += sizeof(esf.iTOW); }
|
||||
if (gpsATT_DataConfig & GPS_ESF_STATUS_VERSION_ENABLE) { memcpy(&esf.version, _data + dataIdx, sizeof(esf.version)); dataIdx += sizeof(esf.version); }
|
||||
if (gpsATT_DataConfig & GPS_ESF_STATUS_INITSTATUS1_ENABLE) { memcpy(&esf.initStatus1, _data + dataIdx, sizeof(esf.initStatus1)); dataIdx += sizeof(esf.initStatus1); }
|
||||
if (gpsATT_DataConfig & GPS_ESF_STATUS_INITSTATUS2_ENABLE) { memcpy(&esf.initStatus2, _data + dataIdx, sizeof(esf.initStatus2)); dataIdx += sizeof(esf.initStatus2); }
|
||||
if (gpsATT_DataConfig & GPS_ESF_STATUS_FUSIONMODE_ENABLE) { memcpy(&esf.fusionMode, _data + dataIdx, sizeof(esf.fusionMode)); dataIdx += sizeof(esf.fusionMode); }
|
||||
if (gpsATT_DataConfig & GPS_ESF_STATUS_NUMSENS_ENABLE) { memcpy(&esf.numSens, _data + dataIdx, sizeof(esf.numSens)); dataIdx += sizeof(esf.numSens); }
|
||||
if (gpsATT_DataConfig & GPS_ESF_STATUS_SENSSTATUS_ENABLE) { memcpy(&esf.sensStatus, _data + dataIdx, sizeof(esf.sensStatus)); dataIdx += sizeof(esf.sensStatus); }
|
||||
|
||||
if (gpsATT_DataConfig & GPS_UDR_STATUS_ENABLE) { memcpy(&udrStatus, _data + dataIdx, sizeof(udrStatus)); dataIdx += sizeof(udrStatus); }
|
||||
|
||||
}
|
||||
|
||||
std::string getStringCSV()
|
||||
{
|
||||
std::stringstream ss;
|
||||
// int precision = 12;
|
||||
// ss << std::setprecision(precision) << std::fixed;
|
||||
ss << timestamp << ",";
|
||||
ss << pvt.iTOW << ",";
|
||||
ss << pvt.year
|
||||
<< std::setw(2) << std::setfill('0') << (int)pvt.month
|
||||
<< std::setw(2) << std::setfill('0') << (int)pvt.day << ",";
|
||||
ss << std::setw(2) << std::setfill('0') << (int)pvt.hour
|
||||
<< std::setw(2) << std::setfill('0') << (int)pvt.min
|
||||
<< std::setw(2) << std::setfill('0') << (int)pvt.sec << ",";
|
||||
ss << (int)pvt.valid << ",";
|
||||
ss << pvt.tAcc << ",";
|
||||
ss << pvt.nano << ",";
|
||||
ss << (int)pvt.fixType << ",";
|
||||
ss << (int)pvt.flags << ",";
|
||||
ss << (int)pvt.flags2 << ",";
|
||||
ss << pvt.longitude<< ",";
|
||||
ss << pvt.latitude << ",";
|
||||
ss << (int)pvt.numSV << ",";
|
||||
ss << pvt.height << ",";
|
||||
ss << pvt.hMSL << ",";
|
||||
ss << pvt.hAcc << ",";
|
||||
ss << pvt.vAcc << ",";
|
||||
ss << pvt.velN << ",";
|
||||
ss << pvt.velE << ",";
|
||||
ss << pvt.velD << ",";
|
||||
ss << pvt.gSpeed << ",";
|
||||
ss << pvt.headMot*1e-5 << ",";
|
||||
ss << pvt.sAcc << ",";
|
||||
ss << pvt.headAcc*1e-5 << ",";
|
||||
ss << pvt.pDOP*0.01 << ",";
|
||||
ss << pvt.headVeh*1e-5 << ",";
|
||||
|
||||
ss << att.iTOW << ",";
|
||||
ss << (int)att.version << ",";
|
||||
ss << att.roll*1e-5 << ",";
|
||||
ss << att.pitch*1e-5 << ",";
|
||||
ss << att.heading*1e-5 << ",";
|
||||
ss << att.accRoll*1e-5 << ",";
|
||||
ss << att.accPitch*1e-5 << ",";
|
||||
ss << att.accHeading*1e-5 << ",";
|
||||
|
||||
ss << esf.iTOW << ",";
|
||||
ss << (int)esf.version << ",";
|
||||
ss << (int)esf.initStatus1 << ",";
|
||||
ss << (int)esf.initStatus2 << ",";
|
||||
ss << (int)esf.fusionMode << ",";
|
||||
ss << (int)esf.numSens << ",";
|
||||
ss << esf.sensStatus[0] << ",";
|
||||
ss << esf.sensStatus[1] << ",";
|
||||
ss << esf.sensStatus[2] << ",";
|
||||
ss << esf.sensStatus[3] << ",";
|
||||
ss << esf.sensStatus[4] << ",";
|
||||
ss << esf.sensStatus[5] << ",";
|
||||
ss << esf.sensStatus[6] << ",";
|
||||
|
||||
ss << udrStatus;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,429 @@
|
||||
/***********************************************************************
|
||||
** Copyright (C) 2019 LP-Research
|
||||
** All rights reserved.
|
||||
** Contact: LP-Research (klaus@lp-research.com)
|
||||
**
|
||||
** This file is part of the Open Motion Analysis Toolkit (OpenMAT).
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with
|
||||
** or without modification, are permitted provided that the
|
||||
** following conditions are met:
|
||||
**
|
||||
** Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SENSOR_DATA_I_H
|
||||
#define SENSOR_DATA_I_H
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cstdio>
|
||||
#include "LpMatrix.h"
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
#include <stdio.h> //sprintf
|
||||
#endif
|
||||
|
||||
/* --- PRINTF_BYTE_TO_BINARY macro's --- */
|
||||
//https://stackoverflow.com/questions/111928/is-there-a-printf-converter-to-print-in-binary-format
|
||||
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
|
||||
#define PRINTF_BYTE_TO_BINARY_INT8(i) \
|
||||
(((i) & 0x80ll) ? '1' : '0'), \
|
||||
(((i) & 0x40ll) ? '1' : '0'), \
|
||||
(((i) & 0x20ll) ? '1' : '0'), \
|
||||
(((i) & 0x10ll) ? '1' : '0'), \
|
||||
(((i) & 0x08ll) ? '1' : '0'), \
|
||||
(((i) & 0x04ll) ? '1' : '0'), \
|
||||
(((i) & 0x02ll) ? '1' : '0'), \
|
||||
(((i) & 0x01ll) ? '1' : '0')
|
||||
|
||||
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
|
||||
PRINTF_BYTE_TO_BINARY_INT8((i) >> 8), PRINTF_BYTE_TO_BINARY_INT8(i)
|
||||
#define PRINTF_BYTE_TO_BINARY_INT32(i) \
|
||||
PRINTF_BYTE_TO_BINARY_INT16((i) >> 16), PRINTF_BYTE_TO_BINARY_INT16(i)
|
||||
#define PRINTF_BYTE_TO_BINARY_INT64(i) \
|
||||
PRINTF_BYTE_TO_BINARY_INT32((i) >> 32), PRINTF_BYTE_TO_BINARY_INT32(i)
|
||||
|
||||
#define PRINTF_BINARY_PATTERN_INT16_PP \
|
||||
PRINTF_BINARY_PATTERN_INT8 " " PRINTF_BINARY_PATTERN_INT8
|
||||
#define PRINTF_BINARY_PATTERN_INT32_PP \
|
||||
PRINTF_BINARY_PATTERN_INT16_PP " " PRINTF_BINARY_PATTERN_INT16_PP
|
||||
#define PRINTF_BINARY_PATTERN_INT64_PP \
|
||||
PRINTF_BINARY_PATTERN_INT32_PP " " PRINTF_BINARY_PATTERN_INT32_PP
|
||||
|
||||
#define PRINTF_BINARY_PATTERN_INT16 \
|
||||
PRINTF_BINARY_PATTERN_INT8 PRINTF_BINARY_PATTERN_INT8
|
||||
#define PRINTF_BINARY_PATTERN_INT32 \
|
||||
PRINTF_BINARY_PATTERN_INT16 PRINTF_BINARY_PATTERN_INT16
|
||||
/* --- end macros --- */
|
||||
|
||||
|
||||
struct IG1ImuDataI
|
||||
{
|
||||
static const int MAX_DATA_SIZE = 50;
|
||||
unsigned int timestamp;
|
||||
int dataSize;
|
||||
float data[MAX_DATA_SIZE];
|
||||
LpVector3f accRaw;
|
||||
LpVector3f accCalibrated;
|
||||
LpVector3f gyroIRaw;
|
||||
LpVector3f gyroIBiasCalibrated;
|
||||
LpVector3f gyroIAlignmentCalibrated;
|
||||
LpVector3f gyroIIRaw;
|
||||
LpVector3f gyroIIBiasCalibrated;
|
||||
LpVector3f gyroIIAlignmentCalibrated;
|
||||
LpVector3f magRaw;
|
||||
LpVector3f magCalibrated;
|
||||
LpVector3f angularVelocity;
|
||||
LpVector4f quaternion;
|
||||
LpVector3f euler;
|
||||
LpVector3f linAcc;
|
||||
float pressure;
|
||||
float altitude;
|
||||
float temperature;
|
||||
|
||||
IG1ImuDataI()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
dataSize = 0;
|
||||
timestamp = 0;
|
||||
for (int i = 0; i < MAX_DATA_SIZE; ++i)
|
||||
data[i] = 0.0f;
|
||||
|
||||
vectZero3x1(&accRaw);
|
||||
vectZero3x1(&accCalibrated);
|
||||
vectZero3x1(&gyroIRaw);
|
||||
vectZero3x1(&gyroIBiasCalibrated);
|
||||
vectZero3x1(&gyroIAlignmentCalibrated);
|
||||
vectZero3x1(&gyroIIRaw);
|
||||
vectZero3x1(&gyroIIBiasCalibrated);
|
||||
vectZero3x1(&gyroIIAlignmentCalibrated);
|
||||
|
||||
vectZero3x1(&magRaw);
|
||||
vectZero3x1(&magCalibrated);
|
||||
|
||||
vectZero3x1(&angularVelocity);
|
||||
vectZero4x1(&quaternion);
|
||||
vectZero3x1(&euler);
|
||||
vectZero3x1(&linAcc);
|
||||
pressure = 0.0f;
|
||||
altitude = 0.0f;
|
||||
temperature = 0.0f;
|
||||
}
|
||||
};
|
||||
|
||||
struct IG1InfoI
|
||||
{
|
||||
std::string firmwareInfo;
|
||||
std::string deviceName;
|
||||
std::string serialNumber;
|
||||
std::string filterVersion;
|
||||
bool iapCheckStatus;
|
||||
|
||||
IG1InfoI()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
firmwareInfo = "";
|
||||
deviceName = "";
|
||||
serialNumber = "";
|
||||
filterVersion = "";
|
||||
iapCheckStatus = 0;
|
||||
}
|
||||
|
||||
|
||||
std::string toString()
|
||||
{
|
||||
std::stringstream ss;
|
||||
int w = 20;
|
||||
ss << std::setw(w) << std::left << "Device name: " << deviceName << "\n";
|
||||
ss << std::setw(w) << std::left << "Firmware info: " << firmwareInfo << "\n";
|
||||
ss << std::setw(w) << std::left << "Filter version: " << filterVersion << "\n";
|
||||
ss << std::setw(w) << std::left << "Serial no.: " << serialNumber << "\n";
|
||||
ss << std::setw(w) << std::left << "IAP check status: " << (iapCheckStatus ? "Ready" : "Not Ready") << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct IG1SettingsI
|
||||
{
|
||||
uint32_t transmitDataConfig;
|
||||
uint32_t sensorId;
|
||||
uint32_t internalProcessingFrequency;
|
||||
uint32_t dataStreamFrequency;
|
||||
uint32_t useRadianOutput;
|
||||
uint32_t enableGyroAutocalibration;
|
||||
float gyroThreshold;
|
||||
|
||||
// Acc
|
||||
uint32_t accRange;
|
||||
|
||||
// Gyro
|
||||
uint32_t gyroRange;
|
||||
|
||||
// Mag
|
||||
uint32_t magRange;
|
||||
float magCalibrationTimeout;
|
||||
|
||||
// Filter
|
||||
uint32_t filterMode;
|
||||
|
||||
// Uart communication
|
||||
uint32_t uartBaudrate;
|
||||
uint32_t uartDataFormat;
|
||||
uint32_t uartDataPrecision;
|
||||
char uartAsciiStart;
|
||||
char uartAsciiStop;
|
||||
|
||||
// CAN Communication
|
||||
uint32_t canStartId;
|
||||
uint32_t canBaudrate;
|
||||
uint32_t canDataPrecision; // Fix point 16bit or Floating point
|
||||
uint32_t canMode; // Sequential / CANOpen
|
||||
uint32_t canMapping[16];
|
||||
uint32_t canHeartbeatTime;
|
||||
|
||||
//offset mode
|
||||
uint32_t offsetMode;
|
||||
|
||||
//gps
|
||||
uint32_t gpsTransmitDataConfig[2];
|
||||
|
||||
|
||||
IG1SettingsI()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
// general
|
||||
transmitDataConfig = 0;
|
||||
sensorId = 0;
|
||||
dataStreamFrequency = 0;
|
||||
useRadianOutput = 0;
|
||||
enableGyroAutocalibration = 0;
|
||||
gyroThreshold = 0;
|
||||
|
||||
// Acc
|
||||
accRange = 0;
|
||||
|
||||
// Gyro
|
||||
gyroRange = 0;
|
||||
|
||||
// Mag
|
||||
magRange = 0;
|
||||
magCalibrationTimeout = 0;
|
||||
|
||||
// Filter parameters
|
||||
filterMode = 0;
|
||||
|
||||
// uart communication
|
||||
uartBaudrate = 0;
|
||||
uartDataFormat = 0;
|
||||
uartDataPrecision = 0;
|
||||
uartAsciiStart = '$';
|
||||
uartAsciiStop = '\n';
|
||||
|
||||
// CAN Communication
|
||||
canStartId = 0;
|
||||
canBaudrate = 0;
|
||||
canDataPrecision = 0; // Fix point 16bit or Floating point
|
||||
canMode = 0; // Sequential / CANOpen
|
||||
memset(canMapping, 0, sizeof(canMapping[0]) * 16);
|
||||
canHeartbeatTime = 0;
|
||||
|
||||
//offset mode
|
||||
offsetMode = 0;
|
||||
|
||||
//gps
|
||||
memset(gpsTransmitDataConfig, 0, sizeof(gpsTransmitDataConfig[0]) * 2);
|
||||
}
|
||||
|
||||
std::string toString()
|
||||
{
|
||||
int w = 38;
|
||||
std::stringstream ss;
|
||||
// general
|
||||
ss << "=== General === \n";
|
||||
ss << "Transmit Data: " << transmitDataConfig << " (" << uint32ToBinaryPP(transmitDataConfig) << ")\n";
|
||||
ss << std::setw(w) << std::left << "Sensor ID: " << sensorId << "\n";
|
||||
ss << std::setw(w) << std::left << "Data stream freq: " << dataStreamFrequency << "Hz\n";
|
||||
ss << std::setw(w) << std::left << "Gyro output unit: " << (useRadianOutput ? "radian" : "deg") << "\n";
|
||||
ss << std::setw(w) << std::left << "Gyro autocalibration: " << (enableGyroAutocalibration ? "Enable" : "Disable") << "\n";
|
||||
ss << std::setw(w) << std::left << "Gyro threshold: " << gyroThreshold << "dps\n";
|
||||
|
||||
ss << "=== Acc === \n";
|
||||
ss << std::setw(w) << std::left << "Acc range: " << accRange << "G\n";
|
||||
|
||||
ss << "=== Gyro === \n";
|
||||
ss << std::setw(w) << std::left << "Gyro range: " << gyroRange << "dps\n";
|
||||
|
||||
ss << "=== Mag === \n";
|
||||
ss << std::setw(w) << std::left << "Mag range: " << magRange << "Gauss\n";
|
||||
ss << std::setw(w) << std::left << "Mag CalibrationTimeout: " << magCalibrationTimeout << " s\n";
|
||||
|
||||
ss << "=== Filter === \n";
|
||||
ss << std::setw(w) << std::left << "Filter mode: " << filterMode << "\n";
|
||||
|
||||
ss << "=== Uart === \n";
|
||||
ss << std::setw(w) << std::left << "Uart baudrate: " << uartBaudrate << "\n";
|
||||
ss << std::setw(w) << std::left << "Uart data format: " << (uartDataFormat ? "ASCII" : "LPBus") << "\n";
|
||||
ss << std::setw(w) << std::left << "Uart data precision: " << (uartDataPrecision ? "Floating point" : "Fixed point") << "\n";
|
||||
ss << std::setw(w) << std::left << "Uart ascii start: " << std::hex << "0x" << (int)uartAsciiStart << "\n";
|
||||
ss << std::setw(w) << std::left << "Uart ascii stop: " << std::hex << "0x" << (int)uartAsciiStop << "\n";
|
||||
ss << std::dec;
|
||||
|
||||
ss << "=== CAN === \n";
|
||||
ss << std::setw(w) << std::left << "CAN Start ID: " << canStartId << std::hex << "(0x" << canStartId << std::dec << ")" << "\n";
|
||||
ss << std::setw(w) << std::left << "CAN baudrate: " << canBaudrate << "\n";
|
||||
ss << std::setw(w) << std::left << "CAN data precision: " << (canDataPrecision ? "Floating point" : "Fixed point") << "\n";
|
||||
ss << std::setw(w) << std::left << "CAN Mode: " << (canMode ? "Sequential" : "CANOpen") << "\n";
|
||||
|
||||
ss << std::setw(w / 2) << std::left << "CAN Mapping:";
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
ss << canMapping[i] << " ";
|
||||
}
|
||||
ss << "\n";
|
||||
ss << std::setw(w) << std::left << "CAN Heartbeat: " << canHeartbeatTime << "\n";
|
||||
|
||||
ss << "=== Offset === \n";
|
||||
ss << std::setw(w) << std::left << "Offset Mode: " << offsetMode << "\n";
|
||||
|
||||
ss << "=== GPS === \n";
|
||||
ss << "GPS Transmit Data0: " << gpsTransmitDataConfig[0] << " (" << uint32ToBinaryPP(gpsTransmitDataConfig[0]) << ")\n";
|
||||
ss << "GPS Transmit Data1: " << gpsTransmitDataConfig[1] << " (" << uint32ToBinaryPP(gpsTransmitDataConfig[1]) << ")\n";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string uint32ToBinaryPP(uint32_t data)
|
||||
{
|
||||
char binaryFormat[36] = { 0 };
|
||||
snprintf(binaryFormat, 36, PRINTF_BINARY_PATTERN_INT32_PP, PRINTF_BYTE_TO_BINARY_INT32(data));
|
||||
return std::string(binaryFormat);
|
||||
}
|
||||
|
||||
std::string uint32ToBinary(uint32_t data)
|
||||
{
|
||||
char binaryFormat[36] = { 0 };
|
||||
snprintf(binaryFormat, 36, PRINTF_BINARY_PATTERN_INT32, PRINTF_BYTE_TO_BINARY_INT32(data));
|
||||
return std::string(binaryFormat);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// GPS Data
|
||||
////////////////////////////////
|
||||
typedef struct _NAV_PVT
|
||||
{
|
||||
uint32_t iTOW;
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint8_t min;
|
||||
uint8_t sec;
|
||||
uint8_t valid; //0xF3 Means "Time(Mask:0x02) and Date(Mask:0x01) is valid"
|
||||
uint32_t tAcc;
|
||||
int32_t nano; //unit:ns
|
||||
uint8_t fixType; //enum fixType;
|
||||
uint8_t flags; //differential correction; head of Vehicle is valid
|
||||
uint8_t flags2;
|
||||
uint8_t numSV;
|
||||
int32_t longitude;
|
||||
int32_t latitude;
|
||||
int32_t height;
|
||||
int32_t hMSL;
|
||||
uint32_t hAcc;
|
||||
uint32_t vAcc;
|
||||
int32_t velN;
|
||||
int32_t velE;
|
||||
int32_t velD;
|
||||
int32_t gSpeed;
|
||||
int32_t headMot;
|
||||
uint32_t sAcc;
|
||||
uint32_t headAcc;
|
||||
uint16_t pDOP;
|
||||
int32_t headVeh;
|
||||
|
||||
} NAV_PVT;
|
||||
|
||||
typedef struct _NAV_ATT
|
||||
{
|
||||
uint32_t iTOW;
|
||||
uint8_t version;
|
||||
int32_t roll;
|
||||
int32_t pitch;
|
||||
int32_t heading;
|
||||
uint32_t accRoll;
|
||||
uint32_t accPitch;
|
||||
uint32_t accHeading;
|
||||
|
||||
} NAV_ATT;
|
||||
|
||||
typedef struct _ESF_STATUS
|
||||
{
|
||||
uint32_t iTOW;
|
||||
uint8_t version;
|
||||
uint8_t initStatus1;
|
||||
uint8_t initStatus2;
|
||||
uint8_t fusionMode;
|
||||
uint8_t numSens;
|
||||
uint32_t sensStatus[7];
|
||||
|
||||
} ESF_STATUS;
|
||||
|
||||
struct IG1GpsDataI
|
||||
{
|
||||
unsigned int timestamp;
|
||||
NAV_PVT pvt;
|
||||
NAV_ATT att;
|
||||
ESF_STATUS esf;
|
||||
unsigned int udrStatus;
|
||||
|
||||
IG1GpsDataI()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
timestamp = 0;
|
||||
memset(&pvt, 0, sizeof(NAV_PVT));
|
||||
memset(&att, 0, sizeof(NAV_ATT));
|
||||
memset(&esf, 0, sizeof(ESF_STATUS));
|
||||
udrStatus = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,366 @@
|
||||
#include "SerialPort.h"
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
Serial::Serial():
|
||||
portNo(0),
|
||||
connected(false),
|
||||
usbMode(MODE_USB_EXPRESS)
|
||||
{
|
||||
}
|
||||
|
||||
Serial::~Serial()
|
||||
{
|
||||
//Check if we are connected before trying to disconnect
|
||||
close();
|
||||
}
|
||||
|
||||
bool Serial::open(int portno, int baudrate)
|
||||
{
|
||||
if (isConnected())
|
||||
CloseHandle(this->hSerial);
|
||||
|
||||
//if (usbMode == MODE_USB_EXPRESS)
|
||||
// return open("0001");
|
||||
|
||||
portNo = portno;
|
||||
stringstream ss;
|
||||
ss << "\\\\.\\COM" << portNo;
|
||||
string portName = ss.str();
|
||||
//We're not yet connected
|
||||
this->connected = false;
|
||||
|
||||
//Try to connect to the given port throuh CreateFile
|
||||
this->hSerial = CreateFile(portName.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
//Check if the connection was successfull
|
||||
if (this->hSerial == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("[Serial] ERROR: Invalid handle value\n");
|
||||
CloseHandle(this->hSerial);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
char mode_str[128];
|
||||
switch (baudrate)
|
||||
{
|
||||
case BAUDRATE_4800:
|
||||
strcpy(mode_str, "baud=4800");
|
||||
break;
|
||||
case BAUDRATE_9600:
|
||||
strcpy(mode_str, "baud=9600");
|
||||
break;
|
||||
case BAUDRATE_19200:
|
||||
strcpy(mode_str, "baud=19200");
|
||||
break;
|
||||
case BAUDRATE_38400:
|
||||
strcpy(mode_str, "baud=38400");
|
||||
break;
|
||||
case BAUDRATE_57600:
|
||||
strcpy(mode_str, "baud=57600");
|
||||
break;
|
||||
case BAUDRATE_115200:
|
||||
strcpy(mode_str, "baud=115200");
|
||||
break;
|
||||
case BAUDRATE_230400:
|
||||
strcpy(mode_str, "baud=230400");
|
||||
break;
|
||||
case BAUDRATE_256000:
|
||||
strcpy(mode_str, "baud=256000");
|
||||
break;
|
||||
case BAUDRATE_460800:
|
||||
strcpy(mode_str, "baud=460800");
|
||||
break;
|
||||
case BAUDRATE_921600:
|
||||
strcpy(mode_str, "baud=921600");
|
||||
break;
|
||||
}
|
||||
strcat(mode_str, " data=8");
|
||||
strcat(mode_str, " parity=n");
|
||||
strcat(mode_str, " stop=1");
|
||||
strcat(mode_str, " dtr=on rts=on");
|
||||
DCB port_settings;
|
||||
memset(&port_settings, 0, sizeof(port_settings)); /* clear the new struct */
|
||||
port_settings.DCBlength = sizeof(port_settings);
|
||||
|
||||
if (!BuildCommDCBA(mode_str, &port_settings))
|
||||
{
|
||||
printf("unable to set comport dcb settings\n");
|
||||
CloseHandle(this->hSerial);
|
||||
return false;
|
||||
}
|
||||
if (!BuildCommDCBA(mode_str, &port_settings))
|
||||
{
|
||||
printf("unable to set comport dcb settings\n");
|
||||
CloseHandle(this->hSerial);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetCommState(this->hSerial, &port_settings))
|
||||
{
|
||||
printf("unable to set comport cfg settings\n");
|
||||
CloseHandle(this->hSerial);
|
||||
return false;
|
||||
}
|
||||
|
||||
COMMTIMEOUTS Cptimeouts;
|
||||
|
||||
Cptimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
Cptimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
Cptimeouts.ReadTotalTimeoutConstant = 0;
|
||||
Cptimeouts.WriteTotalTimeoutMultiplier = 100;
|
||||
Cptimeouts.WriteTotalTimeoutConstant = 100;
|
||||
|
||||
if (!SetCommTimeouts(this->hSerial, &Cptimeouts))
|
||||
{
|
||||
printf("unable to set comport time-out settings\n");
|
||||
CloseHandle(this->hSerial);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this->connected = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serial::open(std::string deviceId, int baudrate)
|
||||
{
|
||||
bool f;
|
||||
|
||||
transform(deviceId.begin(), deviceId.end(), deviceId.begin(), ::toupper);
|
||||
this->idNumber = deviceId;
|
||||
std::cout << "[LpmsU] Lpms::connect deviceID is : " << deviceId << std::endl;
|
||||
f = false;
|
||||
|
||||
SI_STATUS siStatus;
|
||||
DWORD devercNum = 0;
|
||||
SI_DEVICE_STRING DeviceString;
|
||||
|
||||
this->idNumber = deviceId;
|
||||
|
||||
DWORD numDevs;
|
||||
if (SI_GetNumDevices(&numDevs) != SI_SUCCESS)
|
||||
return false;
|
||||
devercNum = numDevs;
|
||||
for (DWORD d = 0; d < numDevs; d++)
|
||||
{
|
||||
siStatus = SI_GetProductString(d, DeviceString, SI_RETURN_SERIAL_NUMBER);
|
||||
if (siStatus == SI_SUCCESS)
|
||||
{
|
||||
string deviceString = string(DeviceString);
|
||||
|
||||
transform(deviceString.begin(), deviceString.end(), deviceString.begin(), ::toupper);
|
||||
if (deviceId == deviceString)
|
||||
{
|
||||
devercNum = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
siStatus = SI_Open(devercNum, &cyHandle);
|
||||
siStatus = SI_SetBaudRate(cyHandle, baudrate);
|
||||
siStatus = SI_SetFlowControl(cyHandle, SI_HANDSHAKE_LINE, SI_FIRMWARE_CONTROLLED, SI_HELD_INACTIVE, SI_STATUS_INPUT, SI_STATUS_INPUT, 0);
|
||||
if (siStatus == SI_SUCCESS) {
|
||||
std::cout << "[LpmsU] SI_Open device is successul : " << deviceId << std::endl;
|
||||
|
||||
this->connected = true;
|
||||
SI_FlushBuffers(cyHandle, TRUE, TRUE);
|
||||
}
|
||||
else {
|
||||
std::cout << "[LpmsU] SI_Open device is failed : " << deviceId << std::endl;
|
||||
|
||||
this->connected = false;
|
||||
}
|
||||
|
||||
return this->connected ;
|
||||
}
|
||||
|
||||
void Serial::setMode(int mode)
|
||||
{
|
||||
usbMode = mode;
|
||||
}
|
||||
|
||||
int Serial::getMode(void)
|
||||
{
|
||||
return usbMode;
|
||||
}
|
||||
|
||||
bool Serial::close()
|
||||
{
|
||||
if (this->connected)
|
||||
{
|
||||
//We're no longer connected
|
||||
this->connected = false;
|
||||
//Close the serial handler
|
||||
if (usbMode == MODE_USB_EXPRESS)
|
||||
{
|
||||
SI_Close(cyHandle);
|
||||
|
||||
cout << "[LpmsU] Connection to " << idNumber << " closed." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CloseHandle(this->hSerial);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Serial::readData(unsigned char *buffer, unsigned int nbChar)
|
||||
{
|
||||
if (!isConnected())
|
||||
return 0;
|
||||
|
||||
if (usbMode == MODE_USB_EXPRESS)
|
||||
{
|
||||
SI_STATUS siStatus;
|
||||
PBYTE ModemStatus;
|
||||
|
||||
#ifdef _WIN32
|
||||
unsigned long eventDWord;
|
||||
unsigned long txBytes;
|
||||
unsigned long rxBytes;
|
||||
unsigned long qStatus;
|
||||
#else
|
||||
unsigned int eventDWord;
|
||||
unsigned int txBytes;
|
||||
unsigned int rxBytes;
|
||||
#endif
|
||||
|
||||
bool f = true;
|
||||
|
||||
unsigned long bytesReceived = 0;
|
||||
|
||||
if (this->connected == false) return 0;
|
||||
|
||||
siStatus = SI_CheckRXQueue(cyHandle, &rxBytes, &qStatus);
|
||||
|
||||
if (siStatus != SI_SUCCESS)
|
||||
{
|
||||
std::cout << "USB read error\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
siStatus = SI_Read(cyHandle, buffer, rxBytes, &bytesReceived);
|
||||
#else
|
||||
siStatus = SI_Read(cyHandle, buffer, rxBytes, (unsigned int *)bytesReceived);
|
||||
#endif
|
||||
|
||||
|
||||
return bytesReceived;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Number of bytes we'll have read
|
||||
DWORD bytesRead;
|
||||
//Number of bytes we'll really ask to read
|
||||
unsigned int toRead;
|
||||
|
||||
//int n;
|
||||
//ReadFile(this->hSerial, buffer, nbChar, (LPDWORD)((void *)&n), NULL);
|
||||
//return n;
|
||||
//Use the ClearCommError function to get status info on the Serial port
|
||||
ClearCommError(this->hSerial, &this->errors, &this->status);
|
||||
|
||||
//Check if there is something to read
|
||||
if (this->status.cbInQue>0)
|
||||
{
|
||||
//If there is we check if there is enough data to read the required number
|
||||
//of characters, if not we'll read only the available characters to prevent
|
||||
//locking of the application.
|
||||
if (this->status.cbInQue>nbChar)
|
||||
{
|
||||
toRead = nbChar;
|
||||
}
|
||||
else
|
||||
{
|
||||
toRead = this->status.cbInQue;
|
||||
}
|
||||
|
||||
//Try to read the require number of chars, and return the number of read bytes on success
|
||||
if (ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL))
|
||||
{
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//If nothing has been read, or that an error was detected return -1
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool Serial::writeData(const char *buffer, unsigned int nbChar)
|
||||
{
|
||||
if (!isConnected())
|
||||
{
|
||||
if (usbMode == MODE_USB_EXPRESS)
|
||||
std::cout << "Sensor " << idNumber << " not connected\n";
|
||||
else
|
||||
std::cout << "COM "<< portNo << " not connected\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usbMode == MODE_USB_EXPRESS)
|
||||
{
|
||||
SI_STATUS siStatus;
|
||||
|
||||
#ifdef _WIN32
|
||||
unsigned long bytesWritten;
|
||||
#else
|
||||
unsigned int bytesWritten;
|
||||
#endif
|
||||
|
||||
bool f = false;
|
||||
|
||||
if (this->connected == false) return false;
|
||||
|
||||
siStatus = SI_Write(cyHandle, (unsigned char *)buffer, nbChar, &bytesWritten);
|
||||
|
||||
if (siStatus == SI_SUCCESS) {
|
||||
f = true;
|
||||
}else{
|
||||
f = false;
|
||||
std::cout << "Write error\n";
|
||||
}
|
||||
return f;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD bytesSend;
|
||||
//Try to write the buffer on the Serial port
|
||||
if (!WriteFile(this->hSerial, (void *)buffer, nbChar, &bytesSend, 0))
|
||||
{
|
||||
std::cout << "Write error\n";
|
||||
//In case it don't work get comm error and return false
|
||||
ClearCommError(this->hSerial, &this->errors, &this->status);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Serial::isConnected()
|
||||
{
|
||||
//Simply return the connection status
|
||||
return this->connected;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
#ifndef SERIALCLASS_H_INCLUDED
|
||||
#define SERIALCLASS_H_INCLUDED
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include "SiUSBXp.h"
|
||||
#elif __linux__
|
||||
#include <stdio.h> // standard input / output functions
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <asm/termbits.h>
|
||||
#include <cstring>
|
||||
#include <libudev.h>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#endif
|
||||
#include "LpLog.h"
|
||||
|
||||
|
||||
const static int INCOMING_DATA_MAX_LENGTH = 2048;
|
||||
|
||||
class Serial
|
||||
{
|
||||
const std::string TAG = "SERIAL";
|
||||
public:
|
||||
enum {
|
||||
BAUDRATE_4800=4800,
|
||||
BAUDRATE_9600=9600,
|
||||
BAUDRATE_19200=19200,
|
||||
BAUDRATE_38400=38400,
|
||||
BAUDRATE_57600=57600,
|
||||
BAUDRATE_115200=115200,
|
||||
BAUDRATE_230400=230400,
|
||||
BAUDRATE_256000=256000,
|
||||
BAUDRATE_460800=460800,
|
||||
BAUDRATE_921600=921600
|
||||
};
|
||||
|
||||
static const int MODE_VCP = 0;
|
||||
static const int MODE_USB_EXPRESS = 1;
|
||||
|
||||
private:
|
||||
//Connection status
|
||||
bool connected;
|
||||
|
||||
#ifdef _WIN32
|
||||
//Serial comm handler
|
||||
HANDLE hSerial;
|
||||
//Get various information about the connection
|
||||
COMSTAT status;
|
||||
//Keep track of last error
|
||||
DWORD errors;
|
||||
|
||||
int portNo;
|
||||
|
||||
// SILAB
|
||||
HANDLE cyHandle;
|
||||
std::string idNumber;
|
||||
|
||||
#elif __linux__
|
||||
|
||||
int fd;
|
||||
std::string portNo;
|
||||
|
||||
std::map<std::string, std::string> usbDeviceMap;
|
||||
|
||||
#endif
|
||||
|
||||
int usbMode;
|
||||
|
||||
public:
|
||||
|
||||
Serial();
|
||||
|
||||
~Serial();
|
||||
|
||||
#ifdef _WIN32
|
||||
bool open(int portno, int baudrate = BAUDRATE_9600);
|
||||
bool open(std::string deviceId, int baudrate);
|
||||
#elif __linux__
|
||||
bool open(std::string portno, int baudrate = BAUDRATE_115200);
|
||||
#endif
|
||||
|
||||
// Silab USBXpress or VCP mode, default VCP mode
|
||||
void setMode(int mode = MODE_VCP);
|
||||
|
||||
int getMode(void);
|
||||
|
||||
bool close();
|
||||
|
||||
int readData(unsigned char *buffer, unsigned int nbChar);
|
||||
#ifdef _WIN32
|
||||
bool writeData(const char *buffer, unsigned int nbChar);
|
||||
#elif __linux__
|
||||
bool writeData(unsigned char *buffer, unsigned int nbChar);
|
||||
#endif
|
||||
bool isConnected();
|
||||
|
||||
#ifdef _WIN32
|
||||
int getPortNo() { return portNo; }
|
||||
#elif __linux__
|
||||
std::string getPortNo() { return portNo; }
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int set_interface_attribs (int fd, int speed, int parity);
|
||||
void createUsbDeviceMap();
|
||||
|
||||
#endif
|
||||
LpLog& log = LpLog::getInstance();
|
||||
|
||||
};
|
||||
|
||||
#endif // SERIALCLASS_H_INCLUDED
|
||||
@@ -0,0 +1,266 @@
|
||||
|
||||
#include "SerialPort.h"
|
||||
#include "LpUtil.h"
|
||||
using namespace std;
|
||||
|
||||
Serial::Serial():
|
||||
portNo(""),
|
||||
connected(false)
|
||||
{
|
||||
}
|
||||
|
||||
Serial::~Serial()
|
||||
{
|
||||
//Check if we are connected before trying to disconnect
|
||||
close();
|
||||
}
|
||||
|
||||
bool Serial::open(std::string portno, int baudrate)
|
||||
{
|
||||
if (isConnected())
|
||||
close();
|
||||
|
||||
createUsbDeviceMap();
|
||||
|
||||
map<string, string>::iterator iter = usbDeviceMap.find(portno);
|
||||
if (iter != usbDeviceMap.end())
|
||||
{
|
||||
portno = iter->second;
|
||||
}
|
||||
|
||||
fd = ::open (portno.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
|
||||
if (fd < 0)
|
||||
{
|
||||
log.e(TAG, "Error opening %s: Err %d %s\n", portno.c_str(), errno, strerror (errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (set_interface_attribs (fd, baudrate, 0) == -1)
|
||||
{
|
||||
log.e(TAG, "Error configuring serial attributes");
|
||||
return false;
|
||||
}
|
||||
|
||||
//tcflush(fd,TCIOFLUSH);
|
||||
portNo = portno;
|
||||
this->connected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Serial::close()
|
||||
{
|
||||
if (this->connected)
|
||||
{
|
||||
//We're no longer connected
|
||||
this->connected = false;
|
||||
|
||||
//tcflush(fd,TCIOFLUSH);
|
||||
//Close the serial handler
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Serial::readData(unsigned char *buffer, unsigned int nbChar)
|
||||
{
|
||||
if (!isConnected())
|
||||
return 0;
|
||||
|
||||
int bytes_avail;
|
||||
ioctl(fd, FIONREAD, &bytes_avail);
|
||||
|
||||
if (bytes_avail > INCOMING_DATA_MAX_LENGTH) {
|
||||
log.d(TAG, "Warning: Buffer overflow: %d\n", bytes_avail);
|
||||
bytes_avail = INCOMING_DATA_MAX_LENGTH;
|
||||
} else if (bytes_avail > nbChar)
|
||||
bytes_avail = nbChar;
|
||||
|
||||
int n = ::read(fd, buffer, bytes_avail);//sizeof(rxBuffer)); // read up to 100 characters if ready to read
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void Serial::setMode(int mode)
|
||||
{
|
||||
usbMode = mode;
|
||||
}
|
||||
|
||||
int Serial::getMode(void)
|
||||
{
|
||||
return usbMode;
|
||||
}
|
||||
|
||||
bool Serial::writeData(unsigned char *buffer, unsigned int nbChar)
|
||||
{
|
||||
if (!isConnected())
|
||||
{
|
||||
log.e(TAG, "Error: dongle not connected\n");
|
||||
return false;
|
||||
}
|
||||
int ret;
|
||||
ret = ::write(fd, buffer, nbChar); // send 7 character greeting
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serial::isConnected()
|
||||
{
|
||||
//Simply return the connection status
|
||||
return this->connected;
|
||||
}
|
||||
|
||||
|
||||
int Serial::set_interface_attribs (int fd, int speed, int parity)
|
||||
{
|
||||
/*
|
||||
struct termios2 tty;
|
||||
|
||||
|
||||
if (ioctl(fd, TCGETS2, &tty) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
tty.c_cflag &= ~CBAUD;
|
||||
tty.c_cflag |= BOTHER;
|
||||
tty.c_ispeed = speed;
|
||||
tty.c_ospeed = speed;
|
||||
|
||||
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
|
||||
// disable IGNBRK for mismatched speed tests; otherwise receive break
|
||||
// as \000 chars
|
||||
tty.c_iflag &= ~IGNBRK; // disable break processing
|
||||
tty.c_lflag = 0; // no signaling chars, no echo,
|
||||
// no canonical processing
|
||||
tty.c_oflag = 0; // no remapping, no delays
|
||||
tty.c_cc[VMIN] = 0; // read doesn't block
|
||||
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||||
|
||||
tty.c_iflag &= ~(IXON | IXOFF | IXANY |INLCR | IGNCR | ICRNL); //enable xon
|
||||
tty.c_iflag |=IXOFF;
|
||||
|
||||
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
|
||||
// enable reading
|
||||
|
||||
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
|
||||
tty.c_cflag |= parity;
|
||||
tty.c_cflag &= ~CSTOPB;
|
||||
tty.c_cflag &= ~CRTSCTS;
|
||||
|
||||
if (ioctl(fd, TCSETS2, &tty) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
struct termios2 config;
|
||||
|
||||
if (ioctl(fd, TCGETS2, &config) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
config.c_cflag &= ~CBAUD;
|
||||
config.c_cflag |= BOTHER;
|
||||
config.c_ispeed = speed;
|
||||
config.c_ospeed = speed;
|
||||
|
||||
|
||||
config.c_iflag &= ~(IGNBRK | IXANY | INLCR | IGNCR | ICRNL);
|
||||
config.c_iflag &= ~IXON; // disable XON/XOFF flow control (output)
|
||||
config.c_iflag &= ~IXOFF; // disable XON/XOFF flow control (input)
|
||||
config.c_cflag &= ~CRTSCTS; // disable RTS flow control
|
||||
config.c_lflag = 0;
|
||||
config.c_oflag = 0;
|
||||
config.c_cflag &= ~CSIZE;
|
||||
config.c_cflag |= CS8; // 8-bit chars
|
||||
config.c_cflag |= CLOCAL; // ignore modem controls
|
||||
config.c_cflag |= CREAD; // enable reading
|
||||
config.c_cflag &= ~(PARENB | PARODD); // disable parity
|
||||
config.c_cflag &= ~CSTOPB; // one stop bit
|
||||
config.c_cc[VMIN] = 0; // read doesn´t block
|
||||
config.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||||
|
||||
config.c_cflag |= parity;
|
||||
|
||||
if (ioctl(fd, TCSETS2, &config) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
struct termios2 config;
|
||||
|
||||
if (ioctl(fd, TCGETS2, &config) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
config.c_iflag &= ~(IGNBRK | IXANY | INLCR | IGNCR | ICRNL);
|
||||
config.c_iflag &= ~IXON; // disable XON/XOFF flow control (output)
|
||||
config.c_iflag &= ~IXOFF; // disable XON/XOFF flow control (input)
|
||||
config.c_cflag &= ~CRTSCTS; // disable RTS flow control
|
||||
config.c_lflag = 0;
|
||||
config.c_oflag = 0;
|
||||
config.c_cflag &= ~CSIZE;
|
||||
config.c_cflag |= CS8; // 8-bit chars
|
||||
config.c_cflag |= CLOCAL; // ignore modem controls
|
||||
config.c_cflag |= CREAD; // enable reading
|
||||
config.c_cflag &= ~(PARENB | PARODD); // disable parity
|
||||
config.c_cflag &= ~CSTOPB; // one stop bit
|
||||
config.c_cc[VMIN] = 0; // read doesn´t block
|
||||
config.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||||
|
||||
|
||||
if (ioctl(fd, TCSETS2, &config) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Serial::createUsbDeviceMap()
|
||||
{
|
||||
struct udev *udev;
|
||||
struct udev_device *dev;
|
||||
struct udev_enumerate *enumerate;
|
||||
struct udev_list_entry *list, *node;
|
||||
const char *path;
|
||||
|
||||
usbDeviceMap.clear();
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
{
|
||||
printf("can not create udev");
|
||||
}
|
||||
|
||||
enumerate = udev_enumerate_new(udev);
|
||||
udev_enumerate_add_match_subsystem(enumerate, "tty");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
|
||||
list = udev_enumerate_get_list_entry(enumerate);
|
||||
udev_list_entry_foreach(node, list)
|
||||
{
|
||||
path = udev_list_entry_get_name(node);
|
||||
dev = udev_device_new_from_syspath(udev, path);
|
||||
|
||||
|
||||
if (udev_device_get_property_value(dev, "ID_SERIAL_SHORT") &&
|
||||
udev_device_get_property_value(dev, "DEVNAME"))
|
||||
{
|
||||
string serialID(udev_device_get_property_value(dev, "ID_SERIAL_SHORT"));
|
||||
string devName(udev_device_get_property_value(dev, "DEVNAME"));
|
||||
|
||||
string vendorId(udev_device_get_property_value(dev, "ID_VENDOR_ID"));
|
||||
string productId(udev_device_get_property_value(dev, "ID_MODEL_ID"));
|
||||
|
||||
// Check device usb is CP2102
|
||||
if (vendorId=="10c4" && (productId=="ea60" || productId == "ea61" ))
|
||||
usbDeviceMap.insert(pair<string, string>(serialID, devName));
|
||||
}
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
build/
|
||||
bin/
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
cmake_minimum_required(VERSION 2.4.6)
|
||||
|
||||
project (LpmsIG1Example)
|
||||
|
||||
if(COMMAND cmake_policy)
|
||||
cmake_policy(SET CMP0003 NEW)
|
||||
cmake_policy(SET CMP0015 NEW)
|
||||
endif(COMMAND cmake_policy)
|
||||
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
set(BUILD_ARCHITECTURE "32-bit" CACHE STRING "")
|
||||
set_property(CACHE BUILD_ARCHITECTURE PROPERTY STRINGS "32-bit" "64-bit")
|
||||
|
||||
set(IG1_INC "./..")
|
||||
set(IG1_LIB "./lib")
|
||||
|
||||
include_directories("${IG1_INC}")
|
||||
link_directories("${IG1_LIB}")
|
||||
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -std=gnu++11")
|
||||
endif()
|
||||
|
||||
set(headers
|
||||
${IG1_INC}/LpMatrix.h
|
||||
${IG1_INC}/LpmsIG1Registers.h
|
||||
${IG1_INC}/LpmsIG1I.h
|
||||
${IG1_INC}/SensorDataI.h
|
||||
)
|
||||
|
||||
set(LpmsIG1_SimpleExample_SRCS
|
||||
${IG1_INC}/LpMatrix.c
|
||||
LpmsIG1_SimpleExample.cpp
|
||||
)
|
||||
|
||||
set(LpmsIG1_RS485Example_SRCS
|
||||
${IG1_INC}/LpMatrix.c
|
||||
LpmsIG1_RS485Example.cpp
|
||||
)
|
||||
|
||||
set(LpmsBEx_SimpleExample_SRCS
|
||||
${IG1_INC}/LpMatrix.c
|
||||
LpmsBEx_SimpleExample.cpp
|
||||
)
|
||||
|
||||
set(LpmsNAV3_SimpleExample_SRCS
|
||||
${IG1_INC}/LpMatrix.c
|
||||
LpmsNAV3_SimpleExample.cpp
|
||||
)
|
||||
|
||||
# LpmsIG1 Simple Example
|
||||
add_executable(LpmsIG1_SimpleExample ${LpmsIG1_SimpleExample_SRCS} ${headers})
|
||||
target_link_libraries(LpmsIG1_SimpleExample LpmsIG1_OpenSourceLib rt pthread udev)
|
||||
|
||||
# LpmsIG1_RS485 Example
|
||||
add_executable(LpmsIG1_RS485Example ${LpmsIG1_RS485Example_SRCS} ${headers})
|
||||
target_link_libraries(LpmsIG1_RS485Example LpmsIG1_OpenSourceLib rt pthread udev)
|
||||
|
||||
# LpmsBEx Simple Example
|
||||
add_executable(LpmsBEx_SimpleExample ${LpmsBEx_SimpleExample_SRCS} ${headers})
|
||||
target_link_libraries(LpmsBEx_SimpleExample LpmsIG1_OpenSourceLib rt pthread udev)
|
||||
|
||||
|
||||
# LpmsNAV3 Simple Example
|
||||
add_executable(LpmsNAV3_SimpleExample ${LpmsNAV3_SimpleExample_SRCS} ${headers})
|
||||
target_link_libraries(LpmsNAV3_SimpleExample LpmsIG1_OpenSourceLib rt pthread udev)
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "LpmsIG1I.h"
|
||||
#include "SensorDataI.h"
|
||||
#include "LpmsIG1Registers.h"
|
||||
|
||||
using namespace std;
|
||||
string TAG("MAIN");
|
||||
IG1I* sensor1;
|
||||
// Start print data thread
|
||||
std::thread *printThread;
|
||||
static bool printThreadIsRunning = false;
|
||||
|
||||
void logd(std::string tag, const char* str, ...)
|
||||
{
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %4s] [ %-8s]: ", "INFO", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
|
||||
void printTask()
|
||||
{
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "Sensor is not connected. Sensor Status: %d\n", sensor1->getStatus());
|
||||
logd(TAG, "printTask terminated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sensor1->commandGotoStreamingMode();
|
||||
|
||||
printThreadIsRunning = true;
|
||||
while (sensor1->getStatus() == STATUS_CONNECTED && printThreadIsRunning)
|
||||
{
|
||||
IG1ImuDataI sd;
|
||||
if (sensor1->hasImuData())
|
||||
{
|
||||
sensor1->getImuData(sd);
|
||||
float freq = sensor1->getDataFrequency();
|
||||
logd(TAG, "t(s): %.3f acc: %+2.2f %+2.2f %+2.2f gyr: %+3.2f %+3.2f %+3.2f euler: %+3.2f %+3.2f %+3.2f Hz:%3.3f \r\n",
|
||||
sd.timestamp*0.002f,
|
||||
sd.accCalibrated.data[0], sd.accCalibrated.data[1], sd.accCalibrated.data[2],
|
||||
sd.gyroIAlignmentCalibrated.data[0], sd.gyroIAlignmentCalibrated.data[1], sd.gyroIAlignmentCalibrated.data[2],
|
||||
sd.euler.data[0], sd.euler.data[1], sd.euler.data[2],
|
||||
freq);
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(2));
|
||||
}
|
||||
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "printTask terminated\n");
|
||||
}
|
||||
|
||||
void printMenu()
|
||||
{
|
||||
cout << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "Main Menu" << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "[c] Connect sensor" << endl;
|
||||
cout << "[d] Disconnect sensor" << endl;
|
||||
cout << "[0] Goto command mode" << endl;
|
||||
cout << "[1] Goto streaming mode" << endl;
|
||||
cout << "[h] Reset sensor heading" << endl;
|
||||
cout << "[i] Print sensor info" << endl;
|
||||
cout << "[s] Print sensor settings" << endl;
|
||||
cout << "[p] Print sensor data" << endl;
|
||||
cout << "[a] Toggle enable/disable auto reconnect" << endl;
|
||||
cout << "[q] quit" << endl;
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
string comportNo = "/dev/ttyUSB0";
|
||||
int baudrate = 115200;
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
}
|
||||
else if (argc == 3)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
baudrate = atoi(argv[2]);
|
||||
}
|
||||
|
||||
logd(TAG, "Connecting to %s @%d\n", comportNo.c_str(), baudrate);
|
||||
|
||||
// Create LpmsIG1 object with corresponding comport and baudrate
|
||||
sensor1 = IG1Factory();
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
sensor1->setAutoReconnectStatus(true);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
sensor1->release();
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
logd(TAG, "Waiting for sensor to connect\r\n");
|
||||
this_thread::sleep_for(chrono::milliseconds(1000));
|
||||
} while (
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
logd(TAG, "Sensor connection error status: %d\n", sensor1->getStatus());
|
||||
sensor1->release();
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
logd(TAG, "Sensor connected\n");
|
||||
printMenu();
|
||||
|
||||
bool quit = false;
|
||||
while (!quit)
|
||||
{
|
||||
char cmd = '\0';
|
||||
string input;
|
||||
getline(cin, input);
|
||||
|
||||
if (!input.empty())
|
||||
cmd = input.at(0);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case 'c':
|
||||
logd(TAG, "Connect sensor\n");
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
logd(TAG, "Disconnect sensor\n");
|
||||
sensor1->disconnect();
|
||||
break;
|
||||
|
||||
case '0':
|
||||
logd(TAG, "Goto command mode\n");
|
||||
sensor1->commandGotoCommandMode();
|
||||
break;
|
||||
|
||||
case '1':
|
||||
logd(TAG, "Goto streaming mode\n");
|
||||
sensor1->commandGotoStreamingMode();
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
logd(TAG, "Reset heading\n");
|
||||
// reset sensor heading
|
||||
sensor1->commandSetOffsetMode(LPMS_OFFSET_MODE_HEADING);
|
||||
break;
|
||||
|
||||
case 'i': {
|
||||
logd(TAG, "Print sensor info\n");
|
||||
// Print sensor info
|
||||
IG1InfoI info;
|
||||
sensor1->getInfo(info);
|
||||
cout << info.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
logd(TAG, "Print sensor settings\n");
|
||||
// Print sensor settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
cout << settings.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
logd(TAG, "Print sensor data\n");
|
||||
// Print sensor data
|
||||
if (!printThreadIsRunning)
|
||||
printThread = new std::thread(printTask);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a': {
|
||||
logd(TAG, "Toggle auto reconnect\n");
|
||||
bool b = sensor1->getAutoReconnectStatus();
|
||||
sensor1->setAutoReconnectStatus(!b);
|
||||
logd(TAG, "Auto reconnect %s\n", !b? "enabled":"disabled");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
logd(TAG, "quit\n");
|
||||
// disconnect sensor
|
||||
sensor1->disconnect();
|
||||
quit = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
printThreadIsRunning = false;
|
||||
if (printThread && printThread->joinable()) {
|
||||
printThread->join();
|
||||
printThread = NULL;
|
||||
}
|
||||
printMenu();
|
||||
break;
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
|
||||
if (printThread && printThread->joinable())
|
||||
printThread->join();
|
||||
|
||||
// release sensor resources
|
||||
sensor1->release();
|
||||
logd(TAG, "Bye\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "LpmsIG1I.h"
|
||||
#include "SensorDataI.h"
|
||||
#include "LpmsIG1Registers.h"
|
||||
|
||||
using namespace std;
|
||||
string TAG("MAIN");
|
||||
IG1I* sensor1;
|
||||
// Start print data thread
|
||||
std::thread *printThread;
|
||||
static bool printThreadIsRunning = false;
|
||||
|
||||
void logd(std::string tag, const char* str, ...)
|
||||
{
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %4s] [ %-8s]: ", "INFO", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
|
||||
void printTask()
|
||||
{
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "Sensor is not connected. Sensor Status: %d\n", sensor1->getStatus());
|
||||
logd(TAG, "printTask terminated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sensor1->commandGotoStreamingMode();
|
||||
|
||||
printThreadIsRunning = true;
|
||||
while (sensor1->getStatus() == STATUS_CONNECTED && printThreadIsRunning)
|
||||
{
|
||||
IG1ImuDataI sd;
|
||||
if (sensor1->hasImuData())
|
||||
{
|
||||
sensor1->getImuData(sd);
|
||||
float freq = sensor1->getDataFrequency();
|
||||
logd(TAG, "t(s): %.3f acc: %+2.2f %+2.2f %+2.2f gyr: %+3.2f %+3.2f %+3.2f euler: %+3.2f %+3.2f %+3.2f Hz:%3.3f \r\n",
|
||||
sd.timestamp*0.002f,
|
||||
sd.accCalibrated.data[0], sd.accCalibrated.data[1], sd.accCalibrated.data[2],
|
||||
sd.gyroIAlignmentCalibrated.data[0], sd.gyroIAlignmentCalibrated.data[1], sd.gyroIAlignmentCalibrated.data[2],
|
||||
sd.euler.data[0], sd.euler.data[1], sd.euler.data[2],
|
||||
freq);
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(2));
|
||||
}
|
||||
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "printTask terminated\n");
|
||||
}
|
||||
|
||||
void printMenu()
|
||||
{
|
||||
cout << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "Main Menu" << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "[c] Connect sensor" << endl;
|
||||
cout << "[d] Disconnect sensor" << endl;
|
||||
cout << "[0] Goto command mode" << endl;
|
||||
cout << "[1] Goto streaming mode" << endl;
|
||||
cout << "[h] Reset sensor heading" << endl;
|
||||
cout << "[i] Print sensor info" << endl;
|
||||
cout << "[s] Print sensor settings" << endl;
|
||||
cout << "[p] Print sensor data" << endl;
|
||||
cout << "[a] Toggle enable/disable auto reconnect" << endl;
|
||||
cout << "[q] quit" << endl;
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
string comportNo = "/dev/ttyUSB0";
|
||||
int baudrate = 115200;
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
}
|
||||
else if (argc == 3)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
baudrate = atoi(argv[2]);
|
||||
}
|
||||
|
||||
logd(TAG, "Connecting to %s @%d\n", comportNo.c_str(), baudrate);
|
||||
|
||||
// Create LpmsIG1 object with corresponding comport and baudrate
|
||||
sensor1 = IG1Factory();
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
sensor1->setAutoReconnectStatus(true);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
sensor1->release();
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
logd(TAG, "Waiting for sensor to connect\r\n");
|
||||
this_thread::sleep_for(chrono::milliseconds(1000));
|
||||
} while (
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
logd(TAG, "Sensor connection error status: %d\n", sensor1->getStatus());
|
||||
sensor1->release();
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
logd(TAG, "Sensor connected\n");
|
||||
printMenu();
|
||||
|
||||
bool quit = false;
|
||||
while (!quit)
|
||||
{
|
||||
char cmd = '\0';
|
||||
string input;
|
||||
getline(cin, input);
|
||||
|
||||
if (!input.empty())
|
||||
cmd = input.at(0);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case 'c':
|
||||
logd(TAG, "Connect sensor\n");
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
logd(TAG, "Disconnect sensor\n");
|
||||
sensor1->disconnect();
|
||||
break;
|
||||
|
||||
case '0':
|
||||
logd(TAG, "Goto command mode\n");
|
||||
sensor1->commandGotoCommandMode();
|
||||
break;
|
||||
|
||||
case '1':
|
||||
logd(TAG, "Goto streaming mode\n");
|
||||
sensor1->commandGotoStreamingMode();
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
logd(TAG, "Reset heading\n");
|
||||
// reset sensor heading
|
||||
sensor1->commandSetOffsetMode(LPMS_OFFSET_MODE_HEADING);
|
||||
break;
|
||||
|
||||
case 'i': {
|
||||
logd(TAG, "Print sensor info\n");
|
||||
// Print sensor info
|
||||
IG1InfoI info;
|
||||
sensor1->getInfo(info);
|
||||
cout << info.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
logd(TAG, "Print sensor settings\n");
|
||||
// Print sensor settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
cout << settings.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
logd(TAG, "Print sensor data\n");
|
||||
// Print sensor data
|
||||
if (!printThreadIsRunning)
|
||||
printThread = new std::thread(printTask);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a': {
|
||||
logd(TAG, "Toggle auto reconnect\n");
|
||||
bool b = sensor1->getAutoReconnectStatus();
|
||||
sensor1->setAutoReconnectStatus(!b);
|
||||
logd(TAG, "Auto reconnect %s\n", !b? "enabled":"disabled");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
logd(TAG, "quit\n");
|
||||
// disconnect sensor
|
||||
sensor1->disconnect();
|
||||
quit = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
printThreadIsRunning = false;
|
||||
if (printThread && printThread->joinable()) {
|
||||
printThread->join();
|
||||
printThread = NULL;
|
||||
}
|
||||
printMenu();
|
||||
break;
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
|
||||
if (printThread && printThread->joinable())
|
||||
printThread->join();
|
||||
|
||||
// release sensor resources
|
||||
sensor1->release();
|
||||
logd(TAG, "Bye\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "LpmsIG1I.h"
|
||||
#include "SensorDataI.h"
|
||||
#include "LpmsIG1Registers.h"
|
||||
|
||||
using namespace std;
|
||||
string TAG("MAIN");
|
||||
IG1I* sensor1;
|
||||
// Start print data thread
|
||||
std::thread *printThread;
|
||||
static bool printThreadIsRunning = false;
|
||||
|
||||
void logd(std::string tag, const char* str, ...)
|
||||
{
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %4s] [ %-8s]: ", "INFO", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
|
||||
void printTask()
|
||||
{
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "Sensor is not connected. Sensor Status: %d\n", sensor1->getStatus());
|
||||
logd(TAG, "printTask terminated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sensor1->commandGotoStreamingMode();
|
||||
|
||||
printThreadIsRunning = true;
|
||||
while (sensor1->getStatus() == STATUS_CONNECTED && printThreadIsRunning)
|
||||
{
|
||||
IG1ImuDataI sd;
|
||||
if (sensor1->hasImuData())
|
||||
{
|
||||
sensor1->getImuData(sd);
|
||||
float freq = sensor1->getDataFrequency();
|
||||
logd(TAG, "t(s): %.3f acc: %+2.2f %+2.2f %+2.2f gyr: %+3.2f %+3.2f %+3.2f euler: %+3.2f %+3.2f %+3.2f Hz:%3.3f \r\n",
|
||||
sd.timestamp*0.002f,
|
||||
sd.accCalibrated.data[0], sd.accCalibrated.data[1], sd.accCalibrated.data[2],
|
||||
sd.gyroIAlignmentCalibrated.data[0], sd.gyroIAlignmentCalibrated.data[1], sd.gyroIAlignmentCalibrated.data[2],
|
||||
sd.euler.data[0], sd.euler.data[1], sd.euler.data[2],
|
||||
freq);
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(2));
|
||||
}
|
||||
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "printTask terminated\n");
|
||||
}
|
||||
|
||||
void printMenu()
|
||||
{
|
||||
cout << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "Main Menu" << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "[c] Connect sensor" << endl;
|
||||
cout << "[d] Disconnect sensor" << endl;
|
||||
cout << "[0] Goto command mode" << endl;
|
||||
cout << "[1] Goto streaming mode" << endl;
|
||||
cout << "[h] Reset sensor heading" << endl;
|
||||
cout << "[i] Print sensor info" << endl;
|
||||
cout << "[s] Print sensor settings" << endl;
|
||||
cout << "[p] Print sensor data" << endl;
|
||||
cout << "[a] Toggle enable/disable auto reconnect" << endl;
|
||||
cout << "[q] quit" << endl;
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
string comportNo = "/dev/ttyTHS2";
|
||||
int baudrate = 115200;
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
}
|
||||
else if (argc == 3)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
baudrate = atoi(argv[2]);
|
||||
}
|
||||
|
||||
logd(TAG, "Connecting to %s @%d\n", comportNo.c_str(), baudrate);
|
||||
|
||||
// Create LpmsIG1 object with corresponding comport and baudrate
|
||||
sensor1 = IG1Factory();
|
||||
|
||||
// Set verbosity to INFO level to output info messages
|
||||
// Use VERBOSE_NONE to turn off all messages from library
|
||||
// Use VERBOSE_DEBUG to output debug messages
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
|
||||
// Enable auto reconnect
|
||||
sensor1->setAutoReconnectStatus(true);
|
||||
|
||||
// Set connection interface to RS485
|
||||
sensor1->setConnectionInterface(CONNECTION_INTERFACE_RS485);
|
||||
|
||||
// Set GPIO pin toggle wait time to 2ms
|
||||
sensor1->setControlGPIOToggleWaitMs(2);
|
||||
|
||||
// Use pin 388 as RS485 flow control pin
|
||||
sensor1->setControlGPIOForRs485(388);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
sensor1->release();
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
logd(TAG, "Waiting for sensor to connect\r\n");
|
||||
this_thread::sleep_for(chrono::milliseconds(1000));
|
||||
} while (
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
logd(TAG, "Sensor connection error: %d\n", sensor1->getStatus());
|
||||
sensor1->release();
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
logd(TAG, "Sensor connected\n");
|
||||
printMenu();
|
||||
|
||||
bool quit = false;
|
||||
while (!quit)
|
||||
{
|
||||
char cmd = '\0';
|
||||
string input;
|
||||
getline(cin, input);
|
||||
|
||||
if (!input.empty())
|
||||
cmd = input.at(0);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case 'c':
|
||||
logd(TAG, "Connect sensor\n");
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
logd(TAG, "Disconnect sensor\n");
|
||||
sensor1->disconnect();
|
||||
break;
|
||||
|
||||
case '0':
|
||||
logd(TAG, "Goto command mode\n");
|
||||
sensor1->commandGotoCommandMode();
|
||||
break;
|
||||
|
||||
case '1':
|
||||
logd(TAG, "Goto streaming mode\n");
|
||||
sensor1->commandGotoStreamingMode();
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
logd(TAG, "Reset heading\n");
|
||||
// reset sensor heading
|
||||
sensor1->commandSetOffsetMode(LPMS_OFFSET_MODE_HEADING);
|
||||
break;
|
||||
|
||||
case 'i': {
|
||||
logd(TAG, "Print sensor info\n");
|
||||
// Print sensor info
|
||||
IG1InfoI info;
|
||||
sensor1->getInfo(info);
|
||||
cout << info.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
logd(TAG, "Print sensor settings\n");
|
||||
// Print sensor settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
cout << settings.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
logd(TAG, "Print sensor data\n");
|
||||
// Print sensor data
|
||||
if (!printThreadIsRunning)
|
||||
printThread = new std::thread(printTask);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a': {
|
||||
logd(TAG, "Toggle auto reconnect\n");
|
||||
bool b = sensor1->getAutoReconnectStatus();
|
||||
sensor1->setAutoReconnectStatus(!b);
|
||||
logd(TAG, "Auto reconnect %s\n", !b? "enabled":"disabled");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
logd(TAG, "quit\n");
|
||||
// disconnect sensor
|
||||
sensor1->disconnect();
|
||||
quit = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
printThreadIsRunning = false;
|
||||
if (printThread && printThread->joinable()) {
|
||||
printThread->join();
|
||||
printThread = NULL;
|
||||
}
|
||||
printMenu();
|
||||
break;
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
|
||||
if (printThread && printThread->joinable())
|
||||
printThread->join();
|
||||
|
||||
// release sensor resources
|
||||
sensor1->release();
|
||||
logd(TAG, "Bye\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "LpmsIG1I.h"
|
||||
#include "SensorDataI.h"
|
||||
#include "LpmsIG1Registers.h"
|
||||
|
||||
using namespace std;
|
||||
string TAG("MAIN");
|
||||
IG1I* sensor1;
|
||||
// Start print data thread
|
||||
std::thread *printThread;
|
||||
static bool printThreadIsRunning = false;
|
||||
|
||||
void logd(std::string tag, const char* str, ...)
|
||||
{
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %4s] [ %-8s]: ", "INFO", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
|
||||
void printTask()
|
||||
{
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "Sensor is not connected. Sensor Status: %d\n", sensor1->getStatus());
|
||||
logd(TAG, "printTask terminated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sensor1->commandGotoStreamingMode();
|
||||
|
||||
printThreadIsRunning = true;
|
||||
while (sensor1->getStatus() == STATUS_CONNECTED && printThreadIsRunning)
|
||||
{
|
||||
IG1ImuDataI sd;
|
||||
if (sensor1->hasImuData())
|
||||
{
|
||||
sensor1->getImuData(sd);
|
||||
float freq = sensor1->getDataFrequency();
|
||||
logd(TAG, "t(s): %.3f acc: %+2.2f %+2.2f %+2.2f gyr: %+3.2f %+3.2f %+3.2f euler: %+3.2f %+3.2f %+3.2f Hz:%3.3f \r\n",
|
||||
sd.timestamp*0.002f,
|
||||
sd.accCalibrated.data[0], sd.accCalibrated.data[1], sd.accCalibrated.data[2],
|
||||
sd.gyroIAlignmentCalibrated.data[0], sd.gyroIAlignmentCalibrated.data[1], sd.gyroIAlignmentCalibrated.data[2],
|
||||
sd.euler.data[0], sd.euler.data[1], sd.euler.data[2],
|
||||
freq);
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(2));
|
||||
}
|
||||
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "printTask terminated\n");
|
||||
}
|
||||
|
||||
void printMenu()
|
||||
{
|
||||
cout << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "Main Menu" << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "[c] Connect sensor" << endl;
|
||||
cout << "[d] Disconnect sensor" << endl;
|
||||
cout << "[0] Goto command mode" << endl;
|
||||
cout << "[1] Goto streaming mode" << endl;
|
||||
cout << "[h] Reset sensor heading" << endl;
|
||||
cout << "[i] Print sensor info" << endl;
|
||||
cout << "[s] Print sensor settings" << endl;
|
||||
cout << "[p] Print sensor data" << endl;
|
||||
cout << "[a] Toggle enable/disable auto reconnect" << endl;
|
||||
cout << "[q] quit" << endl;
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
string comportNo = "LPMSIG1-SENSOR-ID";
|
||||
int baudrate = 921600;
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
}
|
||||
else if (argc == 3)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
baudrate = atoi(argv[2]);
|
||||
}
|
||||
|
||||
logd(TAG, "Connecting to %s @%d\n", comportNo.c_str(), baudrate);
|
||||
|
||||
// Create LpmsIG1 object with corresponding comport and baudrate
|
||||
sensor1 = IG1Factory();
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
sensor1->setAutoReconnectStatus(true);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
sensor1->release();
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
logd(TAG, "Waiting for sensor to connect\r\n");
|
||||
this_thread::sleep_for(chrono::milliseconds(1000));
|
||||
} while (
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
logd(TAG, "Sensor connection error status: %d\n", sensor1->getStatus());
|
||||
sensor1->release();
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
logd(TAG, "Sensor connected\n");
|
||||
printMenu();
|
||||
|
||||
bool quit = false;
|
||||
while (!quit)
|
||||
{
|
||||
char cmd = '\0';
|
||||
string input;
|
||||
getline(cin, input);
|
||||
|
||||
if (!input.empty())
|
||||
cmd = input.at(0);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case 'c':
|
||||
logd(TAG, "Connect sensor\n");
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
logd(TAG, "Disconnect sensor\n");
|
||||
sensor1->disconnect();
|
||||
break;
|
||||
|
||||
case '0':
|
||||
logd(TAG, "Goto command mode\n");
|
||||
sensor1->commandGotoCommandMode();
|
||||
break;
|
||||
|
||||
case '1':
|
||||
logd(TAG, "Goto streaming mode\n");
|
||||
sensor1->commandGotoStreamingMode();
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
logd(TAG, "Reset heading\n");
|
||||
// reset sensor heading
|
||||
sensor1->commandSetOffsetMode(LPMS_OFFSET_MODE_HEADING);
|
||||
break;
|
||||
|
||||
case 'i': {
|
||||
logd(TAG, "Print sensor info\n");
|
||||
// Print sensor info
|
||||
IG1InfoI info;
|
||||
sensor1->getInfo(info);
|
||||
cout << info.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
logd(TAG, "Print sensor settings\n");
|
||||
// Print sensor settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
cout << settings.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
logd(TAG, "Print sensor data\n");
|
||||
// Print sensor data
|
||||
if (!printThreadIsRunning)
|
||||
printThread = new std::thread(printTask);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a': {
|
||||
logd(TAG, "Toggle auto reconnect\n");
|
||||
bool b = sensor1->getAutoReconnectStatus();
|
||||
sensor1->setAutoReconnectStatus(!b);
|
||||
logd(TAG, "Auto reconnect %s\n", !b? "enabled":"disabled");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
logd(TAG, "quit\n");
|
||||
// disconnect sensor
|
||||
sensor1->disconnect();
|
||||
quit = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
printThreadIsRunning = false;
|
||||
if (printThread && printThread->joinable()) {
|
||||
printThread->join();
|
||||
printThread = NULL;
|
||||
}
|
||||
printMenu();
|
||||
break;
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
|
||||
if (printThread && printThread->joinable())
|
||||
printThread->join();
|
||||
|
||||
// release sensor resources
|
||||
sensor1->release();
|
||||
logd(TAG, "Bye\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "LpmsIG1I.h"
|
||||
#include "SensorDataI.h"
|
||||
#include "LpmsIG1Registers.h"
|
||||
|
||||
using namespace std;
|
||||
string TAG("MAIN");
|
||||
IG1I* sensor1;
|
||||
// Start print data thread
|
||||
std::thread *printThread;
|
||||
static bool printThreadIsRunning = false;
|
||||
|
||||
void logd(std::string tag, const char* str, ...)
|
||||
{
|
||||
va_list a_list;
|
||||
va_start(a_list, str);
|
||||
if (!tag.empty())
|
||||
printf("[ %4s] [ %-8s]: ", "INFO", tag.c_str());
|
||||
vprintf(str, a_list);
|
||||
va_end(a_list);
|
||||
}
|
||||
|
||||
void printTask()
|
||||
{
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "Sensor is not connected. Sensor Status: %d\n", sensor1->getStatus());
|
||||
logd(TAG, "printTask terminated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sensor1->commandGotoStreamingMode();
|
||||
|
||||
printThreadIsRunning = true;
|
||||
while (sensor1->getStatus() == STATUS_CONNECTED && printThreadIsRunning)
|
||||
{
|
||||
IG1ImuDataI sd;
|
||||
while (sensor1->hasImuData())
|
||||
{
|
||||
sensor1->getImuData(sd);
|
||||
float freq = sensor1->getDataFrequency();
|
||||
logd(TAG, "t(s): %.3f acc: %+2.2f %+2.2f %+2.2f gyr: %+3.2f %+3.2f %+3.2f euler: %+3.2f %+3.2f %+3.2f Hz:%3.3f \r\n",
|
||||
sd.timestamp*0.001f,
|
||||
sd.accCalibrated.data[0], sd.accCalibrated.data[1], sd.accCalibrated.data[2],
|
||||
sd.gyroIAlignmentCalibrated.data[0], sd.gyroIAlignmentCalibrated.data[1], sd.gyroIAlignmentCalibrated.data[2],
|
||||
sd.euler.data[0], sd.euler.data[1], sd.euler.data[2],
|
||||
freq);
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(2));
|
||||
}
|
||||
|
||||
printThreadIsRunning = false;
|
||||
logd(TAG, "printTask terminated\n");
|
||||
}
|
||||
|
||||
void printMenu()
|
||||
{
|
||||
cout << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "Main Menu" << endl;
|
||||
cout << "===================" << endl;
|
||||
cout << "[c] Connect sensor" << endl;
|
||||
cout << "[d] Disconnect sensor" << endl;
|
||||
cout << "[0] Goto command mode" << endl;
|
||||
cout << "[1] Goto streaming mode" << endl;
|
||||
cout << "[h] Reset sensor heading" << endl;
|
||||
cout << "[i] Print sensor info" << endl;
|
||||
cout << "[s] Print sensor settings" << endl;
|
||||
cout << "[p] Print sensor data" << endl;
|
||||
cout << "[a] Toggle enable/disable auto reconnect" << endl;
|
||||
cout << "[q] quit" << endl;
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
string comportNo = "/dev/ttyUSB0";
|
||||
int baudrate = 115200;
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
}
|
||||
else if (argc == 3)
|
||||
{
|
||||
comportNo = string(argv[1]);
|
||||
baudrate = atoi(argv[2]);
|
||||
}
|
||||
|
||||
logd(TAG, "Connecting to %s @%d\n", comportNo.c_str(), baudrate);
|
||||
|
||||
// Create LpmsIG1 object with corresponding comport and baudrate
|
||||
sensor1 = IG1Factory();
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
sensor1->setAutoReconnectStatus(true);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
sensor1->release();
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
logd(TAG, "Waiting for sensor to connect\r\n");
|
||||
this_thread::sleep_for(chrono::milliseconds(1000));
|
||||
} while (
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() != STATUS_CONNECTED)
|
||||
{
|
||||
logd(TAG, "Sensor connection error status: %d\n", sensor1->getStatus());
|
||||
sensor1->release();
|
||||
logd(TAG, "bye\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
logd(TAG, "Sensor connected\n");
|
||||
printMenu();
|
||||
|
||||
bool quit = false;
|
||||
while (!quit)
|
||||
{
|
||||
char cmd = '\0';
|
||||
string input;
|
||||
getline(cin, input);
|
||||
|
||||
if (!input.empty())
|
||||
cmd = input.at(0);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case 'c':
|
||||
logd(TAG, "Connect sensor\n");
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
logd(TAG, "Error connecting to sensor\n");
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
logd(TAG, "Disconnect sensor\n");
|
||||
sensor1->disconnect();
|
||||
break;
|
||||
|
||||
case '0':
|
||||
logd(TAG, "Goto command mode\n");
|
||||
sensor1->commandGotoCommandMode();
|
||||
break;
|
||||
|
||||
case '1':
|
||||
logd(TAG, "Goto streaming mode\n");
|
||||
sensor1->commandGotoStreamingMode();
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
logd(TAG, "Reset heading\n");
|
||||
// reset sensor heading
|
||||
sensor1->commandSetOffsetMode(LPMS_OFFSET_MODE_HEADING);
|
||||
break;
|
||||
|
||||
case 'i': {
|
||||
logd(TAG, "Print sensor info\n");
|
||||
// Print sensor info
|
||||
IG1InfoI info;
|
||||
sensor1->getInfo(info);
|
||||
cout << info.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
logd(TAG, "Print sensor settings\n");
|
||||
// Print sensor settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
cout << settings.toString() << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
logd(TAG, "Print sensor data\n");
|
||||
// Print sensor data
|
||||
if (!printThreadIsRunning)
|
||||
printThread = new std::thread(printTask);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a': {
|
||||
logd(TAG, "Toggle auto reconnect\n");
|
||||
bool b = sensor1->getAutoReconnectStatus();
|
||||
sensor1->setAutoReconnectStatus(!b);
|
||||
logd(TAG, "Auto reconnect %s\n", !b? "enabled":"disabled");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
logd(TAG, "quit\n");
|
||||
// disconnect sensor
|
||||
sensor1->disconnect();
|
||||
quit = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
printThreadIsRunning = false;
|
||||
if (printThread && printThread->joinable()) {
|
||||
printThread->join();
|
||||
printThread = NULL;
|
||||
}
|
||||
printMenu();
|
||||
break;
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
|
||||
if (printThread && printThread->joinable())
|
||||
printThread->join();
|
||||
|
||||
// release sensor resources
|
||||
sensor1->release();
|
||||
logd(TAG, "Bye\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Temporary files
|
||||
*.user
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
@@ -0,0 +1,90 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(lpms_ig1)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "-std=c++11")
|
||||
|
||||
find_package(catkin REQUIRED COMPONENTS
|
||||
roscpp
|
||||
std_msgs
|
||||
message_generation
|
||||
)
|
||||
|
||||
|
||||
generate_messages(
|
||||
DEPENDENCIES
|
||||
std_msgs
|
||||
)
|
||||
|
||||
link_directories("${IG1_LIB}")
|
||||
|
||||
set(lpms_ig1_node_SRCS
|
||||
src/lpms_ig1_node.cpp
|
||||
)
|
||||
|
||||
set(lpms_ig1_rs485_node_SRCS
|
||||
src/lpms_ig1_rs485_node.cpp
|
||||
)
|
||||
|
||||
set(lpms_ig1_rs485_client_SRCS
|
||||
src/lpms_ig1_rs485_client.cpp
|
||||
)
|
||||
|
||||
set(lpms_be1_node_SRCS
|
||||
src/lpms_be1_node.cpp
|
||||
)
|
||||
|
||||
set(lpms_nav3_node_SRCS
|
||||
src/lpms_nav3_node.cpp
|
||||
)
|
||||
|
||||
## Declare a catkin package
|
||||
catkin_package()
|
||||
|
||||
## Build
|
||||
include_directories(include ${catkin_INCLUDE_DIRS})
|
||||
|
||||
# lpms_ig1_node
|
||||
add_executable(lpms_ig1_node ${lpms_ig1_node_SRCS})
|
||||
target_link_libraries(lpms_ig1_node
|
||||
${catkin_LIBRARIES}
|
||||
LpmsIG1_OpenSourceLib.so
|
||||
)
|
||||
add_dependencies(lpms_ig1_node ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
# lpms_ig1_rs485_node
|
||||
add_executable(lpms_ig1_rs485_node ${lpms_ig1_rs485_node_SRCS})
|
||||
target_link_libraries(lpms_ig1_rs485_node
|
||||
${catkin_LIBRARIES}
|
||||
LpmsIG1_OpenSourceLib.so
|
||||
)
|
||||
add_dependencies(lpms_ig1_rs485_node ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
# lpms_ig1_rs485_client
|
||||
add_executable(lpms_ig1_rs485_client ${lpms_ig1_rs485_client_SRCS})
|
||||
target_link_libraries(lpms_ig1_rs485_client
|
||||
${catkin_LIBRARIES}
|
||||
LpmsIG1_OpenSourceLib.so
|
||||
)
|
||||
add_dependencies(lpms_ig1_rs485_client ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
# lpms_be1_node
|
||||
add_executable(lpms_be1_node ${lpms_be1_node_SRCS})
|
||||
target_link_libraries(lpms_be1_node
|
||||
${catkin_LIBRARIES}
|
||||
LpmsIG1_OpenSourceLib.so
|
||||
)
|
||||
add_dependencies(lpms_be1_node ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
|
||||
# lpms_NAV3_node
|
||||
add_executable(lpms_nav3_node ${lpms_nav3_node_SRCS})
|
||||
target_link_libraries(lpms_nav3_node
|
||||
${catkin_LIBRARIES}
|
||||
LpmsIG1_OpenSourceLib.so
|
||||
)
|
||||
add_dependencies(lpms_nav3_node ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
# imudata_rad_to_deg_node
|
||||
add_executable(imudata_rad_to_deg_node src/imudata_rad_to_deg_node.cpp)
|
||||
target_link_libraries(imudata_rad_to_deg_node ${catkin_LIBRARIES})
|
||||
add_dependencies(imudata_rad_to_deg_node ${catkin_EXPORTED_TARGETS})
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<launch>
|
||||
<!-- IG1 Sensor node -->
|
||||
<node name="lpms_be1" pkg="lpms_ig1" type="lpms_be1_node" output="screen">
|
||||
<param name="port" value="0001" type="string" />
|
||||
<param name="baudrate" value="115200" type="int" />
|
||||
<param name="frame_id" value="imu" type="string" />
|
||||
</node>
|
||||
|
||||
<!-- imudata rad to deg conversion node -->
|
||||
<node name="imudata_deg" pkg="lpms_ig1" type="imudata_rad_to_deg_node" />
|
||||
|
||||
<!-- Plots -->
|
||||
<node name="plot_imu_gyro" pkg="rqt_plot" type="rqt_plot"
|
||||
args="/angular_vel_deg" />
|
||||
|
||||
<node name="plot_imu_euler" pkg="rqt_plot" type="rqt_plot"
|
||||
args="/rpy_deg" />
|
||||
</launch>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<launch>
|
||||
<!-- IG1 Sensor node -->
|
||||
<node name="lpms_ig1" pkg="lpms_ig1" type="lpms_ig1_node">
|
||||
<param name="port" value="/dev/ttyUSB0" type="string" />
|
||||
<param name="baudrate" value="921600" type="int" />
|
||||
<param name="frame_id" value="imu" type="string" />
|
||||
</node>
|
||||
|
||||
<!-- imudata rad to deg conversion node -->
|
||||
<node name="imudata_deg" pkg="lpms_ig1" type="imudata_rad_to_deg_node" />
|
||||
|
||||
<!-- Plots -->
|
||||
<node name="plot_imu_gyro" pkg="rqt_plot" type="rqt_plot"
|
||||
args="/angular_vel_deg" />
|
||||
|
||||
<node name="plot_imu_euler" pkg="rqt_plot" type="rqt_plot"
|
||||
args="/rpy_deg" />
|
||||
</launch>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<launch>
|
||||
<!-- IG1 RS484 Sensor node -->
|
||||
<node name="lpms_ig1_rs485" pkg="lpms_ig1" type="lpms_ig1_rs485_node">
|
||||
<param name="port" value="/dev/ttyTHS5" type="string" />
|
||||
<param name="baudrate" value="115200" type="int" />
|
||||
<param name="rs485ControlPin" value="388" type="int" />
|
||||
<param name="rs485ControlPinToggleWaitMs" value="2" type="int" />
|
||||
<param name="frame_id" value="imu" type="string" />
|
||||
</node>
|
||||
|
||||
<!-- imudata rad to deg conversion node -->
|
||||
<node name="imudata_deg" pkg="lpms_ig1" type="imudata_rad_to_deg_node" />
|
||||
|
||||
<!-- Plots -->
|
||||
<node name="plot_imu_gyro" pkg="rqt_plot" type="rqt_plot"
|
||||
args="/angular_vel_deg" />
|
||||
|
||||
<node name="plot_imu_euler" pkg="rqt_plot" type="rqt_plot"
|
||||
args="/rpy_deg" />
|
||||
</launch>
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<launch>
|
||||
<!-- IG1 Sensor node -->
|
||||
<node name="lpms_nav3" pkg="lpms_ig1" type="lpms_nav3_node" output="screen">
|
||||
<param name="port" value="/dev/ttyUSB0" type="string" />
|
||||
<param name="baudrate" value="115200" type="int" />
|
||||
<param name="frame_id" value="imu" type="string" />
|
||||
</node>
|
||||
|
||||
|
||||
<!-- imudata rad to deg conversion node -->
|
||||
<node name="imudata_deg" pkg="lpms_ig1" type="imudata_rad_to_deg_node" />
|
||||
|
||||
<!-- Plots -->
|
||||
<node name="plot_imu_gyro" pkg="rqt_plot" type="rqt_plot"
|
||||
args="/angular_vel_deg" />
|
||||
|
||||
<node name="plot_imu_euler" pkg="rqt_plot" type="rqt_plot"
|
||||
args="/rpy_deg" />
|
||||
</launch>
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>lpms_ig1</name>
|
||||
<version>0.0.1</version>
|
||||
<description>ROS driver for lpms_ig1 sensors.</description>
|
||||
|
||||
<!-- One maintainer tag required, multiple allowed, one person per tag -->
|
||||
<maintainer email="lxf@alubi.cn">Feng</maintainer>
|
||||
<maintainer email="yap@lp-research.com">H.E. YAP</maintainer>
|
||||
|
||||
<!-- One license tag required, multiple allowed, one license per tag -->
|
||||
<!-- Commonly used license strings: -->
|
||||
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
|
||||
<license>TODO</license>
|
||||
|
||||
|
||||
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
|
||||
<!-- Optional attribute type can be: website, bugtracker, or repository -->
|
||||
<!-- Example: -->
|
||||
|
||||
|
||||
<!-- Author tags are optional, mutiple are allowed, one per tag -->
|
||||
<!-- Authors do not have to be maintianers, but could be -->
|
||||
<!-- Example: -->
|
||||
<!-- <author email="xxxxx">xxxxx</author> -->
|
||||
|
||||
|
||||
<!-- The *_depend tags are used to specify dependencies -->
|
||||
<!-- Dependencies can be catkin packages or system dependencies -->
|
||||
<!-- Examples: -->
|
||||
<!-- Use build_depend for packages you need at compile time: -->
|
||||
<!-- <build_depend>message_generation</build_depend> -->
|
||||
<!-- Use buildtool_depend for build tool packages: -->
|
||||
<!-- <buildtool_depend>catkin</buildtool_depend> -->
|
||||
<!-- Use run_depend for packages you need at runtime: -->
|
||||
<!-- <run_depend>message_runtime</run_depend> -->
|
||||
<!-- Use test_depend for packages you need only for testing: -->
|
||||
<!-- <test_depend>gtest</test_depend> -->
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<build_depend>roscpp</build_depend>
|
||||
<build_depend>sensor_msgs</build_depend>
|
||||
<!-- build_depend>orocos_kdl</build_depend -->
|
||||
<run_depend>roscpp</run_depend>
|
||||
<run_depend>sensor_msgs</run_depend>
|
||||
<!-- run_depend>orocos_kdl</run_depend -->
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
<export>
|
||||
<!-- Other tools can request additional information be placed here -->
|
||||
|
||||
</export>
|
||||
</package>
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
#include "ros/ros.h"
|
||||
#include "sensor_msgs/Imu.h"
|
||||
#include <iostream>
|
||||
#include <tf/transform_datatypes.h>
|
||||
|
||||
ros::Publisher angular_vel_deg_publisher;
|
||||
ros::Publisher rpy_deg_publisher;
|
||||
ros::Subscriber imudata_subscriber;
|
||||
|
||||
const float r2d = 57.29577951f;
|
||||
|
||||
void MsgCallback(const sensor_msgs::Imu::ConstPtr& msg)
|
||||
{
|
||||
|
||||
geometry_msgs::Vector3 angular_vel;
|
||||
angular_vel.x = msg->angular_velocity.x*r2d;
|
||||
angular_vel.y = msg->angular_velocity.y*r2d;
|
||||
angular_vel.z = msg->angular_velocity.z*r2d;
|
||||
|
||||
angular_vel_deg_publisher.publish(angular_vel);
|
||||
|
||||
|
||||
tf::Quaternion q(msg->orientation.x, msg->orientation.y, msg->orientation.z, msg->orientation.w);
|
||||
tf::Matrix3x3 m(q);
|
||||
double roll, pitch, yaw;
|
||||
m.getRPY(roll, pitch, yaw);
|
||||
|
||||
geometry_msgs::Vector3 rpy;
|
||||
rpy.x = roll*r2d;
|
||||
rpy.y = pitch*r2d;
|
||||
rpy.z = yaw*r2d;
|
||||
|
||||
rpy_deg_publisher.publish(rpy);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "imu_listener");
|
||||
ros::NodeHandle n;
|
||||
angular_vel_deg_publisher = n.advertise<geometry_msgs::Vector3>("angular_vel_deg", 1000);
|
||||
rpy_deg_publisher = n.advertise<geometry_msgs::Vector3>("rpy_deg", 1000);
|
||||
imudata_subscriber = n.subscribe("/imu/data", 1000, MsgCallback);
|
||||
|
||||
ROS_INFO("waiting for imu data");
|
||||
ros::spin();
|
||||
return 0;
|
||||
}
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ros/ros.h"
|
||||
#include "sensor_msgs/Imu.h"
|
||||
#include "sensor_msgs/MagneticField.h"
|
||||
#include "std_srvs/SetBool.h"
|
||||
#include "std_srvs/Trigger.h"
|
||||
#include "std_msgs/Bool.h"
|
||||
|
||||
#include "lpsensor/LpmsIG1I.h"
|
||||
#include "lpsensor/SensorDataI.h"
|
||||
#include "lpsensor/LpmsIG1Registers.h"
|
||||
|
||||
//! Manages connection with the sensor, publishes data
|
||||
/*!
|
||||
\TODO: Make noncopyable!
|
||||
*/
|
||||
|
||||
struct IG1Command
|
||||
{
|
||||
short command;
|
||||
union Data {
|
||||
uint32_t i[64];
|
||||
float f[64];
|
||||
unsigned char c[256];
|
||||
} data;
|
||||
int dataLength;
|
||||
};
|
||||
|
||||
class LpBE1Proxy
|
||||
{
|
||||
public:
|
||||
// Node handler
|
||||
ros::NodeHandle nh, private_nh;
|
||||
ros::Timer updateTimer;
|
||||
|
||||
// Publisher
|
||||
ros::Publisher imu_pub;
|
||||
ros::Publisher autocalibration_status_pub;
|
||||
|
||||
// Service
|
||||
ros::ServiceServer autocalibration_serv;
|
||||
ros::ServiceServer autoReconnect_serv;
|
||||
ros::ServiceServer gyrocalibration_serv;
|
||||
ros::ServiceServer resetHeading_serv;
|
||||
ros::ServiceServer getImuData_serv;
|
||||
ros::ServiceServer setStreamingMode_serv;
|
||||
ros::ServiceServer setCommandMode_serv;
|
||||
|
||||
sensor_msgs::Imu imu_msg;
|
||||
|
||||
// Parameters
|
||||
std::string comportNo;
|
||||
int baudrate;
|
||||
bool autoReconnect;
|
||||
std::string frame_id;
|
||||
int rate;
|
||||
|
||||
LpBE1Proxy(ros::NodeHandle h) :
|
||||
nh(h),
|
||||
private_nh("~")
|
||||
{
|
||||
// Get node parameters
|
||||
private_nh.param<std::string>("port", comportNo, "/dev/ttyUSB0");
|
||||
private_nh.param("baudrate", baudrate, 115200);
|
||||
private_nh.param("autoreconnect", autoReconnect, true);
|
||||
private_nh.param<std::string>("frame_id", frame_id, "imu");
|
||||
private_nh.param("rate", rate, 200);
|
||||
|
||||
// Create LpmsBE1 object
|
||||
sensor1 = IG1Factory();
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
sensor1->setAutoReconnectStatus(autoReconnect);
|
||||
|
||||
imu_pub = nh.advertise<sensor_msgs::Imu>("data",1);
|
||||
autocalibration_status_pub = nh.advertise<std_msgs::Bool>("is_autocalibration_active", 1, true);
|
||||
|
||||
autocalibration_serv = nh.advertiseService("enable_gyro_autocalibration", &LpBE1Proxy::setAutocalibration, this);
|
||||
autoReconnect_serv = nh.advertiseService("enable_auto_reconnect", &LpBE1Proxy::setAutoReconnect, this);
|
||||
gyrocalibration_serv = nh.advertiseService("calibrate_gyroscope", &LpBE1Proxy::calibrateGyroscope, this);
|
||||
resetHeading_serv = nh.advertiseService("reset_heading", &LpBE1Proxy::resetHeading, this);
|
||||
getImuData_serv = nh.advertiseService("get_imu_data", &LpBE1Proxy::getImuData, this);
|
||||
setStreamingMode_serv = nh.advertiseService("set_streaming_mode", &LpBE1Proxy::setStreamingMode, this);
|
||||
setCommandMode_serv = nh.advertiseService("set_command_mode", &LpBE1Proxy::setCommandMode, this);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
//logd(TAG, "Error connecting to sensor\n");
|
||||
ROS_ERROR("Error connecting to sensor\n");
|
||||
sensor1->release();
|
||||
ros::Duration(3).sleep(); // sleep 3 s
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ROS_INFO("Waiting for sensor to connect %d", sensor1->getStatus());
|
||||
ros::Duration(1).sleep();
|
||||
} while(
|
||||
ros::ok() &&
|
||||
(
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() == STATUS_CONNECTED)
|
||||
{
|
||||
ROS_INFO("Sensor connected");
|
||||
ros::Duration(1).sleep();
|
||||
sensor1->commandGotoStreamingMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_INFO("Sensor connection error: %d.", sensor1->getStatus());
|
||||
ros::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
~LpBE1Proxy(void)
|
||||
{
|
||||
sensor1->release();
|
||||
}
|
||||
|
||||
void update(const ros::TimerEvent& te)
|
||||
{
|
||||
static bool runOnce = false;
|
||||
|
||||
if (sensor1->getStatus() == STATUS_CONNECTED &&
|
||||
sensor1->hasImuData())
|
||||
{
|
||||
if (!runOnce)
|
||||
{
|
||||
publishIsAutocalibrationActive();
|
||||
runOnce = true;
|
||||
}
|
||||
IG1ImuDataI sd;
|
||||
sensor1->getImuData(sd);
|
||||
|
||||
/* Fill the IMU message */
|
||||
|
||||
// Fill the header
|
||||
imu_msg.header.stamp = ros::Time::now();
|
||||
imu_msg.header.frame_id = frame_id;
|
||||
|
||||
// Fill orientation quaternion
|
||||
imu_msg.orientation.w = sd.quaternion.data[0];
|
||||
imu_msg.orientation.x = -sd.quaternion.data[1];
|
||||
imu_msg.orientation.y = -sd.quaternion.data[2];
|
||||
imu_msg.orientation.z = -sd.quaternion.data[3];
|
||||
|
||||
// Fill angular velocity data
|
||||
// - scale from deg/s to rad/s
|
||||
imu_msg.angular_velocity.x = sd.gyroIIAlignmentCalibrated.data[0]*3.1415926/180;
|
||||
imu_msg.angular_velocity.y = sd.gyroIIAlignmentCalibrated.data[1]*3.1415926/180;
|
||||
imu_msg.angular_velocity.z = sd.gyroIIAlignmentCalibrated.data[2]*3.1415926/180;
|
||||
|
||||
// Fill linear acceleration data
|
||||
imu_msg.linear_acceleration.x = -sd.accCalibrated.data[0]*9.81;
|
||||
imu_msg.linear_acceleration.y = -sd.accCalibrated.data[1]*9.81;
|
||||
imu_msg.linear_acceleration.z = -sd.accCalibrated.data[2]*9.81;
|
||||
|
||||
|
||||
// Publish the messages
|
||||
imu_pub.publish(imu_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void run(void)
|
||||
{
|
||||
// The timer ensures periodic data publishing
|
||||
updateTimer = ros::Timer(nh.createTimer(ros::Duration(1.0f/rate),
|
||||
&LpBE1Proxy::update,
|
||||
this));
|
||||
}
|
||||
|
||||
void publishIsAutocalibrationActive()
|
||||
{
|
||||
std_msgs::Bool msg;
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
msg.data = settings.enableGyroAutocalibration;
|
||||
autocalibration_status_pub.publish(msg);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Service Callbacks
|
||||
///////////////////////////////////////////////////
|
||||
bool setAutocalibration (std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
|
||||
{
|
||||
ROS_INFO("set_autocalibration");
|
||||
|
||||
// clear current settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
|
||||
// Send command
|
||||
cmdSetEnableAutocalibration(req.data);
|
||||
ros::Duration(0.2).sleep();
|
||||
cmdGetEnableAutocalibration();
|
||||
ros::Duration(0.1).sleep();
|
||||
|
||||
double retryElapsedTime = 0;
|
||||
int retryCount = 0;
|
||||
while (!sensor1->hasSettings())
|
||||
{
|
||||
ros::Duration(0.1).sleep();
|
||||
ROS_INFO("set_autocalibration wait");
|
||||
|
||||
retryElapsedTime += 0.1;
|
||||
if (retryElapsedTime > 2.0)
|
||||
{
|
||||
retryElapsedTime = 0;
|
||||
cmdGetEnableAutocalibration();
|
||||
retryCount++;
|
||||
}
|
||||
|
||||
if (retryCount > 5)
|
||||
break;
|
||||
}
|
||||
ROS_INFO("set_autocalibration done");
|
||||
|
||||
// Get settings
|
||||
sensor1->getSettings(settings);
|
||||
|
||||
std::string msg;
|
||||
if (settings.enableGyroAutocalibration == req.data)
|
||||
{
|
||||
res.success = true;
|
||||
msg.append(std::string("[Success] autocalibration status set to: ") + (settings.enableGyroAutocalibration?"True":"False"));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.success = false;
|
||||
msg.append(std::string("[Failed] current autocalibration status set to: ") + (settings.enableGyroAutocalibration?"True":"False"));
|
||||
}
|
||||
|
||||
ROS_INFO("%s", msg.c_str());
|
||||
res.message = msg;
|
||||
|
||||
publishIsAutocalibrationActive();
|
||||
return res.success;
|
||||
}
|
||||
|
||||
// Auto reconnect
|
||||
bool setAutoReconnect (std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
|
||||
{
|
||||
ROS_INFO("set_auto_reconnect");
|
||||
|
||||
sensor1->setAutoReconnectStatus(req.data);
|
||||
|
||||
res.success = true;
|
||||
std::string msg;
|
||||
msg.append(std::string("[Success] auto reconnection status set to: ") + (sensor1->getAutoReconnectStatus()?"True":"False"));
|
||||
|
||||
ROS_INFO("%s", msg.c_str());
|
||||
res.message = msg;
|
||||
|
||||
return res.success;
|
||||
}
|
||||
|
||||
// reset heading
|
||||
bool resetHeading (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
ROS_INFO("reset_heading");
|
||||
|
||||
// Send command
|
||||
cmdResetHeading();
|
||||
|
||||
res.success = true;
|
||||
res.message = "[Success] Heading reset";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool calibrateGyroscope (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
ROS_INFO("calibrate_gyroscope: Please make sure the sensor is stationary for 4 seconds");
|
||||
|
||||
cmdCalibrateGyroscope();
|
||||
|
||||
ros::Duration(4).sleep();
|
||||
res.success = true;
|
||||
res.message = "[Success] Gyroscope calibration procedure completed";
|
||||
ROS_INFO("calibrate_gyroscope: Gyroscope calibration procedure completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getImuData (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoCommandMode();
|
||||
ros::Duration(0.1).sleep();
|
||||
cmdGetImuData();
|
||||
res.success = true;
|
||||
res.message = "[Success] Get imu data";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setStreamingMode (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoStreamingMode();
|
||||
res.success = true;
|
||||
res.message = "[Success] Set streaming mode";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setCommandMode (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoCommandMode();
|
||||
res.success = true;
|
||||
res.message = "[Success] Set command mode";
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Helpers
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
void cmdGotoCommandMode ()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GOTO_COMMAND_MODE;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGotoStreamingMode ()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GOTO_STREAM_MODE;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGetImuData()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GET_IMU_DATA;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdCalibrateGyroscope()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = START_GYR_CALIBRATION;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdResetHeading()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = SET_ORIENTATION_OFFSET;
|
||||
cmd.dataLength = 4;
|
||||
cmd.data.i[0] = LPMS_OFFSET_MODE_HEADING;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdSetEnableAutocalibration(int status)
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = SET_ENABLE_GYR_AUTOCALIBRATION;
|
||||
cmd.dataLength = 4;
|
||||
cmd.data.i[0] = status;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGetEnableAutocalibration()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GET_ENABLE_GYR_AUTOCALIBRATION;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Access to LPMS data
|
||||
IG1I* sensor1;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
ros::init(argc, argv, "lpms_be1_node");
|
||||
ros::NodeHandle nh("imu");
|
||||
|
||||
ros::AsyncSpinner spinner(0);
|
||||
spinner.start();
|
||||
|
||||
LpBE1Proxy lpBE1(nh);
|
||||
|
||||
lpBE1.run();
|
||||
ros::waitForShutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+410
@@ -0,0 +1,410 @@
|
||||
|
||||
#include <string>
|
||||
#include "ros/ros.h"
|
||||
#include "sensor_msgs/Imu.h"
|
||||
#include "sensor_msgs/MagneticField.h"
|
||||
#include "std_srvs/SetBool.h"
|
||||
#include "std_srvs/Trigger.h"
|
||||
#include "std_msgs/Bool.h"
|
||||
|
||||
#include "lpsensor/LpmsIG1I.h"
|
||||
#include "lpsensor/SensorDataI.h"
|
||||
#include "lpsensor/LpmsIG1Registers.h"
|
||||
|
||||
struct IG1Command
|
||||
{
|
||||
short command;
|
||||
union Data {
|
||||
uint32_t i[64];
|
||||
float f[64];
|
||||
unsigned char c[256];
|
||||
} data;
|
||||
int dataLength;
|
||||
};
|
||||
|
||||
class LpIG1Proxy
|
||||
{
|
||||
public:
|
||||
// Node handler
|
||||
ros::NodeHandle nh, private_nh;
|
||||
ros::Timer updateTimer;
|
||||
|
||||
// Publisher
|
||||
ros::Publisher imu_pub;
|
||||
ros::Publisher mag_pub;
|
||||
ros::Publisher autocalibration_status_pub;
|
||||
|
||||
// Service
|
||||
ros::ServiceServer autocalibration_serv;
|
||||
ros::ServiceServer autoReconnect_serv;
|
||||
ros::ServiceServer gyrocalibration_serv;
|
||||
ros::ServiceServer resetHeading_serv;
|
||||
ros::ServiceServer getImuData_serv;
|
||||
ros::ServiceServer setStreamingMode_serv;
|
||||
ros::ServiceServer setCommandMode_serv;
|
||||
|
||||
sensor_msgs::Imu imu_msg;
|
||||
sensor_msgs::MagneticField mag_msg;
|
||||
|
||||
// Parameters
|
||||
std::string comportNo;
|
||||
int baudrate;
|
||||
bool autoReconnect;
|
||||
std::string frame_id;
|
||||
int rate;
|
||||
|
||||
LpIG1Proxy(ros::NodeHandle h) :
|
||||
nh(h),
|
||||
private_nh("~")
|
||||
{
|
||||
// Get node parameters
|
||||
private_nh.param<std::string>("port", comportNo, "/dev/ttyUSB0");
|
||||
private_nh.param("baudrate", baudrate, 921600);
|
||||
private_nh.param("autoreconnect", autoReconnect, true);
|
||||
private_nh.param<std::string>("frame_id", frame_id, "imu");
|
||||
private_nh.param("rate", rate, 200);
|
||||
|
||||
// Create LpmsIG1 object
|
||||
sensor1 = IG1Factory();
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
sensor1->setAutoReconnectStatus(autoReconnect);
|
||||
|
||||
ROS_INFO("Settings");
|
||||
ROS_INFO("Port: %s", comportNo.c_str());
|
||||
ROS_INFO("Baudrate: %d", baudrate);
|
||||
ROS_INFO("Auto reconnect: %s", autoReconnect? "Enabled":"Disabled");
|
||||
|
||||
imu_pub = nh.advertise<sensor_msgs::Imu>("data",1);
|
||||
mag_pub = nh.advertise<sensor_msgs::MagneticField>("mag",1);
|
||||
autocalibration_status_pub = nh.advertise<std_msgs::Bool>("is_autocalibration_active", 1, true);
|
||||
|
||||
autocalibration_serv = nh.advertiseService("enable_gyro_autocalibration", &LpIG1Proxy::setAutocalibration, this);
|
||||
autoReconnect_serv = nh.advertiseService("enable_auto_reconnect", &LpIG1Proxy::setAutoReconnect, this);
|
||||
gyrocalibration_serv = nh.advertiseService("calibrate_gyroscope", &LpIG1Proxy::calibrateGyroscope, this);
|
||||
resetHeading_serv = nh.advertiseService("reset_heading", &LpIG1Proxy::resetHeading, this);
|
||||
getImuData_serv = nh.advertiseService("get_imu_data", &LpIG1Proxy::getImuData, this);
|
||||
setStreamingMode_serv = nh.advertiseService("set_streaming_mode", &LpIG1Proxy::setStreamingMode, this);
|
||||
setCommandMode_serv = nh.advertiseService("set_command_mode", &LpIG1Proxy::setCommandMode, this);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
ROS_ERROR("Error connecting to sensor\n");
|
||||
sensor1->release();
|
||||
ros::Duration(3).sleep(); // sleep 3 s
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ROS_INFO("Waiting for sensor to connect %d", sensor1->getStatus());
|
||||
ros::Duration(1).sleep();
|
||||
} while(
|
||||
ros::ok() &&
|
||||
(
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() == STATUS_CONNECTED)
|
||||
{
|
||||
ROS_INFO("Sensor connected");
|
||||
ros::Duration(1).sleep();
|
||||
sensor1->commandGotoStreamingMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_INFO("Sensor connection error: %d.", sensor1->getStatus());
|
||||
ros::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
~LpIG1Proxy(void)
|
||||
{
|
||||
sensor1->release();
|
||||
}
|
||||
|
||||
void update(const ros::TimerEvent& te)
|
||||
{
|
||||
static bool runOnce = false;
|
||||
|
||||
if (sensor1->getStatus() == STATUS_CONNECTED &&
|
||||
sensor1->hasImuData())
|
||||
{
|
||||
if (!runOnce)
|
||||
{
|
||||
publishIsAutocalibrationActive();
|
||||
runOnce = true;
|
||||
}
|
||||
IG1ImuDataI sd;
|
||||
sensor1->getImuData(sd);
|
||||
|
||||
/* Fill the IMU message */
|
||||
|
||||
// Fill the header
|
||||
imu_msg.header.stamp = ros::Time::now();
|
||||
imu_msg.header.frame_id = frame_id;
|
||||
|
||||
// Fill orientation quaternion
|
||||
imu_msg.orientation.w = sd.quaternion.data[0];
|
||||
imu_msg.orientation.x = -sd.quaternion.data[1];
|
||||
imu_msg.orientation.y = -sd.quaternion.data[2];
|
||||
imu_msg.orientation.z = -sd.quaternion.data[3];
|
||||
|
||||
// Fill angular velocity data
|
||||
// - scale from deg/s to rad/s
|
||||
imu_msg.angular_velocity.x = sd.gyroIAlignmentCalibrated.data[0]*3.1415926/180;
|
||||
imu_msg.angular_velocity.y = sd.gyroIAlignmentCalibrated.data[1]*3.1415926/180;
|
||||
imu_msg.angular_velocity.z = sd.gyroIAlignmentCalibrated.data[2]*3.1415926/180;
|
||||
|
||||
// Fill linear acceleration data
|
||||
imu_msg.linear_acceleration.x = -sd.accCalibrated.data[0]*9.81;
|
||||
imu_msg.linear_acceleration.y = -sd.accCalibrated.data[1]*9.81;
|
||||
imu_msg.linear_acceleration.z = -sd.accCalibrated.data[2]*9.81;
|
||||
|
||||
/* Fill the magnetometer message */
|
||||
mag_msg.header.stamp = imu_msg.header.stamp;
|
||||
mag_msg.header.frame_id = frame_id;
|
||||
|
||||
// Units are microTesla in the LPMS library, Tesla in ROS.
|
||||
mag_msg.magnetic_field.x = sd.magRaw.data[0]*1e-6;
|
||||
mag_msg.magnetic_field.y = sd.magRaw.data[1]*1e-6;
|
||||
mag_msg.magnetic_field.z = sd.magRaw.data[2]*1e-6;
|
||||
|
||||
// Publish the messages
|
||||
imu_pub.publish(imu_msg);
|
||||
mag_pub.publish(mag_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void run(void)
|
||||
{
|
||||
// The timer ensures periodic data publishing
|
||||
updateTimer = ros::Timer(nh.createTimer(ros::Duration(1.0f/rate),
|
||||
&LpIG1Proxy::update,
|
||||
this));
|
||||
}
|
||||
|
||||
void publishIsAutocalibrationActive()
|
||||
{
|
||||
std_msgs::Bool msg;
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
msg.data = settings.enableGyroAutocalibration;
|
||||
autocalibration_status_pub.publish(msg);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Service Callbacks
|
||||
///////////////////////////////////////////////////
|
||||
bool setAutocalibration (std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
|
||||
{
|
||||
ROS_INFO("set_autocalibration");
|
||||
|
||||
// clear current settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
|
||||
// Send command
|
||||
cmdSetEnableAutocalibration(req.data);
|
||||
ros::Duration(0.2).sleep();
|
||||
cmdGetEnableAutocalibration();
|
||||
ros::Duration(0.1).sleep();
|
||||
|
||||
double retryElapsedTime = 0;
|
||||
int retryCount = 0;
|
||||
while (!sensor1->hasSettings())
|
||||
{
|
||||
ros::Duration(0.1).sleep();
|
||||
ROS_INFO("set_autocalibration wait");
|
||||
|
||||
retryElapsedTime += 0.1;
|
||||
if (retryElapsedTime > 2.0)
|
||||
{
|
||||
retryElapsedTime = 0;
|
||||
cmdGetEnableAutocalibration();
|
||||
retryCount++;
|
||||
}
|
||||
|
||||
if (retryCount > 5)
|
||||
break;
|
||||
}
|
||||
ROS_INFO("set_autocalibration done");
|
||||
|
||||
// Get settings
|
||||
sensor1->getSettings(settings);
|
||||
|
||||
std::string msg;
|
||||
if (settings.enableGyroAutocalibration == req.data)
|
||||
{
|
||||
res.success = true;
|
||||
msg.append(std::string("[Success] autocalibration status set to: ") + (settings.enableGyroAutocalibration?"True":"False"));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.success = false;
|
||||
msg.append(std::string("[Failed] current autocalibration status set to: ") + (settings.enableGyroAutocalibration?"True":"False"));
|
||||
}
|
||||
|
||||
ROS_INFO("%s", msg.c_str());
|
||||
res.message = msg;
|
||||
|
||||
publishIsAutocalibrationActive();
|
||||
return res.success;
|
||||
}
|
||||
|
||||
// Auto reconnect
|
||||
bool setAutoReconnect (std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
|
||||
{
|
||||
ROS_INFO("set_auto_reconnect");
|
||||
|
||||
sensor1->setAutoReconnectStatus(req.data);
|
||||
|
||||
res.success = true;
|
||||
std::string msg;
|
||||
msg.append(std::string("[Success] auto reconnection status set to: ") + (sensor1->getAutoReconnectStatus()?"True":"False"));
|
||||
|
||||
ROS_INFO("%s", msg.c_str());
|
||||
res.message = msg;
|
||||
|
||||
return res.success;
|
||||
}
|
||||
|
||||
// reset heading
|
||||
bool resetHeading (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
ROS_INFO("reset_heading");
|
||||
|
||||
// Send command
|
||||
cmdResetHeading();
|
||||
|
||||
res.success = true;
|
||||
res.message = "[Success] Heading reset";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool calibrateGyroscope (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
ROS_INFO("calibrate_gyroscope: Please make sure the sensor is stationary for 4 seconds");
|
||||
|
||||
cmdCalibrateGyroscope();
|
||||
|
||||
ros::Duration(4).sleep();
|
||||
res.success = true;
|
||||
res.message = "[Success] Gyroscope calibration procedure completed";
|
||||
ROS_INFO("calibrate_gyroscope: Gyroscope calibration procedure completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getImuData (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoCommandMode();
|
||||
ros::Duration(0.1).sleep();
|
||||
cmdGetImuData();
|
||||
res.success = true;
|
||||
res.message = "[Success] Get imu data";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setStreamingMode (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoStreamingMode();
|
||||
res.success = true;
|
||||
res.message = "[Success] Set streaming mode";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setCommandMode (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoCommandMode();
|
||||
res.success = true;
|
||||
res.message = "[Success] Set command mode";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Helpers
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
void cmdGotoCommandMode ()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GOTO_COMMAND_MODE;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGotoStreamingMode ()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GOTO_STREAM_MODE;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGetImuData()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GET_IMU_DATA;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdCalibrateGyroscope()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = START_GYR_CALIBRATION;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdResetHeading()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = SET_ORIENTATION_OFFSET;
|
||||
cmd.dataLength = 4;
|
||||
cmd.data.i[0] = LPMS_OFFSET_MODE_HEADING;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdSetEnableAutocalibration(int status)
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = SET_ENABLE_GYR_AUTOCALIBRATION;
|
||||
cmd.dataLength = 4;
|
||||
cmd.data.i[0] = status;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGetEnableAutocalibration()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GET_ENABLE_GYR_AUTOCALIBRATION;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Access to LPMS data
|
||||
IG1I* sensor1;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
ros::init(argc, argv, "lpms_ig1_node");
|
||||
ros::NodeHandle nh("imu");
|
||||
|
||||
ros::AsyncSpinner spinner(0);
|
||||
spinner.start();
|
||||
|
||||
LpIG1Proxy lpIG1(nh);
|
||||
|
||||
lpIG1.run();
|
||||
ros::waitForShutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
#include "ros/ros.h"
|
||||
#include <std_srvs/Trigger.h>
|
||||
#include <cstdlib>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "lpms_ig1_rs485_client");
|
||||
|
||||
ros::NodeHandle n;
|
||||
ros::ServiceClient client = n.serviceClient<std_srvs::TriggerRequest, std_srvs::TriggerResponse>("/imu/get_imu_data");
|
||||
|
||||
ros::Rate loop_rate(50);
|
||||
std_srvs::TriggerRequest req;
|
||||
std_srvs::TriggerResponse res;
|
||||
|
||||
int count = 0;
|
||||
while (ros::ok())
|
||||
{
|
||||
|
||||
if (client.call(req, res))
|
||||
{
|
||||
ROS_INFO("get_imu_data: %d", count++);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("Failed to call service get_imu_data");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ros::spinOnce();
|
||||
|
||||
loop_rate.sleep();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+369
@@ -0,0 +1,369 @@
|
||||
|
||||
#include <string>
|
||||
#include "ros/ros.h"
|
||||
#include "sensor_msgs/Imu.h"
|
||||
#include "sensor_msgs/MagneticField.h"
|
||||
#include "std_srvs/SetBool.h"
|
||||
#include "std_srvs/Trigger.h"
|
||||
#include "std_msgs/Bool.h"
|
||||
|
||||
#include "lpsensor/LpmsIG1I.h"
|
||||
#include "lpsensor/SensorDataI.h"
|
||||
#include "lpsensor/LpmsIG1Registers.h"
|
||||
|
||||
struct IG1Command
|
||||
{
|
||||
short command;
|
||||
union Data {
|
||||
uint32_t i[64];
|
||||
float f[64];
|
||||
unsigned char c[256];
|
||||
} data;
|
||||
int dataLength;
|
||||
};
|
||||
|
||||
class LpIG1Proxy
|
||||
{
|
||||
public:
|
||||
// Node handler
|
||||
ros::NodeHandle nh, private_nh;
|
||||
ros::Timer updateTimer;
|
||||
|
||||
// Publisher
|
||||
ros::Publisher imu_pub;
|
||||
ros::Publisher mag_pub;
|
||||
ros::Publisher autocalibration_status_pub;
|
||||
|
||||
// Service
|
||||
ros::ServiceServer autocalibration_serv;
|
||||
ros::ServiceServer autoReconnect_serv;
|
||||
ros::ServiceServer gyrocalibration_serv;
|
||||
ros::ServiceServer resetHeading_serv;
|
||||
ros::ServiceServer getImuData_serv;
|
||||
ros::ServiceServer setStreamingMode_serv;
|
||||
ros::ServiceServer setCommandMode_serv;
|
||||
|
||||
sensor_msgs::Imu imu_msg;
|
||||
sensor_msgs::MagneticField mag_msg;
|
||||
|
||||
// Parameters
|
||||
std::string comportNo;
|
||||
int baudrate;
|
||||
int startupMode;
|
||||
bool autoReconnect;
|
||||
std::string frame_id;
|
||||
int rs485ControlPin;
|
||||
int rs485ControlPinToggleWaitMs;
|
||||
int rate;
|
||||
|
||||
LpIG1Proxy(ros::NodeHandle h) :
|
||||
nh(h),
|
||||
private_nh("~")
|
||||
{
|
||||
// Get node parameters
|
||||
private_nh.param<std::string>("port", comportNo, "/dev/ttyUSB0");
|
||||
private_nh.param("baudrate", baudrate, 115200);
|
||||
private_nh.param("startupmode", startupMode, SENSOR_MODE_STREAMING);
|
||||
private_nh.param("autoreconnect", autoReconnect, true);
|
||||
private_nh.param("rs485ControlPin", rs485ControlPin, -1);
|
||||
private_nh.param("rs485ControlPinToggleWaitMs", rs485ControlPinToggleWaitMs, 2);
|
||||
private_nh.param<std::string>("frame_id", frame_id, "imu");
|
||||
private_nh.param("rate", rate, 200);
|
||||
|
||||
// Create LpmsIG1 object
|
||||
sensor1 = IG1Factory();
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
sensor1->setAutoReconnectStatus(autoReconnect);
|
||||
sensor1->setStartupSensorMode(startupMode);
|
||||
sensor1->setConnectionInterface(CONNECTION_INTERFACE_RS485);
|
||||
sensor1->setControlGPIOForRs485(rs485ControlPin);
|
||||
sensor1->setControlGPIOToggleWaitMs(rs485ControlPinToggleWaitMs);
|
||||
|
||||
ROS_INFO("Settings");
|
||||
ROS_INFO("Port: %s", comportNo.c_str());
|
||||
ROS_INFO("Baudrate: %d", baudrate);
|
||||
ROS_INFO("Startup mode: %s", (startupMode == 0)? "Command mode":"Streaming mode");
|
||||
ROS_INFO("Auto reconnect: %s", autoReconnect? "Enabled":"Disabled");
|
||||
ROS_INFO("rs485ControlPin: %d", rs485ControlPin);
|
||||
ROS_INFO("rs485ControlPinToggleWaitMs: %d", rs485ControlPinToggleWaitMs);
|
||||
|
||||
imu_pub = nh.advertise<sensor_msgs::Imu>("data",1);
|
||||
mag_pub = nh.advertise<sensor_msgs::MagneticField>("mag",1);
|
||||
autocalibration_status_pub = nh.advertise<std_msgs::Bool>("is_autocalibration_active", 1, true);
|
||||
|
||||
autocalibration_serv = nh.advertiseService("enable_gyro_autocalibration", &LpIG1Proxy::setAutocalibration, this);
|
||||
autoReconnect_serv = nh.advertiseService("enable_auto_reconnect", &LpIG1Proxy::setAutoReconnect, this);
|
||||
gyrocalibration_serv = nh.advertiseService("calibrate_gyroscope", &LpIG1Proxy::calibrateGyroscope, this);
|
||||
resetHeading_serv = nh.advertiseService("reset_heading", &LpIG1Proxy::resetHeading, this);
|
||||
getImuData_serv = nh.advertiseService("get_imu_data", &LpIG1Proxy::getImuData, this);
|
||||
setStreamingMode_serv = nh.advertiseService("set_streaming_mode", &LpIG1Proxy::setStreamingMode, this);
|
||||
setCommandMode_serv = nh.advertiseService("set_command_mode", &LpIG1Proxy::setCommandMode, this);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
ROS_ERROR("Error connecting to sensor\n");
|
||||
sensor1->release();
|
||||
ros::Duration(3).sleep(); // sleep 3 s
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ROS_INFO("Waiting for sensor to connect. Sensor status: %d", sensor1->getStatus());
|
||||
ros::Duration(1).sleep();
|
||||
} while(
|
||||
ros::ok() &&
|
||||
(
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() == STATUS_CONNECTED)
|
||||
{
|
||||
ROS_INFO("Sensor connected");
|
||||
ros::Duration(1).sleep();
|
||||
//sensor1->commandGotoStreamingMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_INFO("Sensor connection error: %d.", sensor1->getStatus());
|
||||
ros::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
~LpIG1Proxy(void)
|
||||
{
|
||||
sensor1->release();
|
||||
}
|
||||
|
||||
void update(const ros::TimerEvent& te)
|
||||
{
|
||||
static bool runOnce = false;
|
||||
|
||||
if (sensor1->getStatus() == STATUS_CONNECTED &&
|
||||
sensor1->hasImuData())
|
||||
{
|
||||
if (!runOnce)
|
||||
{
|
||||
publishIsAutocalibrationActive();
|
||||
runOnce = true;
|
||||
}
|
||||
IG1ImuDataI sd;
|
||||
sensor1->getImuData(sd);
|
||||
|
||||
/* Fill the IMU message */
|
||||
|
||||
// Fill the header
|
||||
imu_msg.header.stamp = ros::Time::now();
|
||||
imu_msg.header.frame_id = frame_id;
|
||||
|
||||
// Fill orientation quaternion
|
||||
imu_msg.orientation.w = sd.quaternion.data[0];
|
||||
imu_msg.orientation.x = -sd.quaternion.data[1];
|
||||
imu_msg.orientation.y = -sd.quaternion.data[2];
|
||||
imu_msg.orientation.z = -sd.quaternion.data[3];
|
||||
|
||||
// Fill angular velocity data
|
||||
// - scale from deg/s to rad/s
|
||||
imu_msg.angular_velocity.x = sd.gyroIAlignmentCalibrated.data[0]*3.1415926/180;
|
||||
imu_msg.angular_velocity.y = sd.gyroIAlignmentCalibrated.data[1]*3.1415926/180;
|
||||
imu_msg.angular_velocity.z = sd.gyroIAlignmentCalibrated.data[2]*3.1415926/180;
|
||||
|
||||
// Fill linear acceleration data
|
||||
imu_msg.linear_acceleration.x = -sd.accCalibrated.data[0]*9.81;
|
||||
imu_msg.linear_acceleration.y = -sd.accCalibrated.data[1]*9.81;
|
||||
imu_msg.linear_acceleration.z = -sd.accCalibrated.data[2]*9.81;
|
||||
|
||||
/* Fill the magnetometer message */
|
||||
mag_msg.header.stamp = imu_msg.header.stamp;
|
||||
mag_msg.header.frame_id = frame_id;
|
||||
|
||||
// Units are microTesla in the LPMS library, Tesla in ROS.
|
||||
mag_msg.magnetic_field.x = sd.magRaw.data[0]*1e-6;
|
||||
mag_msg.magnetic_field.y = sd.magRaw.data[1]*1e-6;
|
||||
mag_msg.magnetic_field.z = sd.magRaw.data[2]*1e-6;
|
||||
|
||||
// Publish the messages
|
||||
imu_pub.publish(imu_msg);
|
||||
mag_pub.publish(mag_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void run(void)
|
||||
{
|
||||
// The timer ensures periodic data publishing
|
||||
updateTimer = ros::Timer(nh.createTimer(ros::Duration(1.0f/rate),
|
||||
&LpIG1Proxy::update,
|
||||
this));
|
||||
}
|
||||
|
||||
void publishIsAutocalibrationActive()
|
||||
{
|
||||
std_msgs::Bool msg;
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
msg.data = settings.enableGyroAutocalibration;
|
||||
autocalibration_status_pub.publish(msg);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Service Callbacks
|
||||
///////////////////////////////////////////////////
|
||||
bool setAutocalibration (std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
|
||||
{
|
||||
ROS_INFO("set_autocalibration");
|
||||
|
||||
// clear current settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
|
||||
sensor1->commandSetGyroAutoCalibration(req.data);
|
||||
ros::Duration(0.2).sleep();
|
||||
|
||||
double retryElapsedTime = 0;
|
||||
int retryCount = 0;
|
||||
while (!sensor1->hasSettings())
|
||||
{
|
||||
ros::Duration(0.1).sleep();
|
||||
ROS_INFO("set_autocalibration wait");
|
||||
|
||||
retryElapsedTime += 0.1;
|
||||
if (retryElapsedTime > 2.0)
|
||||
{
|
||||
retryElapsedTime = 0;
|
||||
sensor1->commandGetGyroAutoCalibration();
|
||||
retryCount++;
|
||||
}
|
||||
|
||||
if (retryCount > 5)
|
||||
break;
|
||||
}
|
||||
ROS_INFO("set_autocalibration done");
|
||||
|
||||
// Get settings
|
||||
sensor1->getSettings(settings);
|
||||
|
||||
std::string msg;
|
||||
if (settings.enableGyroAutocalibration == req.data)
|
||||
{
|
||||
res.success = true;
|
||||
msg.append(std::string("[Success] autocalibration status set to: ") + (settings.enableGyroAutocalibration?"True":"False"));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.success = false;
|
||||
msg.append(std::string("[Failed] current autocalibration status set to: ") + (settings.enableGyroAutocalibration?"True":"False"));
|
||||
}
|
||||
|
||||
ROS_INFO("%s", msg.c_str());
|
||||
res.message = msg;
|
||||
|
||||
publishIsAutocalibrationActive();
|
||||
return res.success;
|
||||
}
|
||||
|
||||
// Auto reconnect
|
||||
bool setAutoReconnect (std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
|
||||
{
|
||||
ROS_INFO("set_auto_reconnect");
|
||||
|
||||
sensor1->setAutoReconnectStatus(req.data);
|
||||
|
||||
res.success = true;
|
||||
std::string msg;
|
||||
msg.append(std::string("[Success] auto reconnection status set to: ") + (sensor1->getAutoReconnectStatus()?"True":"False"));
|
||||
|
||||
ROS_INFO("%s", msg.c_str());
|
||||
res.message = msg;
|
||||
|
||||
return res.success;
|
||||
}
|
||||
|
||||
// reset heading
|
||||
bool resetHeading (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
ROS_INFO("reset_heading");
|
||||
|
||||
sensor1->commandSetOffsetMode(LPMS_OFFSET_MODE_HEADING);
|
||||
|
||||
res.success = true;
|
||||
res.message = "[Success] Heading resets";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool calibrateGyroscope (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
ROS_INFO("calibrate_gyroscope: Please make sure the sensor is stationary for 4 seconds");
|
||||
|
||||
sensor1->commandStartGyroCalibration();
|
||||
ros::Duration(4).sleep();
|
||||
res.success = true;
|
||||
res.message = "[Success] Gyroscope calibration procedure completed";
|
||||
ROS_INFO("calibrate_gyroscope: Gyroscope calibration procedure completed");
|
||||
|
||||
//sensor1->commandGotoStreamingMode();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getImuData (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGetImuData();
|
||||
res.success = true;
|
||||
res.message = "[Success] Get imu data";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setStreamingMode (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
sensor1->commandGotoStreamingMode();
|
||||
res.success = true;
|
||||
res.message = "[Success] Set streaming mode";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setCommandMode (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
sensor1->commandGotoCommandMode();
|
||||
res.success = true;
|
||||
res.message = "[Success] Set command mode";
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Helpers
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
void cmdGetImuData()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GET_IMU_DATA;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Access to LPMS data
|
||||
IG1I* sensor1;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
ros::init(argc, argv, "lpms_ig1_node_rs485");
|
||||
ros::NodeHandle nh("imu");
|
||||
|
||||
ros::AsyncSpinner spinner(0);
|
||||
spinner.start();
|
||||
|
||||
LpIG1Proxy lpIG1(nh);
|
||||
|
||||
lpIG1.run();
|
||||
ros::waitForShutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ros/ros.h"
|
||||
#include "sensor_msgs/Imu.h"
|
||||
#include "sensor_msgs/MagneticField.h"
|
||||
#include "std_srvs/SetBool.h"
|
||||
#include "std_srvs/Trigger.h"
|
||||
#include "std_msgs/Bool.h"
|
||||
|
||||
#include "lpsensor/LpmsIG1I.h"
|
||||
#include "lpsensor/SensorDataI.h"
|
||||
#include "lpsensor/LpmsIG1Registers.h"
|
||||
|
||||
//! Manages connection with the sensor, publishes data
|
||||
/*!
|
||||
\TODO: Make noncopyable!
|
||||
*/
|
||||
|
||||
struct IG1Command
|
||||
{
|
||||
short command;
|
||||
union Data {
|
||||
uint32_t i[64];
|
||||
float f[64];
|
||||
unsigned char c[256];
|
||||
} data;
|
||||
int dataLength;
|
||||
};
|
||||
|
||||
class LpNAV3Proxy
|
||||
{
|
||||
public:
|
||||
// Node handler
|
||||
ros::NodeHandle nh, private_nh;
|
||||
ros::Timer updateTimer;
|
||||
|
||||
// Publisher
|
||||
ros::Publisher imu_pub;
|
||||
ros::Publisher autocalibration_status_pub;
|
||||
|
||||
// Service
|
||||
ros::ServiceServer autocalibration_serv;
|
||||
ros::ServiceServer autoReconnect_serv;
|
||||
ros::ServiceServer gyrocalibration_serv;
|
||||
ros::ServiceServer resetHeading_serv;
|
||||
ros::ServiceServer getImuData_serv;
|
||||
ros::ServiceServer setStreamingMode_serv;
|
||||
ros::ServiceServer setCommandMode_serv;
|
||||
|
||||
sensor_msgs::Imu imu_msg;
|
||||
|
||||
// Parameters
|
||||
std::string comportNo;
|
||||
int baudrate;
|
||||
bool autoReconnect;
|
||||
std::string frame_id;
|
||||
int rate;
|
||||
|
||||
LpNAV3Proxy(ros::NodeHandle h) :
|
||||
nh(h),
|
||||
private_nh("~")
|
||||
{
|
||||
// Get node parameters
|
||||
private_nh.param<std::string>("port", comportNo, "/dev/ttyUSB0");
|
||||
private_nh.param("baudrate", baudrate, 115200);
|
||||
private_nh.param("autoreconnect", autoReconnect, true);
|
||||
private_nh.param<std::string>("frame_id", frame_id, "imu");
|
||||
private_nh.param("rate", rate, 200);
|
||||
|
||||
// Create LpmsNAV3 object
|
||||
sensor1 = IG1Factory();
|
||||
sensor1->setVerbose(VERBOSE_INFO);
|
||||
sensor1->setAutoReconnectStatus(autoReconnect);
|
||||
|
||||
imu_pub = nh.advertise<sensor_msgs::Imu>("data",1);
|
||||
autocalibration_status_pub = nh.advertise<std_msgs::Bool>("is_autocalibration_active", 1, true);
|
||||
|
||||
autocalibration_serv = nh.advertiseService("enable_gyro_autocalibration", &LpNAV3Proxy::setAutocalibration, this);
|
||||
autoReconnect_serv = nh.advertiseService("enable_auto_reconnect", &LpNAV3Proxy::setAutoReconnect, this);
|
||||
gyrocalibration_serv = nh.advertiseService("calibrate_gyroscope", &LpNAV3Proxy::calibrateGyroscope, this);
|
||||
resetHeading_serv = nh.advertiseService("reset_heading", &LpNAV3Proxy::resetHeading, this);
|
||||
getImuData_serv = nh.advertiseService("get_imu_data", &LpNAV3Proxy::getImuData, this);
|
||||
setStreamingMode_serv = nh.advertiseService("set_streaming_mode", &LpNAV3Proxy::setStreamingMode, this);
|
||||
setCommandMode_serv = nh.advertiseService("set_command_mode", &LpNAV3Proxy::setCommandMode, this);
|
||||
|
||||
// Connects to sensor
|
||||
if (!sensor1->connect(comportNo, baudrate))
|
||||
{
|
||||
//logd(TAG, "Error connecting to sensor\n");
|
||||
ROS_ERROR("Error connecting to sensor\n");
|
||||
sensor1->release();
|
||||
ros::Duration(3).sleep(); // sleep 3 s
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ROS_INFO("Waiting for sensor to connect %d", sensor1->getStatus());
|
||||
ros::Duration(1).sleep();
|
||||
} while(
|
||||
ros::ok() &&
|
||||
(
|
||||
!(sensor1->getStatus() == STATUS_CONNECTED) &&
|
||||
!(sensor1->getStatus() == STATUS_CONNECTION_ERROR)
|
||||
)
|
||||
);
|
||||
|
||||
if (sensor1->getStatus() == STATUS_CONNECTED)
|
||||
{
|
||||
ROS_INFO("Sensor connected");
|
||||
ros::Duration(1).sleep();
|
||||
sensor1->commandGotoStreamingMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_INFO("Sensor connection error: %d.", sensor1->getStatus());
|
||||
ros::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
~LpNAV3Proxy(void)
|
||||
{
|
||||
sensor1->release();
|
||||
}
|
||||
|
||||
void update(const ros::TimerEvent& te)
|
||||
{
|
||||
static bool runOnce = false;
|
||||
|
||||
if (sensor1->getStatus() == STATUS_CONNECTED &&
|
||||
sensor1->hasImuData())
|
||||
{
|
||||
if (!runOnce)
|
||||
{
|
||||
publishIsAutocalibrationActive();
|
||||
runOnce = true;
|
||||
}
|
||||
IG1ImuDataI sd;
|
||||
sensor1->getImuData(sd);
|
||||
|
||||
/* Fill the IMU message */
|
||||
|
||||
// Fill the header
|
||||
imu_msg.header.stamp = ros::Time::now();
|
||||
imu_msg.header.frame_id = frame_id;
|
||||
|
||||
// Fill orientation quaternion
|
||||
imu_msg.orientation.w = sd.quaternion.data[0];
|
||||
imu_msg.orientation.x = sd.quaternion.data[1];
|
||||
imu_msg.orientation.y = sd.quaternion.data[2];
|
||||
imu_msg.orientation.z = sd.quaternion.data[3];
|
||||
|
||||
// Fill angular velocity data
|
||||
// - scale from deg/s to rad/s
|
||||
imu_msg.angular_velocity.x = sd.gyroIAlignmentCalibrated.data[0]*3.1415926/180;
|
||||
imu_msg.angular_velocity.y = sd.gyroIAlignmentCalibrated.data[1]*3.1415926/180;
|
||||
imu_msg.angular_velocity.z = sd.gyroIAlignmentCalibrated.data[2]*3.1415926/180;
|
||||
|
||||
// Fill linear acceleration data
|
||||
imu_msg.linear_acceleration.x = sd.accCalibrated.data[0]*9.81;
|
||||
imu_msg.linear_acceleration.y = sd.accCalibrated.data[1]*9.81;
|
||||
imu_msg.linear_acceleration.z = sd.accCalibrated.data[2]*9.81;
|
||||
|
||||
|
||||
// Publish the messages
|
||||
imu_pub.publish(imu_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void run(void)
|
||||
{
|
||||
// The timer ensures periodic data publishing
|
||||
updateTimer = ros::Timer(nh.createTimer(ros::Duration(1.0f/rate),
|
||||
&LpNAV3Proxy::update,
|
||||
this));
|
||||
}
|
||||
|
||||
void publishIsAutocalibrationActive()
|
||||
{
|
||||
std_msgs::Bool msg;
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
msg.data = settings.enableGyroAutocalibration;
|
||||
autocalibration_status_pub.publish(msg);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Service Callbacks
|
||||
///////////////////////////////////////////////////
|
||||
bool setAutocalibration (std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
|
||||
{
|
||||
ROS_INFO("set_autocalibration");
|
||||
|
||||
// clear current settings
|
||||
IG1SettingsI settings;
|
||||
sensor1->getSettings(settings);
|
||||
|
||||
// Send command
|
||||
cmdSetEnableAutocalibration(req.data);
|
||||
ros::Duration(0.2).sleep();
|
||||
cmdGetEnableAutocalibration();
|
||||
ros::Duration(0.1).sleep();
|
||||
|
||||
double retryElapsedTime = 0;
|
||||
int retryCount = 0;
|
||||
while (!sensor1->hasSettings())
|
||||
{
|
||||
ros::Duration(0.1).sleep();
|
||||
ROS_INFO("set_autocalibration wait");
|
||||
|
||||
retryElapsedTime += 0.1;
|
||||
if (retryElapsedTime > 2.0)
|
||||
{
|
||||
retryElapsedTime = 0;
|
||||
cmdGetEnableAutocalibration();
|
||||
retryCount++;
|
||||
}
|
||||
|
||||
if (retryCount > 5)
|
||||
break;
|
||||
}
|
||||
ROS_INFO("set_autocalibration done");
|
||||
|
||||
// Get settings
|
||||
sensor1->getSettings(settings);
|
||||
|
||||
std::string msg;
|
||||
if (settings.enableGyroAutocalibration == req.data)
|
||||
{
|
||||
res.success = true;
|
||||
msg.append(std::string("[Success] autocalibration status set to: ") + (settings.enableGyroAutocalibration?"True":"False"));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.success = false;
|
||||
msg.append(std::string("[Failed] current autocalibration status set to: ") + (settings.enableGyroAutocalibration?"True":"False"));
|
||||
}
|
||||
|
||||
ROS_INFO("%s", msg.c_str());
|
||||
res.message = msg;
|
||||
|
||||
publishIsAutocalibrationActive();
|
||||
return res.success;
|
||||
}
|
||||
|
||||
// Auto reconnect
|
||||
bool setAutoReconnect (std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
|
||||
{
|
||||
ROS_INFO("set_auto_reconnect");
|
||||
|
||||
sensor1->setAutoReconnectStatus(req.data);
|
||||
|
||||
res.success = true;
|
||||
std::string msg;
|
||||
msg.append(std::string("[Success] auto reconnection status set to: ") + (sensor1->getAutoReconnectStatus()?"True":"False"));
|
||||
|
||||
ROS_INFO("%s", msg.c_str());
|
||||
res.message = msg;
|
||||
|
||||
return res.success;
|
||||
}
|
||||
|
||||
// reset heading
|
||||
bool resetHeading (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
ROS_INFO("reset_heading");
|
||||
|
||||
// Send command
|
||||
cmdResetHeading();
|
||||
|
||||
res.success = true;
|
||||
res.message = "[Success] Heading reset";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool calibrateGyroscope (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
ROS_INFO("calibrate_gyroscope: Please make sure the sensor is stationary for 4 seconds");
|
||||
|
||||
cmdCalibrateGyroscope();
|
||||
|
||||
ros::Duration(4).sleep();
|
||||
res.success = true;
|
||||
res.message = "[Success] Gyroscope calibration procedure completed";
|
||||
ROS_INFO("calibrate_gyroscope: Gyroscope calibration procedure completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getImuData (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoCommandMode();
|
||||
ros::Duration(0.1).sleep();
|
||||
cmdGetImuData();
|
||||
res.success = true;
|
||||
res.message = "[Success] Get imu data";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setStreamingMode (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoStreamingMode();
|
||||
res.success = true;
|
||||
res.message = "[Success] Set streaming mode";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setCommandMode (std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
|
||||
{
|
||||
cmdGotoCommandMode();
|
||||
res.success = true;
|
||||
res.message = "[Success] Set command mode";
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Helpers
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
void cmdGotoCommandMode ()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GOTO_COMMAND_MODE;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGotoStreamingMode ()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GOTO_STREAM_MODE;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGetImuData()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GET_IMU_DATA;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdCalibrateGyroscope()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = START_GYR_CALIBRATION;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdResetHeading()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = SET_ORIENTATION_OFFSET;
|
||||
cmd.dataLength = 4;
|
||||
cmd.data.i[0] = LPMS_OFFSET_MODE_HEADING;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdSetEnableAutocalibration(int status)
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = SET_ENABLE_GYR_AUTOCALIBRATION;
|
||||
cmd.dataLength = 4;
|
||||
cmd.data.i[0] = status;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
void cmdGetEnableAutocalibration()
|
||||
{
|
||||
IG1Command cmd;
|
||||
cmd.command = GET_ENABLE_GYR_AUTOCALIBRATION;
|
||||
cmd.dataLength = 0;
|
||||
sensor1->sendCommand(cmd.command, cmd.dataLength, cmd.data.c);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Access to LPMS data
|
||||
IG1I* sensor1;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
ros::init(argc, argv, "lpms_be1_node");
|
||||
ros::NodeHandle nh("imu");
|
||||
|
||||
ros::AsyncSpinner spinner(0);
|
||||
spinner.start();
|
||||
|
||||
LpNAV3Proxy lpNAV3(nh);
|
||||
|
||||
lpNAV3.run();
|
||||
ros::waitForShutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
|
||||
#include "ros/ros.h"
|
||||
#include "sensor_msgs/Imu.h"
|
||||
#include <iostream>
|
||||
#include <tf/transform_datatypes.h>
|
||||
|
||||
ros::Publisher rpy_publisher;
|
||||
ros::Subscriber quat_subscriber;
|
||||
|
||||
const float r2d = 57.29577951f;
|
||||
|
||||
void MsgCallback(const sensor_msgs::Imu::ConstPtr& msg)
|
||||
{
|
||||
tf::Quaternion q(msg->orientation.x, msg->orientation.y, msg->orientation.z, msg->orientation.w);
|
||||
tf::Matrix3x3 m(q);
|
||||
double roll, pitch, yaw;
|
||||
m.getRPY(roll, pitch, yaw);
|
||||
|
||||
geometry_msgs::Vector3 rpy;
|
||||
rpy.x = roll;
|
||||
rpy.y = pitch;
|
||||
rpy.z = yaw;
|
||||
|
||||
rpy_publisher.publish(rpy);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "imu_listener");
|
||||
ros::NodeHandle n;
|
||||
rpy_publisher = n.advertise<geometry_msgs::Vector3>("rpy_angles", 1000);
|
||||
quat_subscriber = n.subscribe("/imu/data", 1000, MsgCallback);
|
||||
|
||||
ROS_INFO("waiting for imu data");
|
||||
ros::spin();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <winres.h>
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0, 0, 3, 0
|
||||
PRODUCTVERSION 0, 0, 3, 0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "LpmsIG1_OpenSourceLib"
|
||||
VALUE "FileVersion", "0, 3, 0"
|
||||
VALUE "InternalName", "LpmsIG1_OpenSourceLib"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021 LP-Research Inc."
|
||||
VALUE "OriginalFilename", "LpmsIG1_OpenSourceLib.dll"
|
||||
VALUE "ProductName", "LpmsIG1_OpenSourceLib"
|
||||
VALUE "ProductVersion", "0.3.0 (Build 20210907)"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
Reference in New Issue
Block a user