发表于《开源一块飞控SS0》
tmn_A作者
8个月29天前修改于 8个月29天前IP:广东
948798
2楼
void sculm_err_count(float dv_sculm[3], float dv_m[SAMPLE_COUNT][3], float dtheta[SAMPLE_COUNT][3], ...)
{
    va_list valist;
	va_start(valist, dtheta);
    float result_buff[5][3] = {0};
    for(uint8_t i = 0;i < SAMPLE_COUNT-1;i++)
    {
        for(uint8_t j = i+1;j < SAMPLE_COUNT;j++)
        {
            scalar_mult(result_buff[1], (float)va_arg(valist, double), vector_add(result_buff[2], 2, cross_product(result_buff[3], dtheta[i], dv_m[j]), \
                                                                      cross_product(result_buff[4], dv_m[i], dtheta[j])));
            for(uint8_t k = 0;k < 3;k++)result_buff[0][k] += result_buff[1][k];
        }
    }
    memcpy(dv_sculm, result_buff[0], 12);
    va_end(valist);
}

void velocity_position_update(void)
{
    //获取三次姿态数据进行一次多子样速度更新,现在是三子样
    static uint8_t state = 0;

    static float dv_sfm[3] = {0};//比力(测量加速度)引起的速度增量
    static float dv_g[3] = {0};//重力引起的速度增量,以及实验测得的偏差,惯性离心力、科里奥利力不考虑,地面参考系

    static float dv_m[SAMPLE_COUNT][3] = {0};//比力积分
    static float dtheta[SAMPLE_COUNT][3] = {0};//角速度积分
    static float dv_rotm[3] = {0};//旋转效应补偿
    static float dv_sculm[3] = {0};//划桨效应补偿

    static float dv_m_last[2][3] = {0};//上次和上上次的dv_m
    static float dtheta_last[2][3] = {0};//上次和上上次的dtheta

    static float result_buff[4][3];
    
    //这里用于获取多次数据,用于划桨效应补偿
    for(uint8_t i = 0;i < 3;i++)
    {
        dv_m[state][i] = ins.acc[i]*dt_us/1000000.0f;
        dtheta[state][i] = ins.gyro[i]*dt_us/1000000.0f;
    }
    //更新重力引起的速度增量
    dv_g[2] += -ins.g*dt_us/1000000.0f;
    //记录时间
    ins.v_dt_us += dt_us;
    state ++;
    //速度更新
    if(state >= SAMPLE_COUNT)
    {
        //更新划桨补偿项1
        sculm_err_count(dv_sculm, dv_m, dtheta, K1, K2, K2);
        //将三个子样加和,dv_m[0],dtheta[0]本身有数据,所以不用vector_add
        for(uint8_t i = 1;i < SAMPLE_COUNT;i++)
        {
            for(uint8_t j = 0;j < 3;j++)
            {
                dv_m[0][j] += dv_m[i][j];
                dtheta[0][j] += dtheta[i][j];
            }
        }
        //更新旋转补偿项
        scalar_mult(dv_rotm, 0.5, cross_product(result_buff[0], dtheta[0], dv_m[0]));
        //更新划桨补偿项2
        scalar_mult(result_buff[0], P, vector_add(result_buff[1], 2, cross_product(result_buff[2], dtheta_last[0], dv_m[0]), \
                                                                     cross_product(result_buff[3], dv_m_last[0], dtheta[0])));
        for(uint8_t i = 0;i < 3;i++)dv_sculm[i] += result_buff[0][i];
        scalar_mult(result_buff[0], Q, vector_add(result_buff[1], 2, cross_product(result_buff[2], dtheta_last[1], dv_m[0]), \
                                                                     cross_product(result_buff[3], dv_m_last[1], dtheta[0])));
        for(uint8_t i = 0;i < 3;i++)dv_sculm[i] += result_buff[0][i];                                                           
        //更新固联坐标系中速度增量(比力引起速度补偿量)
        vector_add(dv_sfm, 3, dv_m[0], dv_rotm, dv_sculm);
        //更新地面参考系速度
        vector_add(result_buff[0], 3, ins.velocity, left_mult(result_buff[1], ins.attitude_matrix, dv_sfm), dv_g);
        memcpy(ins.velocity, result_buff[0], 12);
        //记录dv_m和dtheta
        vector_add(dv_m_last[1], 1, dv_m_last[0]);
        vector_add(dv_m_last[0], 1, dv_m[0]);
        vector_add(dtheta_last[1], 1, dtheta_last[0]);
        vector_add(dtheta_last[0], 1, dtheta[0]);
        //记录v
        vector_add(ins.velocity_last, 1, ins.velocity);
        //位置更新,梯形积分
        for(uint8_t i = 0;i < 3;i++)
        {
            ins.position[i] += (ins.velocity_last[i]+ins.velocity[i])*ins.v_dt_us/2000000.0f;
        }
        //归零重力增量
        dv_g[2] = 0;
        //归零状态变量
        state = 0;
        //归零速度更新时间
        ins.v_dt_us = 0;
    }
}

这里是纯惯导部分速度位置更新算法,来自INSS0的inertial_navigation.c,划桨补偿较为复杂我就拿出来了。可以看到这里有挺多宏定义,不过不用管,可以看工程。我是每次获取完数据后执行这个函数,在串口中断里,并不是定时中断,所以用了个时间变量,虽然每次获取完数据的时间间隔差不多,但这样还是严谨些。这里是结合了前两次数据的优化三子样,算法可以看这篇算法、代码与测试(完),不过呢,这确实有点杀鸡用牛刀了,我开始也不了解,只是抄算法,最近也在学习,实际上这种低成本MEMS用优化二子样就够了。总之每获取三个数据,就开始计算旋转补偿和划桨补偿,进而积分速度,再梯形积分位置,最后做一些重力增量,状态变量,更新时间等等的归零。

评论
2
文号 / 948798

百炼成钢
名片专栏发私信
学术分 0
总主题 15 帖总回复 172 楼拥有证书:进士 机友 笔友
注册于 2020/08/28 12:52:17最后登录 2026/10/30 21:53:39
主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:广东

个人简介

辰星引力工作室成员,火箭爱好者,嵌入式爱好者,物理爱好者,还有亚雷斯塔克劳利是我老婆。

笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的