【视觉SLAM入门】7.2. 从卡尔曼滤波到扩展卡尔曼滤波,引入、代码、原理、实战,C++实现以及全部源码

news2024/9/27 5:57:00

"觇其平生,岂能容物?"

  • 0. 简单认识
  • 1. 公式对比解读
  • 2. 应用举例
  • 3. 解决方案(公式---代码对应)
    • 3.1 初始化
    • 3.2 EKF
      • 3.2.1 预测---状态方程
      • 3.2.2 系统协方差矩阵
      • 3.2.3 预测---系统协方差矩阵
      • 3.2.4 设置测量矩阵
      • 3.2.5 更新---状态变量,卡尔曼增益,状态协方差矩阵
  • 4. 源码
    • 4.1 Extended_kalman_filter.hpp
    • 4.2 main.cpp
    • 4.3 CMakeLists.txt

前置事项: 7.2节将KF进行简单介绍和实现,本节介绍EKF扩展卡尔曼滤波

  • 下边统一将卡尔曼滤波器记作KF,扩展卡尔曼滤波器记作EKF

0. 简单认识

  • KF 假设当前状态只由上一时刻状态决定,但是只使用线性方程对系统进行了建模;
  • 为了能够应用到非线性系统,EKF 利用泰勒展开,并只保留一次项,抛弃高次项,将非线性关系近似为线性关系。

1. 公式对比解读

为了易于理解,这里以噪声为加性噪声为例展开:
在这里插入图片描述

  • EKF主要解决非线性问题。如上是线性和非线性系统的运动方程和观测方程。其中EKF的 f f f z z z 都是非线性的。
  • 上节对KF(线性系统已经做了阐述),而EKF将此时状态 x ^ k \hat x_{k} x^k 非线性的表达式 f f f 在上一时刻的后验估计 x ^ k − 1 \hat x_{k-1} x^k1 利用泰勒公式进行一阶展开,做了线性化,具体推导略,比较简单,直接看KFEKF 的结论对比(大体不变):
    在这里插入图片描述
    其中:
    在这里插入图片描述

对比KF的线性系统:

  1. 状态量 x x x 的先验估计(预测),由线性方程表述,变为非线性表述;
  2. 系统的状态协方差矩阵中的 F F F,在KF中就是状态转移矩阵,而在EKF中求法如上,是 f f f 对各状态量的偏导;
  3. 测量矩阵在EKF中的求法,是 非线性观测函数 h h h 对 各状态量求偏导数;

2. 应用举例

假设场景:

小车从原点出发,做匀速运动;

  • 信息1:车载传感器能每隔 Δ t \Delta t Δt 输出车此时的速度 v t v_t vt w t w_t wt
  • 信息2:在原点有一激光雷达,每隔 Δ t \Delta t Δt 检测得到车辆距离 d t d_t dt

要求:

  • 充分利用以上信息,求出小车每一时刻对应的 x 和 y 坐标 a t a_t at b t b_t bt

3. 解决方案(公式—代码对应)

首先写出系统的观测量,根据题设,可以观测到的量设置如下:
z = [ d t 2 v t w t ] z = \begin{bmatrix}d_t^2 \\ v_t \\ w_t \end{bmatrix} z= dt2vtwt
写出系统的观测量,为了更好利用所有以上信息,设状态量如下:
x = [ x y v x v y ] x = \begin{bmatrix}x \\y \\v_x \\v_y \end{bmatrix} x= xyvxvy

3.1 初始化

这一部分是,在卡尔曼滤波中保持不变只需要初始化操作一次的矩阵,设置P,Q,R的初始值,:

Eigen::VectorXd x_in(x_noise[0]) ;
            EKF.Initialization(x_in) ;

            Eigen::MatrixXd P_in(5, 5) ;
            P_in << 10,  10,   1,    0,           0, 
                    10,  10,   1,    0,           0, 
                    1,   1,    0.1,  0,           0, 
                    0,   0,    0,    pow(10,-8),  0, 
                    0,   0,    0,    0,           pow(10,-8) ;

            EKF.Set_P(P_in) ;

            Eigen::MatrixXd Q_in(5, 5) ;
            Q_in << 0.01,  0.0,   0.0,    0.0,  0.0, 
                    0.0,   0.01,  0.0,    0.0,  0.0, 
                    0.0,   0.0,   0.0001, 0.0,  0.0, 
                    0.0,   0.0,   0.0,    0.01, 0.0, 
                    0.0,   0.0,   0.0,    0.0,  0.01 ;
            EKF.SetQ(Q_in) ;

            //R is provided by Sensor producer, in their datasheet
            Eigen::MatrixXd R_in(3, 3) ;
            R_in << 0.0001, 0,      0, 
                    0,      0.0001, 0,
                    0,      0,      0.0001 ;
            EKF.SetR(R_in) ;

3.2 EKF

3.2.1 预测—状态方程

这里是非线性的方程,对应公式:
x k + 1 = f ( x k ) x_{k+1} = f(x_k) xk+1=f(xk)

代码如下:

void PredictX(double delta_time){
            // x_t prediction
            x_(0) = x_(0) + x_(3) * cos(x_(2)) * delta_time;
            x_(1) = x_(1) + x_(3) * sin(x_(2)) * delta_time;
            x_(2) = x_(2) + x_(4) * delta_time;
            //其余的值理论上不变
        }

3.2.2 系统协方差矩阵

这里是手动状态方程对状态变量求偏导数,对应EKF第二个公式中手动求得的:
F ′ F' F,代码中为了对应将F设置为了A,一样的,是手动求得公式输入的:

	void Set_A(double delta_time){
            double theta = x_(2) ;
            double tmp_v = x_(3) ;
            double sv = -sin(theta)*tmp_v*delta_time ;
            double cv = cos(theta)*tmp_v*delta_time ;
            double st = sin(theta)*delta_time ;
            double ct = cos(theta)*delta_time ;
            A_ = Eigen::MatrixXd(5,5) ;
            //状态方程对状态向量求雅克比矩阵
            A_ << 1.0, 0.0, sv,  ct,  0.0,
                  0.0, 1.0, cv,  st,  0.0, 
                  0.0, 0.0, 1.0, 0.0, delta_time, 
                  0.0, 0.0, 0.0, 1.0, 0.0, 
                  0.0, 0.0, 0.0, 0.0, 1.0;      
        }

3.2.3 预测—系统协方差矩阵

对应公式:
P k = F k − 1 P k − 1 F k − 1 T + Q k − 1 P_{k} = F_{k-1}P_{k-1}F_{k-1}^T + Q_{k-1} Pk=Fk1Pk1Fk1T+Qk1
更新P,代码如下:

        // state covariance matrix for predict x
        void PredictP(){
            P_ = A_ * P_ * A_.transpose() + Q_ ;        
        }

3.2.4 设置测量矩阵

这里是观测方程对状态变量求偏导数,对应EKF第二个公式中手动求得的:
H ′ H' H手动输入代码如下:

        void SetH(){
            H_ = Eigen::MatrixXd(3,5) ;
            //观测方程对状态向量求雅可比矩阵
            H_ << 2*x_(0), 2*x_(1), 0,    0,   0,
                  0,       0,       0,    1,   0,
                  0,       0,       0,    0,   1;
        }

3.2.5 更新—状态变量,卡尔曼增益,状态协方差矩阵

对应所有更新公式,代码如下:其中的入口参数是测量值,z_pre是预测值

        void MeasurementUpdate(Eigen::MatrixXd z){
            Eigen::Vector3d z_pre (pow(x_(0),2) + pow(x_(1), 2), x_(3), x_(4)) ;
            Eigen::MatrixXd S = H_ * P_ * H_.transpose() + R_ ;
            Eigen::MatrixXd K = P_ * H_.transpose() * S.inverse() ;
            x_ = x_ + (K * (z - z_pre)) ;  //观测-预测
            P_ = P_ - K*H_*P_ ;
        }

4. 源码

4.1 Extended_kalman_filter.hpp

#ifndef EXTENDED_KALMAN_FILTER_H
#define EXTENDED_KALMAN_FILTER_H
#include "Eigen/Dense"
#include "matplotlibcpp.h"
#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>
#include <random>

class ExtendedKalmanFilter
{       
    public:
        ExtendedKalmanFilter(){
            is_initialized_ = false ;
        };
        ~ExtendedKalmanFilter();

        void Initialization(Eigen::VectorXd x_in){
            x_ = x_in ;
            is_initialized_ = true ; 
        }

        bool IsInitialized(){
            return this->is_initialized_ ;
        }

        /**********calculate / predict x'************/
        // state transistion matrix for predict x'
        void PredictX(double delta_time){
            // x_t prediction
            x_(0) = x_(0) + x_(3) * cos(x_(2)) * delta_time;
            x_(1) = x_(1) + x_(3) * sin(x_(2)) * delta_time;
            x_(2) = x_(2) + x_(4) * delta_time;
            //其余的值理论上不变
        }

        void Set_A(double delta_time){
            double theta = x_(2) ;
            double tmp_v = x_(3) ;
            double sv = -sin(theta)*tmp_v*delta_time ;
            double cv = cos(theta)*tmp_v*delta_time ;
            double st = sin(theta)*delta_time ;
            double ct = cos(theta)*delta_time ;
            A_ = Eigen::MatrixXd(5,5) ;
            //状态方程对状态向量求雅克比矩阵
            A_ << 1.0, 0.0, sv,  ct,  0.0,
                  0.0, 1.0, cv,  st,  0.0, 
                  0.0, 0.0, 1.0, 0.0, delta_time, 
                  0.0, 0.0, 0.0, 1.0, 0.0, 
                  0.0, 0.0, 0.0, 0.0, 1.0;      
        }
        void Set_P(Eigen::MatrixXd P_in){
            P_ = P_in ;
        }
        // state covariance matrix for predict x
        void PredictP(){
            P_ = A_ * P_ * A_.transpose() + Q_ ;        
        }

        // process covariance matrix for predict x'

        void SetQ(Eigen::MatrixXd Q_in){
            Q_ = Q_in ;
        }

        void SetH(){
            H_ = Eigen::MatrixXd(3,5) ;
            //观测方程对状态向量求雅可比矩阵
            H_ << 2*x_(0), 2*x_(1), 0,    0,   0,
                  0,       0,       0,    1,   0,
                  0,       0,       0,    0,   1;
        }

        void SetR(Eigen::MatrixXd R_in){
            R_ = R_in ;
        }

        void MeasurementUpdate(Eigen::MatrixXd z){
            Eigen::Vector3d z_pre (pow(x_(0),2) + pow(x_(1), 2), x_(3), x_(4)) ;
            Eigen::MatrixXd S = H_ * P_ * H_.transpose() + R_ ;
            Eigen::MatrixXd K = P_ * H_.transpose() * S.inverse() ;
            x_ = x_ + (K * (z - z_pre)) ;  //观测-预测
            P_ = P_ - K*H_*P_ ;
        }

        Eigen::VectorXd GetX(){
            return x_ ;
        }

    private:
        bool is_initialized_ ;    // flag of initialized
        Eigen::VectorXd x_ ;      // state vector
        Eigen::MatrixXd A_ ;      // jacba matrix for P predict
        Eigen::MatrixXd P_ ;      // state covariance matrix
        Eigen::MatrixXd Q_ ;      // process covariance matrix
        Eigen::MatrixXd H_ ;      // mesurement matrix
        Eigen::MatrixXd R_ ;      // mesurement covariance matrix

};
ExtendedKalmanFilter::~ExtendedKalmanFilter()
{
}

#endif 

4.2 main.cpp

#include "extended_kalman_filter.hpp"

namespace plt = matplotlibcpp;

// creat data
void create_data(std::vector<Eigen::VectorXd> &x_stand, 
                std::vector<Eigen::VectorXd> &x_noise, 
                std::vector<Eigen::VectorXd> &measure, 
                int all_data)
{
    double car_speed = 0.1, delta_time = 0.1, car_omega = 0.01;
    bool watch = false ;
    double tmp_x = 0, tmp_y = 0, tmp_theta = 0, tmp_v = 0, tmp_w = 0; //初值0

    std::random_device rd;                             // 用于生成种子
    std::mt19937 random_w(rd());                       // 以随机设备生成的种子初始化Mersenne Twister伪随机数生成器
    std::uniform_real_distribution<> dis(0, 0.01); // 定义一个0-0.01之间的均匀分布

    // inital value
    // first value
    Eigen::VectorXd a(5, 1), a_measure(3, 1) ;
    a << tmp_x, tmp_y, tmp_theta, tmp_v, tmp_w;
    x_stand.push_back(a);
    x_noise = x_stand;
    a_measure << 0.0, 0.0, 0.0 ;
    measure.push_back(a_measure) ;

    for (size_t i = 0; i < all_data; i++)
    { // standard state data
      // x1 = x0 + v*cos(theta)*time ;   v的x分量速度
        tmp_x = x_stand[i](0) + car_speed * cos(x_stand[i](2)) * delta_time;
        tmp_y = x_stand[i](1) + car_speed * sin(x_stand[i](2)) * delta_time;
        tmp_theta = x_stand[i](2) + car_omega * delta_time;
        a << tmp_x, tmp_y, tmp_theta, car_speed, car_omega;
        x_stand.push_back(a);
      // noise measure data
        float speed_noise = car_speed + dis(random_w) * 10; // 原速度0.1 + 一个0-0.1的值
        float omega_noise = car_omega + dis(random_w);
        a_measure(0) = pow(tmp_x, 2) + pow(tmp_y, 2) + dis(random_w)/10 ;
        a_measure(1) = speed_noise ;
        a_measure(2) = omega_noise ;
        measure.push_back(a_measure) ;
  
        // noise state data
        speed_noise = car_speed + dis(random_w) * 10; // 原速度0.1 + 一个0-0.1的值
        omega_noise = car_omega + dis(random_w);

        tmp_x = x_noise[i](0) + speed_noise * cos(x_noise[i](2)) * delta_time;
        tmp_y = x_noise[i](1) + speed_noise * sin(x_noise[i](2)) * delta_time;
        tmp_theta = x_stand[i](2) + omega_noise * delta_time;
        a << tmp_x, tmp_y, tmp_theta, speed_noise, omega_noise;
        x_noise.push_back(a);
    }
    if (watch)
    {
        std::cout << std::fixed; // 输出固定格式
        std::cout.precision(4); // 保留4位小数
        for (size_t i = 0; i < all_data; i++)
        {
            for (size_t j = 0; j < 5; j++)
            {
                    std::cout <<  x_noise[i](j) << "  ";
            }
            std::cout << std::endl ;
        }
    }
    
}

int main(int argc, const char **argv)
{
    int all_data_num = 1000;
    double delta_time = 0.1 ;  //two state vector(1, 5) and one measure vector(1,3)
    std::vector<Eigen::VectorXd> x_stand, x_noise, measure_x; 
    static std::vector<double> vis_x_std, vis_y_std, vis_x_nse, vis_y_nse, vis_x_ekf, vis_y_ekf;
    create_data(x_stand, x_noise, measure_x, all_data_num);

    ExtendedKalmanFilter EKF;
    while (x_noise.size())
    {
        // Initialize kalman filter
        if (!EKF.IsInitialized())
        {
            Eigen::VectorXd x_in(x_noise[0]) ;
            EKF.Initialization(x_in) ;

            Eigen::MatrixXd P_in(5, 5) ;
            P_in << 10,  10,   1,    0,           0, 
                    10,  10,   1,    0,           0, 
                    1,   1,    0.1,  0,           0, 
                    0,   0,    0,    pow(10,-8),  0, 
                    0,   0,    0,    0,           pow(10,-8) ;

            EKF.Set_P(P_in) ;

            Eigen::MatrixXd Q_in(5, 5) ;
            Q_in << 0.01,  0.0,   0.0,    0.0,  0.0, 
                    0.0,   0.01,  0.0,    0.0,  0.0, 
                    0.0,   0.0,   0.0001, 0.0,  0.0, 
                    0.0,   0.0,   0.0,    0.01, 0.0, 
                    0.0,   0.0,   0.0,    0.0,  0.01 ;
            EKF.SetQ(Q_in) ;

            //R is provided by Sensor producer, in their datasheet
            Eigen::MatrixXd R_in(3, 3) ;
            R_in << 0.0001, 0,      0, 
                    0,      0.0001, 0,
                    0,      0,      0.0001 ;
            EKF.SetR(R_in) ;
        }

        //state forward eqution
        EKF.PredictX(delta_time) ;
        EKF.Set_A(delta_time) ; //first update x, the calculate A
        EKF.PredictP() ;        // state convarince matrix
        EKF.SetH() ;            // measurement convarince matrix

        // measurement value
        Eigen::VectorXd z(measure_x[0]) ;
        EKF.MeasurementUpdate(z) ;

        //result
        Eigen::VectorXd x_out = EKF.GetX() ;
        // std::cout << "original output x : " << x_noise[0](0) <<
        //                             " y: " << x_noise[0](1) << std::endl ;
        // std::cout << "ideal   output x : " << x_stand[0](0) <<
        //                             " y: " << x_stand[0](1) << std::endl ;
        // std::cout << "kalman output x : " << x_out(0) <<
        //                             " y: " << x_out(1) << std::endl << std::endl;

        //for painting//
        vis_x_ekf.push_back(x_out(0)) ;
        vis_y_ekf.push_back(x_out(1)) ;
        vis_x_nse.push_back(x_noise[0](0)) ;
        vis_y_nse.push_back(x_noise[0](1)) ;
        vis_x_std.push_back(x_stand[0](0)) ;
        vis_y_std.push_back(x_stand[0](1)) ;

        x_noise.erase(x_noise.begin()) ;
        x_stand.erase(x_stand.begin()) ;
        measure_x.erase(measure_x.begin()) ;
    }

        plt::figure_size(1200, 780);
        plt::plot(vis_x_ekf, vis_y_ekf,"r");
        plt::plot(vis_x_nse, vis_y_nse,"g");
        plt::plot(vis_x_std, vis_y_std,"b");
        plt::title("ekf-red, noise-green, stand-blue");
        plt::save("./basic.png");
    //     //for painting//
    return 0;
}

4.3 CMakeLists.txt

# CMakeLists.txt  
  
# 设置构建类型为 Release  
cmake_minimum_required(VERSION 3.10)  
project(common_kf)  
set(CMAKE_BUILD_TYPE "Debug")
  
set(CMAKE_CXX_STANDARD 14) # 使用 C++14 标准  
  
find_package(PythonLibs REQUIRED)
include_directories(
        ${PYTHON_INCLUDE_DIRS}
)
# 添加当前目录到 include 路径  
include_directories(${PROJECT_SOURCE_DIR}/include)  

# 添加源文件到编译  
add_executable(KalDemo main.cpp)

target_link_libraries(KalDemo
        ${PYTHON_LIBRARIES}
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/985289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

搞懂三极管

三极管的电流放大作用应该算是模拟电路里面的一个难点内容&#xff0c;我想用这几个动画简单的解释下为什么小电流Ib能控制大电流Ic的大小&#xff0c;以及放大电路的原理。 我这里的三极管也叫双极型晶体管,模电的放大电路和数电的简单逻辑电路里面都会用到。有集电极c、基极b…

docker-compose 升级

此方法针对Linux版本生效&#xff0c;请测试有效&#xff1b;记录以方面日后能使用到&#xff1b; ## 安装docker 使用常用命名安装即可, 以下命令安装若提示找不到安装包&#xff0c;直接update 即可。 yum install docker OR apt install docker OR apt install do…

2023 年全国大学生数学建模B题目-多波束测线问题

B题目感觉属于平面几何和立体几何的问题&#xff0c;本质上需要推导几何变换情况&#xff0c;B题目属于有标准答案型&#xff0c;没太大的把握不建议选择&#xff0c;可发挥型不大。 第一问 比较简单&#xff0c;就一个2维平面的问题&#xff0c;但有点没理解&#xff0c;这个…

【2023最新版】腾讯云CODING平台使用教程(Pycharm/命令:本地项目推送到CODING)

目录 一、CODING简介 网址 二、CODING使用 1. 创建项目 2. 创建代码仓库 三、PyCharm&#xff1a;本地项目推送到CODING 1. 管理远程 2. 提交 3. 推送 4. 结果 四、使用命令推送 1. 打开终端 2. 初始化 Git 仓库 3. 添加远程仓库 4. 添加文件到暂存区 5. 提交更…

【代码随想录】Day 48 动态规划9 (打家劫舍Ⅰ Ⅱ Ⅲ)

打家劫舍 https://leetcode.cn/problems/house-robber/ 注意要是i-1没偷&#xff0c;那么dp[i] dp[i-2] nums[i]&#xff0c;而不是dp[i-1]&#xff1a; class Solution { public:int rob(vector<int>& nums) {if (nums.size() 0) return 0;if (nums.size() 1…

【图文并茂】C++介绍之串

1.1串 引子—— ​ 字符串简称为串&#xff0c;串是由字符元素构成的&#xff0c;其中元素的逻辑关系也是一种线性关系。串的处理在计算机非数值处理中占用重要的地位&#xff0c;如信息检索系统&#xff0c;文字编辑等都是以串数据作为处理对象 串是由零个或多个字符组成的…

OSCP系列靶场-Esay-Sumo

OSCP系列靶场-Esay-Sumo 总结 getwebshell : nikto扫描 → 发现shellshock漏洞 → 漏洞利用 → getwebshell 提 权 思 路 : 内网信息收集 → 内核版本较老 →脏牛提权 准备工作 启动VPN 获取攻击机IP → 192.168.45.194 启动靶机 获取目标机器IP → 192.168.190.87 信息收…

【LeetCode75】第四十九题 数组中的第K个最大元素

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目很简单&#xff0c;就是给我们一个数组&#xff0c;让我们返回第K大的元素。 那么很直观的一个做法就是我们直接对数组进行降序排序…

【恒生电子内推码】

Hello&#xff0c;我是恒生电子股份有限公司的校园大使&#xff0c;不想简历投递后“泡池子”&#xff0c;登录链接&#xff1a;campus.hundsun.com/campus/jobs&#xff0c;填写我的推荐码&#xff1a;EZVJR0&#xff0c;投递&#xff0c;简历第一时间送到HR面前&#xff0c;快…

STM32-DMA

1 DMA简介 DMA&#xff08;Direct Memory Access&#xff09;,中文名为直接内存访问&#xff0c;它是一些计算机总线架构提供的功能&#xff0c;能使数据从附加设备&#xff08;如磁盘驱动器&#xff09;直接发送到计算机主板的内存上。对应嵌入式处理器来说&#xff0c;DMA可…

【2023年数学建模国赛】赛题发布

2023数学建模国赛赛题已经发布啦&#xff0c;距离赛题发布已经过去三个小时了&#xff0c;大家是否已经确定题目呢&#xff1f;学姐后续会持续更新赛题思路与代码~

TINA如何导入spice模型

本文介绍如何使用TINA仿真运算放大器电路。TINA是TI公司自己的spice仿真软件&#xff0c;各个大厂为了更好的让客户使用自己的器件&#xff0c;都纷纷推出自己的仿真软件&#xff0c;ADI也有类似的软件&#xff0c;有机会我们介绍&#xff0c;这期我们主要简单介绍下如何使用TI…

Jmeter系列-Jmeter面板介绍和常用配置(2)

Jmeter面板介绍 常用菜单栏 分布式运行相关的 选项&#xff0c;可以打开日志&#xff0c;修改语言、函数助手对话框&#xff0c;还有管理插件 常用的图标 从左到右依次 新建测试计划选择测试计划模板创建一个新的测试计划打开jmeter脚本保存jmeter脚本剪切复制粘贴展开目录…

大数据课程K18——Spark的ALS算法与显式矩阵分解

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Spark的ALS算法与显式矩阵分解; ⚪ 掌握Spark的ALS算法原理; 一、ALS算法与显式矩阵分解 1. 概述 我们在实现推荐系统时,当要处理的那些数据是由用户所提供的自身的偏好数据,这些…

Apache nginx解析漏洞复现

文章目录 空字节漏洞安装环境漏洞复现 背锅解析漏洞安装环境漏洞复现 空字节漏洞 安装环境 将nginx解压后放到c盘根目录下&#xff1a; 运行startup.bat启动环境&#xff1a; 在HTML文件夹下有它的主页文件&#xff1a; 漏洞复现 nginx在遇到后缀名有php的文件时&#xff0c;…

微信小程序组件的创建与引用

组件的创建 <view><swiper class"myswiper" interval"{{interval}}" circular autoplay"{{autoplay}}" indicator-dots"{{indicatorDots}}"><swiper-item><image mode"widthFix" src"/image/l…

【JAVA】面向对象的编程语言(继承篇)

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言继承类的继承方式继承的各种类型多继承继承的特性各种继承关键字extends关键字implements关键字super 与 this 关键字super 关键字this 关键字 final 关键字 前言 在之前的…

sklearn中make_blobs方法:聚类数据生成器

sklearn中make_blobs()方法参数&#xff1a; n_samples:表示数据样本点个数,默认值100 n_features:是每个样本的特征&#xff08;或属性&#xff09;数&#xff0c;也表示数据的维度&#xff0c;默认值是2。默认为 2 维数据&#xff0c;测试选取 2 维数据也方便进行可视化展示…

国产化操作系统改造oracle proc依赖库文件缺失处理

国产化操作系统改造oracle proc依赖库文件缺失处理 文章目录 国产化操作系统改造oracle proc依赖库文件缺失处理1 场景2 排查过程2.1 查看安装库文件2.2 搜索yum源libnsl库版本 3 解决方案3.1 方法一&#xff1a;通过yum源安装libnsl3.2 方法二&#xff1a;从其它正常编译环境拷…

YOLOV7改进-添加SAConv.

链接link 1、放到common文件夹下&#xff0c;最后面加 2、yolo.py下 3、修改配置文件cfg-training&#xff1a;yolov7.yaml 4、一般用在3x3卷积上