Skip to content

Commit

Permalink
* add imu module
Browse files Browse the repository at this point in the history
  • Loading branch information
lxowalle committed Oct 11, 2024
1 parent 2770abd commit 1d33f05
Show file tree
Hide file tree
Showing 14 changed files with 357 additions and 93 deletions.
139 changes: 139 additions & 0 deletions components/ext_dev/include/maix_imu.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/**
* @author iawak9lkm
* @copyright Sipeed Ltd 2024-
* @license Apache 2.0
* @update 2024.8.6: Add framework, create this file.
*/

#pragma once
#include "maix_basic.hpp"

#include <atomic>
#include <future>

namespace maix::ext_dev::imu {

/**
* @brief imu mode
* @maixpy maix.ext_dev.imu.Mode
*/
enum Mode {
ACC_ONLY = 0,
GYRO_ONLY,
DUAL
};

/**
* @brief imu acc scale
* @maixpy maix.ext_dev.imu.AccScale
*/
enum AccScale {
ACC_SCALE_2G = 0,
ACC_SCALE_4G,
ACC_SCALE_8G,
ACC_SCALE_16G
};

/**
* @brief imu acc output data rate
* @maixpy maix.ext_dev.imu.AccOdr
*/
enum AccOdr {
ACC_ODR_8000, // Accelerometer ODR set to 8000 Hz.
ACC_ODR_4000, // Accelerometer ODR set to 4000 Hz.
ACC_ODR_2000, // Accelerometer ODR set to 2000 Hz.
ACC_ODR_1000, // Accelerometer ODR set to 1000 Hz.
ACC_ODR_500, // Accelerometer ODR set to 500 Hz.
ACC_ODR_250, // Accelerometer ODR set to 250 Hz.
ACC_ODR_125, // Accelerometer ODR set to 125 Hz.
ACC_ODR_62_5, // Accelerometer ODR set to 62.5 Hz.
ACC_ODR_31_25, // Accelerometer ODR set to 31.25 Hz.
ACC_ODR_128 = 12, // Accelerometer ODR set to 128 Hz.
ACC_ODR_21, // Accelerometer ODR set to 21 Hz.
ACC_ODR_11, // Accelerometer ODR set to 11 Hz.
ACC_ODR_3, // Accelerometer ODR set to 3 Hz.
};

/**
* @brief imu gyro scale
* @maixpy maix.ext_dev.imu.GyroScale
*/
enum GyroScale {
GYRO_SCALE_16DPS = 0, // Gyroscope scale set to ±16 degrees per second.
GYRO_SCALE_32DPS, // Gyroscope scale set to ±32 degrees per second.
GYRO_SCALE_64DPS, // Gyroscope scale set to ±64 degrees per second.
GYRO_SCALE_128DPS, // Gyroscope scale set to ±128 degrees per second.
GYRO_SCALE_256DPS, // Gyroscope scale set to ±256 degrees per second.
GYRO_SCALE_512DPS, // Gyroscope scale set to ±512 degrees per second.
GYRO_SCALE_1024DPS, // Gyroscope scale set to ±1024 degrees per second.
GYRO_SCALE_2048DPS, // Gyroscope scale set to ±2048 degrees per second.
};

/**
* @brief imu gyro output data rate
* @maixpy maix.ext_dev.imu.GyroOdr
*/
enum GyroOdr {
GYRO_ODR_8000, // Gyroscope ODR set to 8000 Hz.
GYRO_ODR_4000, // Gyroscope ODR set to 4000 Hz.
GYRO_ODR_2000, // Gyroscope ODR set to 2000 Hz.
GYRO_ODR_1000, // Gyroscope ODR set to 1000 Hz.
GYRO_ODR_500, // Gyroscope ODR set to 500 Hz.
GYRO_ODR_250, // Gyroscope ODR set to 250 Hz.
GYRO_ODR_125, // Gyroscope ODR set to 125 Hz.
GYRO_ODR_62_5, // Gyroscope ODR set to 62.5 Hz.
GYRO_ODR_31_25, // Gyroscope ODR set to 31.25 Hz.
};

/**
* QMI8656 driver class
* @maixpy maix.ext_dev.imu.IMU
*/
class IMU {
public:
/**
* @brief Construct a new IMU object, will open IMU
*
* @param driver driver name, only support "qmi8656"
* @param i2c_bus i2c bus number. Automatically selects the on-board imu when -1 is passed in.
* @param addr IMU i2c addr.
* @param freq IMU freq
* @param mode IMU Mode: ACC_ONLY/GYRO_ONLY/DUAL
* @param acc_scale acc scale, see @imu::AccScale
* @param acc_odr acc output data rate, see @imu::AccOdr
* @param gyro_scale gyro scale, see @imu::GyroScale
* @param gyro_odr gyro output data rate, see @imu::GyroOdr
* @param block block or non-block, defalut is true
*
* @maixpy maix.ext_dev.imu.IMU.__init__
*/
IMU(std::string driver, int i2c_bus=-1, int addr=0x6B, int freq=400000,
maix::ext_dev::imu::Mode mode=maix::ext_dev::imu::Mode::DUAL,
maix::ext_dev::imu::AccScale acc_scale=maix::ext_dev::imu::AccScale::ACC_SCALE_2G,
maix::ext_dev::imu::AccOdr acc_odr=maix::ext_dev::imu::AccOdr::ACC_ODR_8000,
maix::ext_dev::imu::GyroScale gyro_scale=maix::ext_dev::imu::GyroScale::GYRO_SCALE_16DPS,
maix::ext_dev::imu::GyroOdr gyro_odr=maix::ext_dev::imu::GyroOdr::GYRO_ODR_8000,
bool block=true);
~IMU();

IMU(const IMU&) = delete;
IMU& operator=(const IMU&) = delete;
IMU(IMU&&) = delete;
IMU& operator=(IMU&&) = delete;

/**
* @brief Read data from IMU.
*
* @return list type. If only one of the outputs is initialized, only [x,y,z] of that output will be returned.
* If all outputs are initialized, [acc_x, acc_y, acc_z, gyro_x, gyro_y, gyro_z] is returned.
*
* @maixpy maix.ext_dev.imu.IMU.read
*/
std::vector<float> read();
private:
void* _param;
std::string _driver;
};


}
85 changes: 7 additions & 78 deletions components/ext_dev/include/maix_qmi8658.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,83 +7,12 @@

#pragma once
#include "maix_basic.hpp"
#include "maix_imu.hpp"
#include <atomic>
#include <future>

namespace maix::ext_dev::qmi8658 {

/**
* @brief qmi8658 mode
* @maixpy maix.ext_dev.qmi8658.Mode
*/
enum Mode {
ACC_ONLY = 0,
GYRO_ONLY,
DUAL
};

/**
* @brief qmi8658 acc scale
* @maixpy maix.ext_dev.qmi8658.AccScale
*/
enum AccScale {
ACC_SCALE_2G = 0,
ACC_SCALE_4G,
ACC_SCALE_8G,
ACC_SCALE_16G
};

/**
* @brief qmi8658 acc output data rate
* @maixpy maix.ext_dev.qmi8658.AccOdr
*/
enum AccOdr {
ACC_ODR_8000, // Accelerometer ODR set to 8000 Hz.
ACC_ODR_4000, // Accelerometer ODR set to 4000 Hz.
ACC_ODR_2000, // Accelerometer ODR set to 2000 Hz.
ACC_ODR_1000, // Accelerometer ODR set to 1000 Hz.
ACC_ODR_500, // Accelerometer ODR set to 500 Hz.
ACC_ODR_250, // Accelerometer ODR set to 250 Hz.
ACC_ODR_125, // Accelerometer ODR set to 125 Hz.
ACC_ODR_62_5, // Accelerometer ODR set to 62.5 Hz.
ACC_ODR_31_25, // Accelerometer ODR set to 31.25 Hz.
ACC_ODR_128 = 12, // Accelerometer ODR set to 128 Hz.
ACC_ODR_21, // Accelerometer ODR set to 21 Hz.
ACC_ODR_11, // Accelerometer ODR set to 11 Hz.
ACC_ODR_3, // Accelerometer ODR set to 3 Hz.
};

/**
* @brief qmi8658 gyro scale
* @maixpy maix.ext_dev.qmi8658.GyroScale
*/
enum GyroScale {
GYRO_SCALE_16DPS = 0, // Gyroscope scale set to ±16 degrees per second.
GYRO_SCALE_32DPS, // Gyroscope scale set to ±32 degrees per second.
GYRO_SCALE_64DPS, // Gyroscope scale set to ±64 degrees per second.
GYRO_SCALE_128DPS, // Gyroscope scale set to ±128 degrees per second.
GYRO_SCALE_256DPS, // Gyroscope scale set to ±256 degrees per second.
GYRO_SCALE_512DPS, // Gyroscope scale set to ±512 degrees per second.
GYRO_SCALE_1024DPS, // Gyroscope scale set to ±1024 degrees per second.
GYRO_SCALE_2048DPS, // Gyroscope scale set to ±2048 degrees per second.
};

/**
* @brief qmi8658 gyro output data rate
* @maixpy maix.ext_dev.qmi8658.GyroOdr
*/
enum GyroOdr {
GYRO_ODR_8000, // Gyroscope ODR set to 8000 Hz.
GYRO_ODR_4000, // Gyroscope ODR set to 4000 Hz.
GYRO_ODR_2000, // Gyroscope ODR set to 2000 Hz.
GYRO_ODR_1000, // Gyroscope ODR set to 1000 Hz.
GYRO_ODR_500, // Gyroscope ODR set to 500 Hz.
GYRO_ODR_250, // Gyroscope ODR set to 250 Hz.
GYRO_ODR_125, // Gyroscope ODR set to 125 Hz.
GYRO_ODR_62_5, // Gyroscope ODR set to 62.5 Hz.
GYRO_ODR_31_25, // Gyroscope ODR set to 31.25 Hz.
};

/**
* QMI8656 driver class
* @maixpy maix.ext_dev.qmi8658.QMI8658
Expand All @@ -106,11 +35,11 @@ class QMI8658 {
* @maixpy maix.ext_dev.qmi8658.QMI8658.__init__
*/
QMI8658(int i2c_bus=-1, int addr=0x6B, int freq=400000,
maix::ext_dev::qmi8658::Mode mode=maix::ext_dev::qmi8658::Mode::DUAL,
maix::ext_dev::qmi8658::AccScale acc_scale=maix::ext_dev::qmi8658::AccScale::ACC_SCALE_2G,
maix::ext_dev::qmi8658::AccOdr acc_odr=maix::ext_dev::qmi8658::AccOdr::ACC_ODR_8000,
maix::ext_dev::qmi8658::GyroScale gyro_scale=maix::ext_dev::qmi8658::GyroScale::GYRO_SCALE_16DPS,
maix::ext_dev::qmi8658::GyroOdr gyro_odr=maix::ext_dev::qmi8658::GyroOdr::GYRO_ODR_8000,
maix::ext_dev::imu::Mode mode=maix::ext_dev::imu::Mode::DUAL,
maix::ext_dev::imu::AccScale acc_scale=maix::ext_dev::imu::AccScale::ACC_SCALE_2G,
maix::ext_dev::imu::AccOdr acc_odr=maix::ext_dev::imu::AccOdr::ACC_ODR_8000,
maix::ext_dev::imu::GyroScale gyro_scale=maix::ext_dev::imu::GyroScale::GYRO_SCALE_16DPS,
maix::ext_dev::imu::GyroOdr gyro_odr=maix::ext_dev::imu::GyroOdr::GYRO_ODR_8000,
bool block=true);
~QMI8658();

Expand All @@ -130,7 +59,7 @@ class QMI8658 {
std::vector<float> read();
private:
void* _data;
Mode _mode;
imu::Mode _mode;
std::atomic_bool reset_finished{false};
std::future<std::pair<int, std::string>> open_future;
bool open_fut_need_get{false};
Expand Down
51 changes: 51 additions & 0 deletions components/ext_dev/src/maix_imu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@

#include "maix_basic.hpp"
#include "maix_imu.hpp"
#include "maix_qmi8658.hpp"


namespace maix::ext_dev::imu {

typedef struct {
union {
maix::ext_dev::qmi8658::QMI8658 *qmi8658;
} driver;
} imu_param_t;

IMU::IMU(std::string driver, int i2c_bus, int addr, int freq, imu::Mode mode, imu::AccScale acc_scale,
imu::AccOdr acc_odr, imu::GyroScale gyro_scale, imu::GyroOdr gyro_odr, bool block)
{
err::check_bool_raise(driver == "qmi8658", "Only support qmi8658 now");
imu_param_t *param = (imu_param_t *)malloc(sizeof(imu_param_t));
err::check_null_raise(param, "Failed to malloc param");


param->driver.qmi8658 = new maix::ext_dev::qmi8658::QMI8658(i2c_bus, addr, freq, mode, acc_scale, acc_odr, gyro_scale, gyro_odr, block);
_param = (void *)param;
_driver = driver;
}

IMU::~IMU()
{
if (_param) {
imu_param_t *param = (imu_param_t *)_param;
if (_driver == "qmi8658") {
delete param->driver.qmi8658;
param->driver.qmi8658 = NULL;
}
free(_param);
_param = NULL;
}
}

std::vector<float> IMU::read()
{
std::vector<float> out;
imu_param_t *param = (imu_param_t *)_param;
if (_driver == "qmi8658") {
out = param->driver.qmi8658->read();
}
return out;
}

}
12 changes: 6 additions & 6 deletions components/ext_dev/src/qmi8658/maix_qmi8658.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,20 @@ void Qmi8658c::maix_qmi_deinit_i2c_bus(int bus)

namespace maix::ext_dev::qmi8658 {

static std::vector<float> make_read_result(const Mode& m, const priv::qmi_data_t& data)
static std::vector<float> make_read_result(const imu::Mode& m, const priv::qmi_data_t& data)
{
if (m == Mode::DUAL)
if (m == imu::Mode::DUAL)
return {data.acc_xyz.x, data.acc_xyz.y, data.acc_xyz.z, data.gyro_xyz.x, data.gyro_xyz.y, data.gyro_xyz.z, data.temperature};
if (m == Mode::ACC_ONLY)
if (m == imu::Mode::ACC_ONLY)
return {data.acc_xyz.x, data.acc_xyz.y, data.acc_xyz.z, data.temperature};
if (m == Mode::GYRO_ONLY)
if (m == imu::Mode::GYRO_ONLY)
return {data.gyro_xyz.x, data.gyro_xyz.y, data.gyro_xyz.z, data.temperature};
log::error("[%s] Unknown Mode, return empty", priv::TAG);
return {};
}

QMI8658::QMI8658(int i2c_bus, int addr, int freq, qmi8658::Mode mode, qmi8658::AccScale acc_scale,
qmi8658::AccOdr acc_odr, qmi8658::GyroScale gyro_scale, qmi8658::GyroOdr gyro_odr, bool block)
QMI8658::QMI8658(int i2c_bus, int addr, int freq, imu::Mode mode, imu::AccScale acc_scale,
imu::AccOdr acc_odr, imu::GyroScale gyro_scale, imu::GyroOdr gyro_odr, bool block)
{
auto qmi8658c = new priv::Qmi8658c(i2c_bus, (uint8_t)addr, freq);
this->_data = (void*)qmi8658c;
Expand Down
8 changes: 4 additions & 4 deletions components/vision/include/maix_video.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1295,9 +1295,9 @@ namespace maix::video
* if you bind a audio, audio will be recorded,
* if you bind a IMU, IMU data will be logged.
* @return error code
* @maixpy maix.video.VideoRecorder.record
* @maixpy maix.video.VideoRecorder.record_start
*/
err::Err record();
err::Err record_start();

/**
* @brief Take a snapshot
Expand All @@ -1309,9 +1309,9 @@ namespace maix::video
/**
* @brief Stop recording and save the video
* @return error code
* @maixpy maix.video.VideoRecorder.finish
* @maixpy maix.video.VideoRecorder.record_finish
*/
err::Err finish();
err::Err record_finish();

/**
* @brief Draw a rect on the video
Expand Down
4 changes: 2 additions & 2 deletions components/vision/port/linux/maix_video_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ namespace maix::video
return 0;
}

err::Err VideoRecorder::record()
err::Err VideoRecorder::record_start()
{
return err::ERR_NOT_IMPL;
}
Expand All @@ -275,7 +275,7 @@ namespace maix::video
return NULL;
}

err::Err VideoRecorder::finish()
err::Err VideoRecorder::record_finish()
{
return err::ERR_NOT_IMPL;
}
Expand Down
Loading

0 comments on commit 1d33f05

Please sign in to comment.