美文网首页
C++ 地磁校准

C++ 地磁校准

作者: Kerwin_H | 来源:发表于2021-09-13 09:36 被阅读0次

地磁标定校准

#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <ctime>

using namespace std;

bool load_csv(vector<float> &data_x, vector<float> &data_y, vector<float> &data_z){
    string string1 = "data.csv";
    ifstream ifs(string1, ios::in);
    if (!ifs.is_open())
    {
        cerr << "open file failed!" << endl;
        exit(-1);
    }

    string _line;
    vector<string> subArray;

    while (getline(ifs, _line))
    {
        //解析每行的数据
        stringstream ss(_line);
        string _sub;

        //按照逗号分隔
        int col = 0;
        while (getline(ss, _sub, ',')){
            col++;
            switch (col) {
                case 1:
                    data_x.push_back(stof(_sub));
                    break;
                case 2:
                    data_y.push_back(stof(_sub));
                    break;
                case 3:
                    data_z.push_back(stof(_sub));
                    break;
                default:
                    break;
            }
        }

    }
    ifs.close();
    return true;
}

float calib_mag(vector<float> &data_x, vector<float> &data_y, vector<float> &data_z){
// 初始解
    float x_min = *min_element(data_x.begin(), data_x.end());
    float x_max = *max_element(data_x.begin(), data_x.end());
    float y_min = *min_element(data_y.begin(), data_y.end());
    float y_max = *max_element(data_y.begin(), data_y.end());
    float z_min = *min_element(data_z.begin(), data_z.end());
    float z_max = *max_element(data_z.begin(), data_z.end());
    float xc = 0.5f * (x_min + x_max);
    float yc = 0.5f * (y_min + y_max);
    float zc = 0.5f * (z_min + z_max);
    float a = 0.5f * abs(x_max - x_min);
    float b = 0.5f * abs(y_max - y_min);
    float c = 0.5f * abs(z_max - z_min);
//    xc=0;yc=0;zc=0;a=1;b=1;c=1;
    // 初始误差
    int L = data_x.size();
    float err = 0;
    for (int i = 0; i < L; i++) {
        // 代价函数
        err += abs((data_x[i] - xc) * (data_x[i] - xc) / (a * a) +
                   (data_y[i] - yc) * (data_y[i] - yc) / (b * b) +
                   (data_z[i] - zc) * (data_z[i] - zc) / (c * c) - 1);
    }
    printf("xc = %f yc = %f zc = %f, a = %f b = %f c= %f,init InitErr = %f\n",
           xc, yc, zc, a, b, c, err);

    // 开始计算
    float xc_last = xc;
    float yc_last = yc;
    float zc_last = zc;
    float a_last = a;
    float b_last = b;
    float c_last = c;
    float err_last = err;
    float r[6], xc_new, yc_new, zc_new, a_new, b_new, c_new, err_new;

    for (int i = 0; i < 1000; i++) {
        // 产生随机扰动 -0.5~0.5
        for (float &i : r) {
            i = (rand() % 100) * 0.01f - 0.5f;
        }
        xc_new = xc_last + r[0];
        yc_new = yc_last + r[1];
        zc_new = zc_last + r[2];
        a_new = abs(a_last + r[3]);
        b_new = abs(b_last + r[4]);
        c_new = abs(c_last + r[5]);
        err_new = 0;
        for (int j = 0; j < L; j++) {
            err_new += abs((data_x[j] - xc_new) * (data_x[j] - xc_new) / (a_new * a_new) +
                           (data_y[j] - yc_new) * (data_y[j] - yc_new) / (b_new * b_new) +
                           (data_z[j] - zc_new) * (data_z[j] - zc_new) / (c_new * c_new) - 1);
        }
        if (err_new < err_last) {
            xc_last = xc_new;
            yc_last = yc_new;
            zc_last = zc_new;
            a_last = a_new;
            b_last = b_new;
            c_last = c_new;
            err_last = err_new;
        }
    }

    printf("xc = %f yc = %f zc = %f, a = %f b = %f c= %f,last InitErr = %f\n",
           xc_last, yc_last, zc_last, a_last, b_last, c_last, err_last);
    float avr = (a_last + b_last + c_last) / 3;
    printf("mx = (mx - %f)*%f\n",xc_last,a_last/avr);
    printf("my = (my - %f)*%f\n",yc_last,b_last/avr);
    printf("mz = (mz - %f)*%f\n",zc_last,c_last/avr);
    return err_last;
}

// 地磁校准
int main() {

    srand((int) time(nullptr));  // 产生随机种子  把0换成NULL也行
    vector<float> data_x, data_y, data_z;
    // 读取数据
    load_csv(data_x, data_y, data_z);
    //校准,返回最终误差值
    float err = calib_mag(data_x, data_y, data_z);
    cout << err << endl;

    return 0;
}

相关文章

  • C++ 地磁校准

    地磁标定校准

  • 地磁车检器外壳@车检器外壳加工@地磁车检器外壳生产厂家

    地磁车检器外壳@车检器外壳加工@地磁车检器外壳生产厂家 地磁车检器外壳产品介绍 地磁车检器外壳具有良好的综合性能,...

  • 地磁灵魂

    来简书几个月了,习惯于写写停停,走走看看,读到一些这样的句子: “一个女人最好的生活状态,不是事业有成,不是婚姻生...

  • 07_Geoist的magmod模块模型更新

    内容摘要:Geoist的地磁模型模块支持多种地磁场模型的球谐系数解算,magmod模块目前支持8种全球地磁模型场模...

  • 校准

    只有不断画线才能看出哪条是歪的。

  • 校准

    人把时间用在了什么地方,未来就在什么地方。所谓一分耕耘一分收获。 每个人的时间是有限的,所以时间管理至关重要,与前...

  • ROS机器人底盘(25)-PIBOT的IMU校准

    校准里程计 首先按照ROS机器人底盘(11)-PIBOT的控制及校准校准好里程计 校准IMU 1.启动imu br...

  • weex-25-storage模块

    本节学习目标 使用组件storage缓存数据到本地磁盘 使用组件storage从本地磁盘读取数据 如何删除键值对 ...

  • Topic 14. 临床预测模型之校准曲线 (Calibrati

    点击关注,桓峰基因 前言 Calibration curve,直译过来就是校准曲线或校准图。其实,校准曲线就是实际...

  • 传感器之地磁

    地磁传感器 原理 1. 地磁传感器的应用 健身计划(step-counter)导航应用、盲区导航(过隧道,地下商场...

网友评论

      本文标题:C++ 地磁校准

      本文链接:https://www.haomeiwen.com/subject/dzgxgltx.html