173 lines
5.1 KiB
C++
173 lines
5.1 KiB
C++
/******************** (C) COPYRIGHT 2023 Geek************************************
|
||
* File Name : MagCalibrate.cpp
|
||
* Department : Sensor Algorithm Team
|
||
* Current Version : V1.0
|
||
* Author : zhanli
|
||
* Date of Issued : 2023.09.10
|
||
* Comments : GeekIMU 늚제셕叫硫친욥
|
||
********************************************************************************/
|
||
/* Header File Including -----------------------------------------------------*/
|
||
|
||
#include <stdio.h>
|
||
#include <math.h>
|
||
#include <conio.h>
|
||
#include "MagCalibrate.h"
|
||
#include <fstream>
|
||
#include "Log.h"
|
||
|
||
#define ENABLE_DEBUG_LOG 1
|
||
|
||
MagData mdata[4000];
|
||
|
||
// 늚제셕돨친令쇱꿴
|
||
bool checkMagnetNorm(float x, float y, float z);
|
||
|
||
MagCaliParam CalculateMagCalibrationParams(MagData _mdata[], int dataSize)
|
||
{
|
||
MagCaliParam param, lastparam;
|
||
|
||
srand((unsigned)time(NULL));
|
||
|
||
float xmin = _mdata[0].x;
|
||
float ymin = _mdata[0].y;
|
||
float zmin = _mdata[0].z;
|
||
float xmax = _mdata[0].x;
|
||
float ymax = _mdata[0].y;
|
||
float zmax = _mdata[0].z;
|
||
float err, errnew;
|
||
|
||
for (int i = 0; i < dataSize; i++)
|
||
{
|
||
if (xmax < _mdata[i].x)
|
||
xmax = _mdata[i].x;
|
||
if (ymax < _mdata[i].y)
|
||
ymax = _mdata[i].y;
|
||
if (zmax < _mdata[i].z)
|
||
zmax = _mdata[i].z;
|
||
if (xmin > _mdata[i].x)
|
||
xmin = _mdata[i].x;
|
||
if (ymin > _mdata[i].y)
|
||
ymin = _mdata[i].y;
|
||
if (zmin > _mdata[i].z)
|
||
zmin = _mdata[i].z;
|
||
}
|
||
|
||
lastparam.xOffset = 0.5f * (xmax + xmin);
|
||
lastparam.yOffset = 0.5f * (ymax + ymin);
|
||
lastparam.zOffset = 0.5f * (zmax + zmin);
|
||
lastparam.xScale = 0.5f * fabs(xmax - xmin);
|
||
lastparam.yScale = 0.5f * fabs(ymax - ymin);
|
||
lastparam.zScale = 0.5f * fabs(zmax - zmin);
|
||
err = 0;
|
||
for (int i = 0; i < dataSize; i++)
|
||
err = err + fabs(powf((_mdata[i].x - lastparam.xOffset), 2) / powf(lastparam.xScale, 2) + powf((_mdata[i].y - lastparam.yOffset), 2) / powf(lastparam.yScale, 2) + powf((_mdata[i].z - lastparam.zOffset), 2) / powf(lastparam.zScale, 2) - 1);
|
||
//printf("xc = %f yc = %f zc = %f, a = %f b = %f c= %f,놓迦뺏InitErr = %f\n", lastparam.xOffset, lastparam.yOffset, lastparam.zOffset, lastparam.xScale, lastparam.yScale, lastparam.zScale, err);
|
||
int starttime = clock();
|
||
for (int j = 0; j < 5000; j++)
|
||
{
|
||
param.xOffset = lastparam.xOffset + rand() / (RAND_MAX + 1.0f) - 0.5f;
|
||
param.yOffset = lastparam.yOffset + rand() / (RAND_MAX + 1.0f) - 0.5f;
|
||
param.zOffset = lastparam.zOffset + rand() / (RAND_MAX + 1.0f) - 0.5f;
|
||
param.xScale = fabs(lastparam.xScale + rand() / (RAND_MAX + 1.0f) - 0.5f);
|
||
param.yScale = fabs(lastparam.yScale + rand() / (RAND_MAX + 1.0f) - 0.5f);
|
||
param.zScale = fabs(lastparam.zScale + rand() / (RAND_MAX + 1.0f) - 0.5f);
|
||
errnew = 0;
|
||
for (int i = 0; i < dataSize; i++)
|
||
errnew = errnew + fabs(powf((_mdata[i].x - param.xOffset), 2) / powf(param.xScale, 2) + powf((_mdata[i].y - param.yOffset), 2) / powf(param.yScale, 2) + powf((_mdata[i].z - param.zOffset), 2) / powf(param.zScale, 2) - 1);
|
||
if (errnew < err)
|
||
{
|
||
lastparam.xOffset = param.xOffset;
|
||
lastparam.yOffset = param.yOffset;
|
||
lastparam.zOffset = param.zOffset;
|
||
lastparam.xScale = param.xScale;
|
||
lastparam.yScale = param.yScale;
|
||
lastparam.zScale = param.zScale;
|
||
err = errnew;
|
||
}
|
||
}
|
||
param.xScale = 200 / param.xScale;
|
||
param.yScale = 200 / param.yScale;
|
||
param.zScale = 200 / param.zScale;
|
||
int durtime = clock() - starttime;
|
||
|
||
printf("%f, %f, %f, %f, %f, %f, %f\n cost:%dms\n", param.xOffset, param.yOffset, param.zOffset, param.xScale, param.yScale, param.zScale, err, durtime);
|
||
|
||
return param;
|
||
}
|
||
|
||
|
||
// 쇱꿴角뤠唐路릿돨늚제셕鑒앴
|
||
bool isDuplicateData(float x, float y, float z, int index) {
|
||
|
||
if (index < 0 || index >= 4000) {
|
||
return false;
|
||
}
|
||
// 흔벎x, y, z供홍宮谿,훰槨角路릿鑒앴
|
||
if (mdata[index].x == x && mdata[index].y == y && mdata[index].z == z) {
|
||
#if ENABLE_DEBUG_LOG
|
||
WriteLog(Info, "MagCalibrate: %.6f,%.6f,%.6f ==> Mag Data Duplicate\n",x,y,z);
|
||
#endif
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
MagCaliParam GetMagDataFormFile()
|
||
{
|
||
int maxdatasize = 4000;
|
||
std::ifstream fin("data.txt");
|
||
float x, y, z;
|
||
int i = 0;
|
||
clearMagData();
|
||
#if ENABLE_DEBUG_LOG
|
||
WriteLog(Info, "MagCalibrate: Get mag data form file\n");
|
||
#endif
|
||
while (fin) {
|
||
fin >> x >> y >> z;
|
||
// 속흙侶契,긁출離빈寧契渴놔좃늴
|
||
fin.get();
|
||
|
||
// 賈痰checkMagnetNorm변鑒쇱꿎角뤠槨嫩끽令 &&
|
||
// 쇱꿴뎠품뗍혤돕돨늚제셕xyz角뤠뵨<EBA4A0>寧늴供홍宮谿
|
||
if (checkMagnetNorm(x, y, z) || isDuplicateData(x, y, z, i - 1)) {
|
||
// 흔벎角嫩끽令,契법뎠품鑒앴
|
||
continue;
|
||
}
|
||
WriteLog(Info, "MagCalibrate: Load Magnet Data: %f,%f,%f\n",x,y,z);
|
||
mdata[i].x = x;
|
||
mdata[i].y = y;
|
||
mdata[i].z = z;
|
||
i++;
|
||
|
||
if (i == maxdatasize)
|
||
break;
|
||
}
|
||
|
||
MagCaliParam p = CalculateMagCalibrationParams(mdata, i);
|
||
|
||
return p;
|
||
}
|
||
|
||
// 賈痰memset헌왕mdata鑒莉
|
||
void clearMagData() {
|
||
std::memset(mdata, 0, sizeof(mdata)); // 쉥mdata돨코닸헌쥐
|
||
}
|
||
|
||
// 쇱꿴늚제셕돨친角뤠攣끽
|
||
bool checkMagnetNorm(float x, float y, float z) {
|
||
// 셕炬늚제셕鑒앴돨친
|
||
float norm = std::sqrt(x * x + y * y + z * z);
|
||
|
||
#if ENABLE_DEBUG_LOG
|
||
if (norm > 2000.0f) {
|
||
WriteLog(Info, "Magnet data norm > 2000.0f\n");
|
||
}
|
||
if (norm == 0.0f) {
|
||
WriteLog(Info, "Magnet data norm = 0.0f\n");
|
||
}
|
||
#endif
|
||
// 흔벎친댕黨2000샀諒된黨0,橙柬槨嫩끽
|
||
return (norm > 2000.0f || norm == 0.0f);
|
||
}
|