RM赛事C型板九轴IMU解算(4)(卡尔曼滤波)

由于昨天测试了一些,程序写完之后跳动很大,所以借助网上的一些文章结合AI,给原来的数据读取进行了卡尔曼滤波,但是这一板有好多问题,比经我卡尔曼滤波也是第一次接触,做到不是很好

现在的主要问题是角度反馈有些慢,我打算后续加上FreeRTOS和DMA再看看

我就不给大家讲卡尔曼滤波了,个人认为学的也不通透,所以直接奉上代码,希望大家可以查证、

cpp 复制代码
//这个是。c文件

#include <string.h>
#include <math.h>
#include "KALMAN.h"

// 状态向量:[q0, q1, q2, q3, bgx, bgy, bgz]
float state[7];

// 状态协方差矩阵 P (7x7)
float P[49];

// 过程噪声协方差矩阵 Q (7x7)
float Q[49];

// 观测噪声协方差矩阵 R (6x6):3个加速度计和3个磁力计
float R[36];

// 状态转换矩阵 F (7x7)
float F[49];

// 观测矩阵 H (6x7)
float H[42];

// 卡尔曼增益 K (7x6)
float K[42];

// 预测状态
float state_pred[7];

// 预测协方差
float P_pred[49];

// 残差
float y[6];

// S = H*P*H^T + R
float S[36];

// 临时矩阵
float temp_matrix[49];
float S_inv[36];

// 过滤后的输出数据
float filtered_gyro[3];  // 修正后的角速度
float filtered_acc[3];   // 修正后的加速度
float filtered_mag[3];   // 修正后的磁场

// 四元数乘法
void quaternion_multiply(float *q1, float *q2, float *result) {
    result[0] = q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3];
    result[1] = q1[0]*q2[1] + q1[1]*q2[0] + q1[2]*q2[3] - q1[3]*q2[2];
    result[2] = q1[0]*q2[2] - q1[1]*q2[3] + q1[2]*q2[0] + q1[3]*q2[1];
    result[3] = q1[0]*q2[3] + q1[1]*q2[2] - q1[2]*q2[1] + q1[3]*q2[0];
}

// 四元数归一化
void quaternion_normalize(float *q) {
    float norm = sqrtf(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
    if (norm > 1e-6f) {
        q[0] /= norm;
        q[1] /= norm;
        q[2] /= norm;
        q[3] /= norm;
    }
}

// 四元数共轭
void quaternion_conjugate(float *q, float *result) {
    result[0] = q[0];
    result[1] = -q[1];
    result[2] = -q[2];
    result[3] = -q[3];
}

// 用四元数旋转向量
void quaternion_rotate_vector(float *q, float *v, float *result) {
    float q_vec[4] = {0, v[0], v[1], v[2]};
    float q_conj[4];
    quaternion_conjugate(q, q_conj);
    
    float temp[4];
    quaternion_multiply(q, q_vec, temp);
    quaternion_multiply(temp, q_conj, temp);
    
    result[0] = temp[1] / temp[0];
    result[1] = temp[2] / temp[0];
    result[2] = temp[3] / temp[0];
}

// 矩阵乘法 C = A * B
void matrix_multiply(float *A, float *B, float *C, int A_rows, int A_cols, int B_cols) {
    memset(C, 0, A_rows * B_cols * sizeof(float));
    for (int i = 0; i < A_rows; i++) {
        for (int j = 0; j < B_cols; j++) {
            for (int k = 0; k < A_cols; k++) {
                C[i * B_cols + j] += A[i * A_cols + k] * B[k * B_cols + j];
            }
        }
    }
}

// 矩阵转置 B = A^T
void matrix_transpose(float *A, float *B, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            B[j * rows + i] = A[i * cols + j];
        }
    }
}

// 3x3矩阵求逆 (使用伴随矩阵法)
void matrix_inv_3x3(float *A, float *A_inv) {
    float det = A[0] * (A[4] * A[8] - A[5] * A[7])
               - A[1] * (A[3] * A[8] - A[5] * A[6])
               + A[2] * (A[3] * A[7] - A[4] * A[6]);
    
    if (fabsf(det) < 1e-6f) {
        memset(A_inv, 0, 9 * sizeof(float));
        return;
    }
    
    float inv_det = 1.0f / det;
    A_inv[0] = (A[4] * A[8] - A[5] * A[7]) * inv_det;
    A_inv[1] = (A[2] * A[7] - A[1] * A[8]) * inv_det;
    A_inv[2] = (A[1] * A[5] - A[2] * A[4]) * inv_det;
    A_inv[3] = (A[5] * A[6] - A[3] * A[8]) * inv_det;
    A_inv[4] = (A[0] * A[8] - A[2] * A[6]) * inv_det;
    A_inv[5] = (A[2] * A[3] - A[0] * A[5]) * inv_det;
    A_inv[6] = (A[3] * A[7] - A[4] * A[6]) * inv_det;
    A_inv[7] = (A[1] * A[6] - A[0] * A[7]) * inv_det;
    A_inv[8] = (A[0] * A[4] - A[1] * A[3]) * inv_det;
}

// 6x6矩阵求逆 (使用分块法)
int matrix_inv_6x6(float *A, float *A_inv) {
    // 使用高斯消元法求逆
    float temp[72]; // 6x12 临时矩阵 [A|I]
    
    // 复制A到左边,单位矩阵到右边
    memset(temp, 0, 72 * sizeof(float));
    for (int i = 0; i < 6; i++) {
        for (int j = 0; j < 6; j++) {
            temp[i * 12 + j] = A[i * 6 + j];
        }
        temp[i * 12 + 6 + i] = 1.0f;
    }
    
    // 高斯消元
    for (int col = 0; col < 6; col++) {
        // 找主元
        int pivot_row = col;
        float max_val = fabsf(temp[col * 12 + col]);
        for (int row = col + 1; row < 6; row++) {
            float val = fabsf(temp[row * 12 + col]);
            if (val > max_val) {
                max_val = val;
                pivot_row = row;
            }
        }
        
        if (max_val < 1e-6f) return -1; // 奇异矩阵
        
        // 交换行
        if (pivot_row != col) {
            for (int j = 0; j < 12; j++) {
                float tmp = temp[col * 12 + j];
                temp[col * 12 + j] = temp[pivot_row * 12 + j];
                temp[pivot_row * 12 + j] = tmp;
            }
        }
        
        // 归一化主行
        float pivot = temp[col * 12 + col];
        for (int j = 0; j < 12; j++) {
            temp[col * 12 + j] /= pivot;
        }
        
        // 消元
        for (int row = 0; row < 6; row++) {
            if (row != col) {
                float factor = temp[row * 12 + col];
                for (int j = 0; j < 12; j++) {
                    temp[row * 12 + j] -= factor * temp[col * 12 + j];
                }
            }
        }
    }
    
    // 提取逆矩阵
    for (int i = 0; i < 6; i++) {
        for (int j = 0; j < 6; j++) {
            A_inv[i * 6 + j] = temp[i * 12 + 6 + j];
        }
    }
    
    return 0;
}

// 矩阵减法 C = A - B
void matrix_subtract(float *A, float *B, float *C, int rows, int cols) {
    for (int i = 0; i < rows * cols; i++) {
        C[i] = A[i] - B[i];
    }
}

// 矩阵加法 C = A + B
void matrix_add(float *A, float *B, float *C, int rows, int cols) {
    for (int i = 0; i < rows * cols; i++) {
        C[i] = A[i] + B[i];
    }
}

// 矩阵标量乘法 A = A * scalar
void matrix_scale(float *A, float scalar, int rows, int cols) {
    for (int i = 0; i < rows * cols; i++) {
        A[i] *= scalar;
    }
}

// 初始状态
void init_state(float initial_q[4], float initial_bg[3]) {
    // 初始化状态向量
    memcpy(state, initial_q, 4 * sizeof(float));
    memcpy(state + 4, initial_bg, 3 * sizeof(float));
    
    // 初始化协方差矩阵 P (对角矩阵)
    memset(P, 0, 49 * sizeof(float));
    P[0] = 0.01f;  P[8] = 0.01f;   P[16] = 0.01f;  P[24] = 0.01f;  // q的方差
    P[32] = 0.01f; P[40] = 0.01f;  P[48] = 0.01f;                  // bg的方差
    
    // 初始化过程噪声协方差 Q
    memset(Q, 0, 49 * sizeof(float));
    Q[0] = 0.001f;  Q[8] = 0.001f;   Q[16] = 0.001f;  Q[24] = 0.001f;   // q的噪声
    Q[32] = 0.0001f; Q[40] = 0.0001f; Q[48] = 0.0001f;                 // bg的噪声
    
    // 初始化观测噪声协方差 R (对角矩阵)
    memset(R, 0, 36 * sizeof(float));
    R[0] = 0.1f;  R[7] = 0.1f;  R[14] = 0.1f;   // 加速度计噪声
    R[21] = 0.1f; R[28] = 0.1f; R[35] = 0.1f;   // 磁力计噪声
}

// 计算状态转移矩阵F (雅可比矩阵)
void compute_F_matrix(float *q, float *gyro, float dt) {
    // F = I + dt * Jf
    memset(F, 0, 49 * sizeof(float));
    
    // 单位矩阵
    for (int i = 0; i < 7; i++) {
        F[i * 7 + i] = 1.0f;
    }
    
    // 四元数动力学雅可比 (左上4x4块)
    // dq/dt = 0.5 * q * omega
    float half_dt = 0.5f * dt;
    F[0] = 1.0f;
    F[1] = -half_dt * gyro[0];
    F[2] = -half_dt * gyro[1];
    F[3] = -half_dt * gyro[2];
    
    F[7] = half_dt * gyro[0];
    F[8] = 1.0f;
    F[10] = half_dt * gyro[2];
    F[11] = -half_dt * gyro[1];
    
    F[14] = half_dt * gyro[1];
    F[17] = 1.0f;
    F[18] = -half_dt * gyro[2];
    F[19] = half_dt * gyro[0];
    
    F[21] = half_dt * gyro[2];
    F[24] = half_dt * gyro[1];
    F[25] = 1.0f;
    F[26] = -half_dt * gyro[0];
    
    // 四元数对陀螺仪偏置的导数 (左上4x3块)
    F[4] = -half_dt;
    F[11] = -half_dt;
    F[18] = -half_dt;
    F[25] = -half_dt;
    
    // 陀螺仪偏置保持不变 (右下3x3块)
    F[32] = 1.0f; F[33] = 0; F[34] = 0;
    F[39] = 0;     F[40] = 1.0f; F[41] = 0;
    F[46] = 0;     F[47] = 0; F[48] = 1.0f;
}

// 计算观测矩阵H (雅可比矩阵)
void compute_H_matrix(float *q, float ref_mag[3]) {
    memset(H, 0, 42 * sizeof(float));
    
    float q0 = q[0], q1 = q[1], q2 = q[2], q3 = q[3];
    
    // 加速度计观测对四元数的导数 (3x4块)
    // 期望加速度是 [0, 0, 0, -1] 经过四元数旋转
    H[0] = 2 * q2;
    H[1] = 2 * q3;
    H[2] = 2 * q0;
    H[3] = 2 * q1;
    
    H[7] = -2 * q1;
    H[8] = 2 * q0;
    H[9] = -2 * q3;
    H[10] = 2 * q2;
    
    H[14] = -2 * q0;
    H[15] = -2 * q3;
    H[16] = 2 * q2;
    H[17] = 2 * q1;
    
    // 磁力计观测对四元数的导数 (3x4块)
    float mx = ref_mag[0], my = ref_mag[1], mz = ref_mag[2];
    
    H[21] = 2 * (mx * q2 + my * q3 + mz * q0);
    H[22] = 2 * (mx * q3 - my * q0 + mz * q1);
    H[23] = 2 * (-mx * q0 + my * q1 + mz * q2);
    H[24] = 2 * (mx * q1 - my * q2 + mz * q3);
    
    H[28] = 2 * (mx * q3 + my * q0 - mz * q1);
    H[29] = 2 * (mx * q2 - my * q1 - mz * q0);
    H[30] = 2 * (mx * q1 + my * q2 + mz * q3);
    H[31] = 2 * (-mx * q0 - my * q3 + mz * q2);
    
    H[35] = 2 * (-mx * q0 + my * q1 + mz * q2);
    H[36] = 2 * (-mx * q1 - my * q2 + mz * q3);
    H[37] = 2 * (mx * q2 - my * q3 - mz * q0);
    H[38] = 2 * (mx * q3 + my * q2 + mz * q1);
}

// 预测步骤
void predict(float gyro[3], float dt) {
    // 1. 预测状态
    // 构造旋转四元数 dq = [cos(theta/2), sin(theta/2)*omega/|omega|]
    
    // 单位转换:deg/s -> rad/s
    float gyro_rad[3] = {
        gyro[0] * 0.0174532925f,  // * PI/180
        gyro[1] * 0.0174532925f,
        gyro[2] * 0.0174532925f
    };
    
    float omega_sq = gyro_rad[0]*gyro_rad[0] + gyro_rad[1]*gyro_rad[1] + gyro_rad[2]*gyro_rad[2];
    float theta = sqrtf(omega_sq) * dt;
    
    float dq[4];
    if (theta > 1e-6f) {
        float half_sin = sinf(theta / 2);
        float inv_theta = half_sin / theta;
        dq[0] = cosf(theta / 2);
        dq[1] = gyro_rad[0] * inv_theta;
        dq[2] = gyro_rad[1] * inv_theta;
        dq[3] = gyro_rad[2] * inv_theta;
    } else {
        dq[0] = 1.0f;
        dq[1] = 0;
        dq[2] = 0;
        dq[3] = 0;
    }
    
    // 四元数乘法更新姿态
    float q_new[4];
    quaternion_multiply(state, dq, q_new);
    quaternion_normalize(q_new);
    memcpy(state_pred, q_new, 4 * sizeof(float));
    
    // 陀螺仪偏置保持不变
    memcpy(state_pred + 4, state + 4, 3 * sizeof(float));
    
    // 2. 计算状态转移矩阵 F
    compute_F_matrix(state, gyro_rad, dt);
    
    // 3. 预测协方差 P_pred = F * P * F^T + Q
    float F_transpose[49];
    matrix_transpose(F, F_transpose, 7, 7);
    
    float temp[49];
    matrix_multiply(F, P, temp, 7, 7, 7);
    matrix_multiply(temp, F_transpose, P_pred, 7, 7, 7);
    
    matrix_add(P_pred, Q, P_pred, 7, 7);
    
    // 4. 更新状态和协方差
    memcpy(state, state_pred, 7 * sizeof(float));
    memcpy(P, P_pred, 49 * sizeof(float));
}

// 更新步骤
void update(float acc[3], float mag[3], float ref_mag[3]) {
    // 1. 计算期望观测值
    float q_conj[4];
    quaternion_conjugate(state, q_conj);
    
    // 期望加速度计测量 (重力向量 [0,0,0,-1])
    float gravity[4] = {0, 0, 0, -1};
    float expected_acc[4];
    quaternion_multiply(state, gravity, expected_acc);
    quaternion_multiply(expected_acc, q_conj, expected_acc);
    
    float h_acc[3] = {
        expected_acc[1] / expected_acc[0],
        expected_acc[2] / expected_acc[0],
        expected_acc[3] / expected_acc[0]
    };
    
    // 期望磁力计测量
    float ref_mag_q[4] = {0, ref_mag[0], ref_mag[1], ref_mag[2]};
    float expected_mag[4];
    quaternion_multiply(state, ref_mag_q, expected_mag);
    quaternion_multiply(expected_mag, q_conj, expected_mag);
    
    float h_mag[3] = {
        expected_mag[1] / expected_mag[0],
        expected_mag[2] / expected_mag[0],
        expected_mag[3] / expected_mag[0]
    };
    
    // 2. 计算残差 y = z - h
    float z[6] = {acc[0], acc[1], acc[2], mag[0], mag[1], mag[2]};
    float h[6] = {h_acc[0], h_acc[1], h_acc[2], h_mag[0], h_mag[1], h_mag[2]};
    
    for (int i = 0; i < 6; i++) {
        y[i] = z[i] - h[i];
    }
    
    // 3. 计算观测矩阵 H
    compute_H_matrix(state, ref_mag);
    
    // 4. 计算 S = H * P * H^T + R
    float H_transpose[42];
    matrix_transpose(H, H_transpose, 6, 7);
    
    float temp1[36];
    matrix_multiply(H, P, temp1, 6, 7, 7);
    matrix_multiply(temp1, H_transpose, S, 6, 7, 6);
    
    matrix_add(S, R, S, 6, 6);
    
    // 5. 计算 S 的逆
    if (matrix_inv_6x6(S, S_inv) != 0) {
        return; // 矩阵奇异,跳过更新
    }
    
    // 6. 计算卡尔曼增益 K = P * H^T * S^-1
    float temp2[42];
    matrix_multiply(P, H_transpose, temp2, 7, 7, 6);
    matrix_multiply(temp2, S_inv, K, 7, 6, 6);
    
    // 7. 更新状态 x = x + K * y
    for (int i = 0; i < 7; i++) {
        float delta = 0;
        for (int j = 0; j < 6; j++) {
            delta += K[i * 6 + j] * y[j];
        }
        state[i] += delta;
    }
    
    // 8. 归一化四元数
    quaternion_normalize(state);
    
    // 9. 更新协方差 P = (I - K * H) * P_pred
    float KH[49];
    matrix_multiply(K, H, KH, 7, 6, 7);
    
    float I_KH[49];
    memset(I_KH, 0, 49 * sizeof(float));
    for (int i = 0; i < 7; i++) {
        I_KH[i * 7 + i] = 1.0f;
        for (int j = 0; j < 7; j++) {
            I_KH[i * 7 + j] -= KH[i * 7 + j];
        }
    }
    
    matrix_multiply(I_KH, P_pred, P, 7, 7, 7);
}

// 获取过滤后的传感器数据
void get_filtered_data(float *out_gyro, float *out_acc, float *out_mag) {
    // 修正后的角速度 = 原始角速度 - 估计的偏置
    // 注意:这里保存的是最后一次 predict() 使用的原始陀螺仪数据
    // 如果需要原始值,需要在 predict 中保存
    
    // 修正后的加速度 = 基于估计姿态的重力补偿
    float q_conj[4];
    quaternion_conjugate(state, q_conj);
    float gravity[4] = {0, 0, 0, -1};
    float expected_gravity[4];
    quaternion_multiply(state, gravity, expected_gravity);
    quaternion_multiply(expected_gravity, q_conj, expected_gravity);
    
    // 过滤后的加速度 = 原始加速度 - 重力分量
    // 注意:这里需要传入原始加速度,或保存原始值
    
    // 修正后的磁场 = 基于估计姿态的磁场
    // 注意:这里需要传入原始磁场,或保存原始值
    
    // 简化版本:直接返回当前估计的姿态对应的期望值
    out_acc[0] = expected_gravity[1] / expected_gravity[0];
    out_acc[1] = expected_gravity[2] / expected_gravity[0];
    out_acc[2] = expected_gravity[3] / expected_gravity[0];
}

// 获取修正后的陀螺仪数据(扣除偏置)
// 输入和输出都是 deg/s
void get_filtered_gyro(float *raw_gyro, float *out_gyro) {
    // state[4-6] 估计的偏置单位是 rad/s,需要转换为 deg/s
    float bgx_deg = state[4] * 57.2957795f;  // rad/s -> deg/s
    float bgy_deg = state[5] * 57.2957795f;
    float bgz_deg = state[6] * 57.2957795f;
    
    out_gyro[0] = raw_gyro[0] - bgx_deg;  // 扣除x轴偏置
    out_gyro[1] = raw_gyro[1] - bgy_deg;  // 扣除y轴偏置
    out_gyro[2] = raw_gyro[2] - bgz_deg;  // 扣除z轴偏置
}

// 获取重力补偿后的加速度
void get_filtered_acc(float *raw_acc, float *out_acc) {
    float q_conj[4];
    quaternion_conjugate(state, q_conj);
    
    // 计算当前姿态下的重力向量
    float gravity[4] = {0, 0, 0, -1};  // 世界坐标系重力向下
    float expected_gravity[4];
    quaternion_multiply(state, gravity, expected_gravity);
    quaternion_multiply(expected_gravity, q_conj, expected_gravity);
    
    float gx = expected_gravity[1] / expected_gravity[0];
    float gy = expected_gravity[2] / expected_gravity[0];
    float gz = expected_gravity[3] / expected_gravity[0];
    
    // 过滤后的加速度 = 原始加速度 - 重力分量
    out_acc[0] = raw_acc[0] - gx;
    out_acc[1] = raw_acc[1] - gy;
    out_acc[2] = raw_acc[2] - gz;
}

// 获取航向修正后的磁场
void get_filtered_mag(float *raw_mag, float *ref_mag, float *out_mag) {
    float q_conj[4];
    quaternion_conjugate(state, q_conj);
    
    // 计算期望的磁场向量
    float ref_mag_q[4] = {0, ref_mag[0], ref_mag[1], ref_mag[2]};
    float expected_mag[4];
    quaternion_multiply(state, ref_mag_q, expected_mag);
    quaternion_multiply(expected_mag, q_conj, expected_mag);
    
    out_mag[0] = expected_mag[1] / expected_mag[0];
    out_mag[1] = expected_mag[2] / expected_mag[0];
    out_mag[2] = expected_mag[3] / expected_mag[0];

这个是.h文件

cpp 复制代码
#ifndef KALMAN_H
#define KALMAN_H

#include <stdint.h>

// 全局状态向量:[q0, q1, q2, q3, bgx, bgy, bgz]
extern float state[7];

// 全局协方差矩阵
extern float P[49];
extern float Q[49];
extern float R[36];
extern float F[49];
extern float H[42];
extern float K[42];
extern float state_pred[7];
extern float P_pred[49];
extern float y[6];
extern float S[36];

// 过滤后的输出数据
extern float filtered_gyro[3];  // 修正后的角速度
extern float filtered_acc[3];   // 修正后的加速度
extern float filtered_mag[3];   // 修正后的磁场

// ========== 四元数运算函数 ==========
void quaternion_multiply(float *q1, float *q2, float *result);
void quaternion_normalize(float *q);
void quaternion_conjugate(float *q, float *result);
void quaternion_rotate_vector(float *q, float *v, float *result);

// ========== 矩阵运算函数 ==========
void matrix_multiply(float *A, float *B, float *C, int A_rows, int A_cols, int B_cols);
void matrix_transpose(float *A, float *B, int rows, int cols);
void matrix_inv_3x3(float *A, float *A_inv);
int matrix_inv_6x6(float *A, float *A_inv);
void matrix_subtract(float *A, float *B, float *C, int rows, int cols);
void matrix_add(float *A, float *B, float *C, int rows, int cols);
void matrix_scale(float *A, float scalar, int rows, int cols);

// ========== 卡尔曼滤波核心函数 ==========
void init_state(float initial_q[4], float initial_bg[3]);
void compute_F_matrix(float *q, float *gyro, float dt);
void compute_H_matrix(float *q, float ref_mag[3]);
void predict(float gyro[3], float dt);
void update(float acc[3], float mag[3], float ref_mag[3]);

// ========== 获取过滤后的传感器数据 ==========
// 获取修正后的陀螺仪(扣除估计的偏置)
void get_filtered_gyro(float *raw_gyro, float *out_gyro);

// 获取重力补偿后的加速度(去除重力分量)
void get_filtered_acc(float *raw_acc, float *out_acc);

// 获取航向修正后的磁场
void get_filtered_mag(float *raw_mag, float *ref_mag, float *out_mag);

#endif

这两个分别是写的KALMAN.c和.h文件

我的这个程序只是对于咱们前面的IMU数据的读取

然后再main.c中怎么用在下面

先定义初始化的矩阵函数

cpp 复制代码
float initial_q[4] = {1, 0, 0, 0};
    quaternion_normalize(initial_q);
    init_state(initial_q, (float[3]){0, 0, 0});
    
    // 参考磁场(根据实际位置调整)
    float ref_mag[3] = {0.65f, -0.057f, -0.76f};
	
	float filtered_gyro[3], filtered_acc[3];

然后用函数就行

cpp 复制代码
float delay_time = 0.01f;
	  
	   predict(gyro, 0.01f);
       update(accel, mag, ref_mag);
	  
	    get_filtered_gyro(gyro, filtered_gyro);
        get_filtered_acc(accel, filtered_acc);
	  
相关推荐
盛世宏博北京2 小时前
高效环境管控:楼宇机房以太网温湿度精准监测系统方案
开发语言·数据库·php·以太网温湿度变送器
IT猿手2 小时前
六种智能优化算法(NOA、MA、PSO、GA、ZOA、SWO)求解23个基准测试函数(含参考文献及MATLAB代码)
开发语言·算法·matlab·无人机·无人机路径规划·最新多目标优化算法
We་ct2 小时前
LeetCode 151. 反转字符串中的单词:两种解法深度剖析
前端·算法·leetcode·typescript
gfdhy3 小时前
【C++实战】多态版商品库存管理系统:从设计到实现,吃透面向对象核心
开发语言·数据库·c++·microsoft·毕业设计·毕设
忧郁的橙子.3 小时前
26期_01_Pyhton文件的操作
开发语言·python
余瑜鱼鱼鱼3 小时前
线程和进程的区别和联系
java·开发语言·jvm
yinmaisoft3 小时前
JNPF 表单模板实操:高效复用表单设计指南
前端·javascript·html
zzcufo3 小时前
多邻国第五阶段第13部分
java·开发语言·数据库
37方寸3 小时前
前端基础知识(JavaScript)
开发语言·前端·javascript