Program Listing for File rt_usb_9axisimu.hpp
↰ Return to documentation for file (include/rt_usb_9axisimu_driver/rt_usb_9axisimu.hpp)
/*
* rt_usb_9axisimu.hpp
*
* License: BSD-3-Clause
*
* Copyright (c) 2015-2020 RT Corporation <support@rt-net.jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of RT Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* 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 OWNER 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 RT_USB_9AXISIMU_DRIVER__RT_USB_9AXISIMU_HPP_
#define RT_USB_9AXISIMU_DRIVER__RT_USB_9AXISIMU_HPP_
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <cmath>
#include <sstream>
#include <string>
/**********************************************************************************************************
*
* Constants
*
**********************************************************************************************************/
namespace rt_usb_9axisimu
{
class Consts
{
public:
enum IMU_BINARY_DATA_TABLE
{
IMU_BIN_HEADER_FF0 = 0,
IMU_BIN_HEADER_FF1 = 1,
IMU_BIN_HEADER_R = 2,
IMU_BIN_HEADER_T = 3,
IMU_BIN_HEADER_ID0 = 4,
IMU_BIN_HEADER_ID1 = 5,
IMU_BIN_FIRMWARE = 6,
IMU_BIN_TIMESTAMP = 7,
IMU_BIN_ACC_X_L = 8,
IMU_BIN_ACC_X_H = 9,
IMU_BIN_ACC_Y_L = 10,
IMU_BIN_ACC_Y_H = 11,
IMU_BIN_ACC_Z_L = 12,
IMU_BIN_ACC_Z_H = 13,
IMU_BIN_TEMP_L = 14,
IMU_BIN_TEMP_H = 15,
IMU_BIN_GYRO_X_L = 16,
IMU_BIN_GYRO_X_H = 17,
IMU_BIN_GYRO_Y_L = 18,
IMU_BIN_GYRO_Y_H = 19,
IMU_BIN_GYRO_Z_L = 20,
IMU_BIN_GYRO_Z_H = 21,
IMU_BIN_MAG_X_L = 22,
IMU_BIN_MAG_X_H = 23,
IMU_BIN_MAG_Y_L = 24,
IMU_BIN_MAG_Y_H = 25,
IMU_BIN_MAG_Z_L = 26,
IMU_BIN_MAG_Z_H = 27,
IMU_BIN_DATA_SIZE = 28,
};
enum IMU_ASCII_DATA_TABLE
{
IMU_ASCII_TIMESTAMP = 0,
IMU_ASCII_GYRO_X,
IMU_ASCII_GYRO_Y,
IMU_ASCII_GYRO_Z,
IMU_ASCII_ACC_X,
IMU_ASCII_ACC_Y,
IMU_ASCII_ACC_Z,
IMU_ASCII_MAG_X,
IMU_ASCII_MAG_Y,
IMU_ASCII_MAG_Z,
IMU_ASCII_TEMP,
IMU_ASCII_DATA_SIZE
};
static constexpr int READ_BUFFER_SIZE = 512;
// Convertor
const double CONVERTOR_RAW2G;
const double CONVERTOR_RAW2DPS;
double CONVERTOR_RAW2UT;
double CONVERTOR_RAW2C_1;
double CONVERTOR_RAW2C_2;
const double CONVERTOR_G2A;
const double CONVERTOR_D2R;
const double CONVERTOR_UT2T;
const double DEFAULT_LINEAR_ACCELERATION_STDDEV;
const double DEFAULT_ANGULAR_VELOCITY_STDDEV;
const double DEFAULT_MAGNETIC_FIELD_STDDEV;
Consts()
: CONVERTOR_RAW2G(2048), // for linear_acceleration (raw data to [g])
CONVERTOR_RAW2DPS(16.4), // for angular_velocity (raw data to [degree/s])
CONVERTOR_RAW2UT(0.3), // for magnetic_field (raw data to [uT])
CONVERTOR_RAW2C_1(340), // for temperature (raw data to celsius)
CONVERTOR_RAW2C_2(35), // for temperature (raw data to celsius)
CONVERTOR_G2A(9.80665), // for linear_acceleration (g to m/s^2)
CONVERTOR_D2R(M_PI / 180.0), // for angular_velocity (degree to radian)
CONVERTOR_UT2T(1000000), // for magnetic_field (uT to Tesla)
DEFAULT_LINEAR_ACCELERATION_STDDEV(0.023145) // Default of square root of the
// linear_acceleration_covariance diagonal
// elements in m/s^2.
, DEFAULT_ANGULAR_VELOCITY_STDDEV(0.0010621) // Default of square root of the
// angular_velocity_covariance diagonal
// elements in rad/s.
, DEFAULT_MAGNETIC_FIELD_STDDEV(0.00000080786) // Default of square root of the
// magnetic_field_covariance diagonal
// elements in Tesla.
{
}
~Consts()
{
}
// Method to adjust convertors to firmware version
void ChangeConvertor(const int firmware_ver)
{
if (firmware_ver == 5) {
CONVERTOR_RAW2UT = 0.3;
CONVERTOR_RAW2C_1 = 340;
CONVERTOR_RAW2C_2 = 35;
} else if (firmware_ver >= 6) {
CONVERTOR_RAW2UT = 0.15;
CONVERTOR_RAW2C_1 = 333.87;
CONVERTOR_RAW2C_2 = 21;
}
}
};
/**********************************************************************************************************
*
* Serial port abstraction
*
**********************************************************************************************************/
class SerialPort
{
private:
std::string port_name_; // ex) "/dev/ttyACM0"
struct termios old_settings_;
int port_fd_;
public:
explicit SerialPort(const char * port = "")
: port_name_(port), port_fd_(-1)
{
}
virtual ~SerialPort()
{
closeSerialPort();
}
virtual void setPort(const char * port)
{
port_name_ = port;
}
virtual bool openPort(const char * port)
{
port_name_ = port;
return openSerialPort();
}
virtual bool openSerialPort()
{
int fd = 0;
if (port_fd_ > 0) {
return true;
}
fd = open(port_name_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); // Open serial port
if (fd < 0) {
return false; // Port open error
}
struct termios settings;
tcgetattr(fd, &old_settings_);
cfsetispeed(&settings, B57600);
cfmakeraw(&settings);
tcsetattr(fd, TCSANOW, &settings);
port_fd_ = fd;
return fd > 0;
}
virtual void closeSerialPort()
{
if (port_fd_ > 0) {
tcsetattr(port_fd_, TCSANOW, &old_settings_);
close(port_fd_); // Close serial port
port_fd_ = -1;
}
}
virtual int readFromDevice(unsigned char * buf, unsigned int buf_len)
{
if (port_fd_ < 0) {
return -1;
}
return read(port_fd_, buf, buf_len);
}
virtual int writeToDevice(unsigned char * data, unsigned int data_len)
{
if (port_fd_ < 0) {
return -1;
}
return write(port_fd_, data, data_len);
}
};
/**************************************************************************
*
* IMU
*
**************************************************************************/
// Class to store either raw integer imu data or converted physical quantity
template<typename Type>
class ImuData
{
public:
int firmware_ver;
int timestamp;
Type ax, ay, az, gx, gy, gz, mx, my, mz, temperature;
ImuData()
{
reset();
}
~ImuData()
{
}
inline void reset()
{
firmware_ver = 5;
timestamp = -1;
ax = ay = az = gx = gy = gz = mx = my = mz = temperature = 0;
}
};
class SensorData
{
private:
ImuData<int16_t> imu_raw_data_;
ImuData<double> imu_;
Consts consts_;
public:
SensorData()
{
reset();
}
~SensorData()
{
}
void reset()
{
imu_raw_data_.reset();
imu_.reset();
}
void setImuRawData(ImuData<int16_t> & i)
{
imu_raw_data_ = i;
}
void setImuData(ImuData<double> & i)
{
imu_ = i;
}
// Method to convert raw integer imu_ data to physical quantity
void convertRawDataUnit()
{
// Adjust convertors to firmware version
consts_.ChangeConvertor(imu_raw_data_.firmware_ver);
imu_.firmware_ver = imu_raw_data_.firmware_ver;
imu_.timestamp = imu_raw_data_.timestamp;
// Convert raw data to [g]
imu_.ax = imu_raw_data_.ax / consts_.CONVERTOR_RAW2G;
imu_.ay = imu_raw_data_.ay / consts_.CONVERTOR_RAW2G;
imu_.az = imu_raw_data_.az / consts_.CONVERTOR_RAW2G;
// Convert raw data to [degree/s]
imu_.gx = imu_raw_data_.gx / consts_.CONVERTOR_RAW2DPS;
imu_.gy = imu_raw_data_.gy / consts_.CONVERTOR_RAW2DPS;
imu_.gz = imu_raw_data_.gz / consts_.CONVERTOR_RAW2DPS;
// Convert raw data to [uT]
imu_.mx = imu_raw_data_.mx * consts_.CONVERTOR_RAW2UT;
imu_.my = imu_raw_data_.my * consts_.CONVERTOR_RAW2UT;
imu_.mz = imu_raw_data_.mz * consts_.CONVERTOR_RAW2UT;
// Convert raw data to celsius
imu_.temperature = imu_raw_data_.temperature / consts_.CONVERTOR_RAW2C_1 +
consts_.CONVERTOR_RAW2C_2;
}
ImuData<double> getImuData()
{
return imu_;
}
};
} // namespace rt_usb_9axisimu
#endif // RT_USB_9AXISIMU_DRIVER__RT_USB_9AXISIMU_HPP_