211 lines
6.6 KiB
C++
211 lines
6.6 KiB
C++
/*
|
|
* imu_service.cpp - interfaces for EIS algorithm to access imu sensor
|
|
*
|
|
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* Author: Cody Xie <cody.xie@rock-chips.com>
|
|
*/
|
|
#include "imu_service.h"
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
#include "xcam_common.h"
|
|
#include "xcam_log.h"
|
|
|
|
using namespace XCam;
|
|
|
|
namespace RkCam {
|
|
|
|
EisImuData::EisImuData(std::shared_ptr<EisImuAdaptor> imu, mems_sensor_type_t type,
|
|
mems_sensor_event_t* data, size_t count)
|
|
: imu_(imu), type_(type), data_(data), count_(count) {
|
|
XCAM_ASSERT(imu_.get() != nullptr && data_ != nullptr);
|
|
}
|
|
|
|
EisImuData::~EisImuData() { imu_->FreeData(data_); }
|
|
|
|
mems_sensor_type_t EisImuData::GetType() const { return type_; }
|
|
|
|
mems_sensor_event_t* EisImuData::GetData() const { return data_; }
|
|
|
|
size_t EisImuData::GetCount() const { return count_; }
|
|
|
|
EisImuAdaptor::EisImuAdaptor(const rk_aiq_mems_sensor_intf_t intf, const mems_sensor_type_t type)
|
|
: intf_(intf), type_(type), ctx_(nullptr), handle_(nullptr) {
|
|
XCAM_ASSERT(intf.createContext != nullptr && intf.getSensorList != nullptr);
|
|
}
|
|
|
|
EisImuAdaptor::~EisImuAdaptor() { DeInit(); }
|
|
|
|
XCamReturn EisImuAdaptor::Init(float sample_rate) {
|
|
mems_sensor_list_t sensors_list;
|
|
mems_sensor_capabilities_t caps;
|
|
|
|
if (ctx_ == nullptr) {
|
|
ctx_ = intf_.createContext();
|
|
if (ctx_ == nullptr) {
|
|
LOGE_AEIS("Create IMU context failed");
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
}
|
|
|
|
memset(&sensors_list, 0, sizeof(mems_sensor_list_t));
|
|
auto result = intf_.getSensorList(ctx_, type_, &sensors_list);
|
|
if (result == SENSOR_NO_ERR && sensors_list.count > 0) {
|
|
LOGV_AEIS("Get supported sensor list: ");
|
|
for (int32_t i = 0; i < sensors_list.count; i++) {
|
|
LOGV_AEIS("%d: %s", i, sensors_list.key_list[i]);
|
|
}
|
|
key_ = std::string(sensors_list.key_list[0]);
|
|
intf_.releaseSensorList(&sensors_list);
|
|
} else {
|
|
LOGE_AEIS("Init IMU get no dev");
|
|
intf_.destroyContext(ctx_);
|
|
ctx_ = nullptr;
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
|
|
memset(&caps, 0, sizeof(mems_sensor_capabilities_t));
|
|
const char* c = key_.c_str();
|
|
result = intf_.getSensorCapabilities(ctx_, type_, c, &caps);
|
|
if (result) {
|
|
LOGE_AEIS("Get IMU capabilities failed");
|
|
intf_.destroyContext(ctx_);
|
|
ctx_ = nullptr;
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
|
|
for (int32_t i = 0; i < caps.num_sample_rates; i++) {
|
|
LOGE_AEIS("Get IMU capabilities: %d:sample_cap: %f", i, caps.sample_rates[i]);
|
|
}
|
|
|
|
float matched_sample_rate = 0.0f;
|
|
float max_sample_rate = 0.0f;
|
|
for (int i = 0; i < caps.num_sample_rates; i++) {
|
|
if (max_sample_rate < caps.sample_rates[i]) {
|
|
max_sample_rate = caps.sample_rates[i];
|
|
}
|
|
if (sample_rate == caps.sample_rates[i]) {
|
|
matched_sample_rate = sample_rate;
|
|
break;
|
|
}
|
|
}
|
|
intf_.releaseSensorCapabilities(&caps);
|
|
if (0.0 == matched_sample_rate) {
|
|
matched_sample_rate = max_sample_rate;
|
|
}
|
|
|
|
XCAM_ASSERT(matched_sample_rate != 0.0f);
|
|
if (matched_sample_rate != 0.0) {
|
|
mems_sensor_config_t sensor_cfg;
|
|
memset(&sensor_cfg, 0, sizeof(mems_sensor_config_t));
|
|
result = intf_.getConfig(ctx_, type_, c, &sensor_cfg);
|
|
if (result != SENSOR_NO_ERR) {
|
|
LOGE_AEIS("Get current IMU config failed");
|
|
intf_.destroyContext(ctx_);
|
|
ctx_ = nullptr;
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
LOGD_AEIS("Get current IMU config: %f", sensor_cfg.sample_rate);
|
|
sensor_cfg.sample_rate = matched_sample_rate;
|
|
|
|
result = intf_.setConfig(ctx_, type_, c, sensor_cfg);
|
|
if (result != SENSOR_NO_ERR) {
|
|
LOGE_AEIS("Set IMU config failed\n");
|
|
intf_.destroyContext(ctx_);
|
|
ctx_ = nullptr;
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
LOGD_AEIS("Set IMU config succeed %f", matched_sample_rate);
|
|
}
|
|
|
|
handle_ = intf_.createHandle(ctx_, type_, key_.c_str(), 200, 7);
|
|
if (handle_ == nullptr) {
|
|
LOGE_AEIS("create IMU handle failed");
|
|
intf_.destroyContext(ctx_);
|
|
ctx_ = nullptr;
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
XCamReturn EisImuAdaptor::DeInit() {
|
|
XCAM_ASSERT(intf_.createContext != nullptr);
|
|
if (ctx_ != nullptr) {
|
|
if (handle_ != nullptr) {
|
|
intf_.destroyHandle(handle_);
|
|
}
|
|
intf_.destroyContext(ctx_);
|
|
}
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
mems_sensor_event_t* EisImuAdaptor::GetData(size_t* num_sample) {
|
|
XCAM_ASSERT(ctx_ != nullptr && handle_ != nullptr);
|
|
size_t count = 0;
|
|
|
|
auto data = reinterpret_cast<mems_sensor_event_t*>(intf_.getData(handle_, &count));
|
|
*num_sample = count;
|
|
|
|
#ifdef DEBUG
|
|
const char *dump_env = std::getenv("eis_dump_imu");
|
|
int dump = 0;
|
|
if (dump_env) {
|
|
dump = atoi(dump_env);
|
|
}
|
|
|
|
if (dump > 0 && data != nullptr && count > 0) {
|
|
std::ofstream ofs("/data/imu.txt", std::ios::app);
|
|
if (ofs.is_open()) {
|
|
for (size_t i = 0; i < count; i++) {
|
|
ofs << data[i].id << "," << data[i].timestamp_us << "," << data[i].all.gyro.x << ","
|
|
<< data[i].all.gyro.y << "," << data[i].all.gyro.z << std::endl;
|
|
}
|
|
}
|
|
ofs.close();
|
|
}
|
|
#endif
|
|
|
|
return data;
|
|
}
|
|
|
|
void EisImuAdaptor::FreeData(mems_sensor_event_t* data) {
|
|
XCAM_ASSERT(ctx_ != nullptr && handle_ != nullptr);
|
|
intf_.releaseSamplesData(handle_, data);
|
|
}
|
|
|
|
TaskResult ImuTask::operator()(ServiceParam<imu_param>& p) {
|
|
auto payload = p.payload;
|
|
size_t count = 0;
|
|
|
|
auto data = imu_->GetData(&count);
|
|
if (count > 0 && data != nullptr) {
|
|
payload->data =
|
|
std::unique_ptr<EisImuData>(new EisImuData(imu_, imu_->GetType(), data, count));
|
|
payload->time_point = std::chrono::system_clock::now();
|
|
} else {
|
|
payload->data = nullptr;
|
|
payload->time_point = std::chrono::system_clock::now();
|
|
return TaskResult::kFailed;
|
|
}
|
|
|
|
return TaskResult::kSuccess;
|
|
}
|
|
|
|
} // namespace RkCam
|