自动驾驶---Control之LQR控制

1 前言

        在前面的系列博客文章中为读者阐述了很多规划相关的知识(可参考下面专栏),本篇博客带领读者朋友们了解控制相关的知识,后续仍会撰写规控相关文档。

e3b0c198db3a4fb5a848de57e4f34b65.png

        在控制理论的发展过程中,人们逐渐认识到对于线性动态系统的控制,可以通过优化某种性能指标来达到更好的控制效果。而LQR控制就是基于这种思想发展而来的。它通过将系统状态与控制信号之间的关系表示成一种二次型,然后通过最小化这个二次型来求解最优的控制策略。       

        目前的工业领域三大控制器占据着主要位置:PID,LQR以及MPC,本篇博客为读者介绍LQR控制器。

2 LQR建模求解

        LQR(Linear quadratic regulator,线性二次型调节器)是一种基于状态反馈的最优控制策略,其核心在于设计一个状态反馈控制器,使得系统的性能指标达到最优。下面将对LQR控制器进行详细介绍:

2.1 原理与步骤

  1. 确定状态方程模型:首先需要确定一个描述系统状态的动力学模型,该模型通常以状态空间的形式给出,用于描述系统在不同状态下的动态行为。
  2. 线性化处理:对状态方程进行线性化处理,将其转化为线性系统模型。这是为了简化问题,使得控制器设计更加便捷。
  3. 定义目标函数:目标函数通常是系统状态和控制输入的二次型函数,用于评估控制性能的好坏。这个函数的选择会直接影响到控制器的设计效果。
  4. 优化目标函数:通过设计状态反馈控制器,使得目标函数取最小值。这个过程中,需要求解一个最优控制问题,通常涉及到Riccati方程的求解。

2.2 详细内容

2.2.1 一般推导

        对于一个闭环系统,状态方程为:

eq?%5Cdot%7Bx%7D%3DAx+Bu

        其中eq?x 为状态量,eq?u 为控制量,eq?A%2CB 分别为状态矩阵,控制矩阵。假设eq?u%3D-Kx,那么上式可以整理为一个新的状态方程:

eq?%5Cdot%7Bx%7D%3D%28A-BK%29x%3DA_cx

        为了能够选出最优化的特征值,引入了一个代价函数,考虑两个方面的内容:

  • 希望系统达到稳定状态使得偏差最小:惩罚状态量
  • 希望控制量较小的情况下也能达到稳定状态:惩罚控制量

        因此代价函数可以写成如下形式:

eq?J%3D0.5*%5Cint_%7B0%7D%5E%7B%5Cinfty%7D%28x%5ETQx+u%5ETRu%29dt

        其中,eq?x 为状态量,eq?u 为控制量,eq?Q%2CR 分别为状态权重矩阵,控制权重矩阵。在量产中的调参也主要集中在eq?Q%2CR矩阵上。

        基于上面两个方面的考虑,这里希望 eq?Q 为半正定矩阵来保证eq?x%5ETQx%5Cgeq%200;希望eq?R 为正定矩阵来保证eq?u%5ETRu%3E%200,该项表示控制所付出的代价。

        将eq?u%3D-Kx 代入到代价函数种可得,

eq?J%3D0.5*%5Cint_%7B0%7D%5E%7B%5Cinfty%7D%28x%5ETQx+u%5ETRu%29dt%3D%5C%5C0.5*%5Cint_%7B0%7D%5E%7B%5Cinfty%7D%28x%5ETQx+%28-Kx%29%5ETR%28-Kx%29%29dt%3D%5C%5C0.5*%5Cint_%7B0%7D%5E%7B%5Cinfty%7D%28x%5ETQx+x%5ETK%5ETRKx%29dt%3D%5C%5C0.5*%5Cint_%7B0%7D%5E%7B%5Cinfty%7Dx%5ET%28Q+K%5ETRK%29xdt

        为了得到 eq?K 矩阵,假设存在一个常量矩阵 eq?P 使得,

eq?%5Cfrac%7B%5Cmathrm%7Bd%7D%20%7D%7B%5Cmathrm%7Bd%7D%20t%7D%28x%5ETPx%29%3D-x%5ET%28Q+K%5ETRK%29x

        将上式左边微分展开得到,并代入 eq?%5Cdot%7Bx%7D%3DA_cx

eq?%5Cdot%7Bx%7D%5ETPx+x%5ETP%5Cdot%7Bx%7D%3D-x%5ET%28Q+K%5ETRK%29x%5C%5C%5C%5C%20%5Cdot%7Bx%7D%5ETPx+x%5ETP%5Cdot%7Bx%7D+x%5ET%28Q+K%5ETRK%29x%3D0%5C%5C%5C%5C%20%28A_cx%29%5ETPx+x%5ETP%28A_cx%29+x%5ET%28Q+K%5ETRK%29x%3D0%5C%5C%5C%5C%20x%5ET%28A%5ET_cP+PA_c+Q+K%5ETRK%29x%3D0

        由二次型的性质可得,如果保证上式为0,则括号内的值必须为0,即:

eq?A%5ET_cP+PA_c+Q+K%5ETRK%3D0%5C%5C%5C%5C%20%28A-BK%29%5ETP+P%28A-BK%29+Q+K%5ETRK%3D0

        上式中含有eq?K矩阵的二次型,不利于计算,因此取eq?K%3DR%5E%7B-1%7DB%5ETP 消掉二次项得,

eq?%28A-BK%29%5ETP+P%28A-BK%29+Q+K%5ETRK%3D0%5C%5C%5C%5C%20A%5ETP+PA+Q-K%5ETB%5ETP-PBK+K%5ETRK%3D0%5C%5C%5C%5C%20A%5ETP+PA+Q-%28R%5E%7B-1%7DB%5ETP%29%5ETB%5ETP-PB%28R%5E%7B-1%7DB%5ETP%29+%28R%5E%7B-1%7DB%5ETP%29%5ETR%28R%5E%7B-1%7DB%5ETP%29%3D0%5C%5C%5C%5CA%5ETP+PA+Q-PBR%5E%7B-1%7DB%5ETP%3D0

        从上面的公式中,可以看到形式正好是控制理论中的Riccati方程。

21314f2087ae456cb0c7fda7e806c749.png

2.2.2 离散域推导

        网上看到很多文章的推导结果不太一致,在此处说明,另一种形式的Riccati方程是基于离散时域的推导结果:

eq?P%20%3D%20A%5ETPA%20-%20A%5ETPB%28R%20+%20B%5ETPB%29%5E%7B-1%7DB%5ETPA%20+%20Q

        记 eq?t 时刻代价函数为 eq?V_t,价值函数为 eq?Q_t,其中 eq?%5Bt%3DN%2CN-1...1%2C0%5D

eq?V_t%28x_t%29%3Dmin_%7Bu_t%7Dx%5ET_tQx_t+u%5ET_tRu_t+V_%7Bt+1%7D%28x_%7Bt+1%7D%29%2C%20t%3C%3DN-1%5C%5C%5C%5C%20V_N%28x_N%29%3Dx%5ET_NQ_fx_N%2C%20t%3DN%5C%5C%5C%5C%20Q_t%28x_t%2Cu_t%29%3Dx%5ET_tQx_t+u%5ET_tRu_t+V_%7Bt+1%7D%28x_%7Bt+1%7D%29

        这里同样假设存在一个矩阵eq?P_t (eq?P_t%3DP%5ET_t)使得下式成立,

eq?V_t%28x_t%29%3Dx%5ET_tP_tx_t

        那么基于离散状态方程 eq?x_%7Bk+1%7D%3DAx_k+Bu_keq?Q_t 可以写为:

eq?Q_t%28x_t%2Cu_t%29%3Dx%5ET_tQx_t+u%5ET_tRu_t+%28Ax_t+Bu_t%29%5ETP_%7Bt+1%7D%28Ax_t+Bu_t%29

        对于价值函数 eq?Q_t 取极小值,即

eq?%5Cfrac%7B%5Cpartial%20Q_t%7D%7B%5Cpartial%20u%7D%3D0

       这里插一个矩阵求导的知识(注意区分:分子布局还是分母布局)

eq?y%3Dx%5ETAx%5C%5C%5C%5C%5Cfrac%7B%5Cpartial%20y%7D%7B%5Cpartial%20x%7D%3Dx%5ET%28A+A%5ET%29                  

eq?y%3DMx%5C%5C%5C%5CJ%3Dy%5ETSy%5C%5C%5C%5C%5Cfrac%7B%5Cpartial%20J%7D%7B%5Cpartial%20x%7D%3D%5Cfrac%7B%5Cpartial%20%28x%5ETM%5ETSMx%29%7D%7B%5Cpartial%20x%7D%5C%5C%5C%5C%3Dx%5ET%28M%5ETSM+M%5ETS%5ETM%29

        整理可得,

eq?u%5ET_t%28R+R%5ET%29+%28Ax_t+Bu_t%29%5ET%28P_%7Bt+1%7D+P%5ET_%7Bt+1%7D%29B%3D0

        由于eq?R%2C%20P 都是对称矩阵,可得,

eq?2u%5ET_tR+2%28Ax_t+Bu_t%29%5ETP_%7Bt+1%7DB%3D0

eq?u_t%3D-%28R%20+%20B%5ETP_%7Bt+1%7DB%29%5E%7B-1%7DB%5ETP_%7Bt+1%7DAx_t

        由 eq?u%3D-Kx 可得,

eq?K_t%3D%28R%20+%20B%5ETP_%7Bt+1%7DB%29%5E%7B-1%7DB%5ETP_%7Bt+1%7DA

        将 eq?u_t 代入到 eq?Q_t 中可得,

eq?x%5ET_tP_tx_t%20%3D%20x%5ET_t%28Q+A%5ETP_%7Bt+1%7DA%20-%20A%5ETP_%7Bt+1%7DB%28R%20+%20B%5ETP_%7Bt+1%7DB%29%5E%7B-1%7DB%5ETP_%7Bt+1%7DA%29x_t

        最后得到的离散Riccati方程如下:

eq?P_t%20%3D%20Q+A%5ETP_%7Bt+1%7DA%20-%20A%5ETP_%7Bt+1%7DB%28R%20+%20B%5ETP_%7Bt+1%7DB%29%5E%7B-1%7DB%5ETP_%7Bt+1%7DA

        在控制理论中,Riccati方程扮演着至关重要的角色,它通常用于描述线性时不变系统的最优控制问题。通过求解Riccati方程,可以找到使得系统状态达到最优的反馈控制律。对于离散时间系统和连续时间系统,Riccati方程的形式和求解方法会有所不同。

        求解连续时间Riccati方程通常涉及数值方法,因为解析解可能不存在或难以找到。常用的数值方法包括迭代法和直接法。迭代法如牛顿法或不动点迭代法,通过迭代更新矩阵 P的值,直到满足收敛条件。直接法则试图通过矩阵分解或变换直接求解方程。

        此部分的代码主要如下:

#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/LU>
#include <iostream>

using Eigen::Matrix;
using Eigen::Dynamic;

typedef Matrix<double, Dynamic, Dynamic> Mtx;

/*
 * @brief Computes the LQR gain matrix (usually denoted K) for a discrete time
 * infinite horizon problem.
 *
 * @param A State matrix of the underlying system
 * @param B Input matrix of the underlying system
 * @param Q Weight matrix penalizing the state
 * @param R Weight matrix penalizing the controls
 * @param N Weight matrix penalizing state / control pairs
 * @param K Pointer to the generated matrix (has to be a double/dynamic size
 * matrix!)
 * @param eps Delta between iterations that determines when convergence is
 * reached
 */
bool SolveLQRMatrix(const Mtx &A, const Mtx &B, const Mtx &Q, const Mtx &R,
                    const Mtx &N, Mtx *K, double eps = 1e-15) {
  // check if dimensions are compatible
  if (A.rows() != A.cols() || B.rows() != A.rows() || Q.rows() != Q.cols() ||
      Q.rows() != A.rows() || R.rows() != R.cols() || R.rows() != B.cols() ||
      N.rows() != A.rows() || N.cols() != B.cols()) {
    std::cout << "One or more matrices have incompatible dimensions. Aborting."
              << std::endl;
    return false;
  }

  // precompute as much as possible
  Mtx B_T = B.transpose();
  Mtx Acal = A - B * R.inverse() * N.transpose();
  Mtx Acal_T = Acal.transpose();
  Mtx Qcal = Q - N * R.inverse() * N.transpose();

  // initialize P with Q
  Mtx P = Q;

  // iterate until P converges
  unsigned int numIterations = 0;
  Mtx Pold = P;
  while (true) {
    numIterations++;
    // compute new P
    P = Acal_T * P * Acal -
        Acal_T * P * B * (R + B_T * P * B).inverse() * B_T * P * Acal + Qcal;

    // update delta
    Mtx delta = P - Pold;
    if (fabs(delta.maxCoeff()) < eps) {
      std::cout << "Number of iterations until convergence: " << numIterations
                << std::endl;
      break;
    }
    Pold = P;
  }

  // compute K from P
  *K = (R + B_T * P * B).inverse() * (B_T * P * A + N.transpose());

  return true;
}

3 车辆LQR控制

        本小节以汽车运动学模型为例,车辆的运动模型如下图所示,本小节理论部分主要参考龚建伟老师著作《无人驾驶车辆模型预测控制》,基于汽车动力学模型的推导可参考Rajamani的著作《Vehicle Dynamics And Control》。

8eda4aa31dea47d0b145ee42b380a6a0.png

3.1 运动学模型        

        可得车辆的运动学模型为:

L%20%7D%20%5Cend%7Bbmatrix%7D*v_req?

        可将整个系统看作一个输入为eq?u%28v%2C%5Cdelta%20%29 和 eq?%5Cchi%20%28x%2Cy%2C%5Cvarphi%20%29 的控制系统。其一般形式为:

eq?%5Cdot%7B%5Cchi%7D%3Df%28%5Cchi%2Cu%29

        在自动驾驶轨迹跟踪中,通常以跟踪偏差作为输入,因此可得,

eq?%5Cdot%7B%5Cchi%7D%3Df%28%5Cchi_r%2Cu_r%29&plus;%5Cfrac%7B%5Cpartial%28%5Cchi%2Cu%29%20%7D%7B%5Cpartial%20%5Cchi%7D%7C_%7B%5Cchi%3D%5Cchi_r%2Cu%3Du_r%7D%28%5Cchi-%5Cchi_r%29&plus;%5Cfrac%7B%5Cpartial%28%5Cchi%2Cu%29%20%7D%7B%5Cpartial%20u%7D%7C_%7B%5Cchi%3D%5Cchi_r%2Cu%3Du_r%7D%28u-u_r%29

%28lcos%5E2%5Cdelta_r%29%20%5Cend%7Bbmatrix%7D%5Cbegin%7Bbmatrix%7D%20v-v_r%5C%5C%20%5Cdelta-%5Cdelta_r%20%5Cend%7Bbmatrix%7D

  为了能够将该模型应用于控制器的设计,最终进行离散化处理,最终可以写成如下形式: eq?%5Ctilde%7B%5Cchi%7D%28k&plus;1%29%3D%20A%5Ctilde%7B%5Cchi%7D%7Bk%7D&plus;B%5Ctilde%7Bu%7D%28k%29

%28lcos%5E2%5Cdelta_r%29%20%5Cend%7Bbmatrix%7D

         建立运动学模型的代码如下(只保留重要部分):

void Model::GetModel(float curvature, Eigen::Matrix<double, 3, 1> state_actual){
    //target delta is variable because of curve path.
    float target_delta = atan(wheel_base*curvature); //dphi/dt = V*tan(delta)/L;  w = V*tan(delta)/L
    /*****************************************************/
    // A
    Matrix_->A(0, 0) = 1;
    Matri>A(1, 0) = 0;
    Matrix_->A(1, 1) = 1;
    Matrix_->Ax_->A(0, 1) = 0;
    Matrix_->A(0, 2) = -target_velocity*sin(state_actual(2,0))*dt_;
    Matrix_-(1, 2) = target_velocity*cos(state_actual(2,0))*dt_;
    Matrix_->A(2, 0) = 0;
    Matrix_->A(2, 1) = 0;
    Matrix_->A(2, 2) = 1;
    /*****************************************************/
    // B
    Matrix_->B(0, 0) = cos(state_actual(2,0))*dt_;
    Matrix_->B(0, 1) = 0;
    Matrix_->B(1, 0) = sin(state_actual(2,0))*dt_;
    Matrix_->B(1, 1) = 0;
    Matrix_->B(2, 0) = tan(target_delta)*dt_/wheel_base;
    Matrix_->B(2, 1) = target_velocity*dt_/(wheel_base*(cos(target_delta)*cos(target_delta)));
}

3.2 求解

        再结合上面一节LQR求解代码如下(非完整):

void LQRControl::LQRController(){
        //near point
        int index = FindMatchedPoint(actual_pos.x, actual_pos.y);

        x_ref_(0, 0) = planning_path[index].position.x;
        x_ref_(1, 0) = planning_path[index].position.y;
        x_ref_(2, 0) = planning_path[index].position.yaw;
        x_act_(0, 0) = actual_pos.x;
        x_act_(1, 0) = actual_pos.y;
        x_act_(2, 0) = actual_pos.yaw;
        /***********compute curvature of target point********************************/
        curvature = ComputeCurvature(index);
        // get model matrix A and B
        model_.GetModel(curvature, x_act_);
        matrix_c.A = model_.Matrix_->A;
        matrix_c.B = model_.Matrix_->B;
        // Q(3x3): positive semi-definite matrix, penalizing the state
        matrix_c.Q(0, 0) = 1;
        matrix_c.Q(0, 0) = 10;
        matrix_c.Q(0, 0) = 1;
        // R(2x2): positive definite matrix,  penalizing the controls
        matrix_c.R(0, 0) = 100;
        matrix_c.R(1, 1) = 100;
        // N(3x2):  penalizing the state/control pairs
        matrix_c.N = Eigen::Matrix<double, 3, 2>::Zero();
        /****************************************************************************/
        // Solve the Riccati Equation
        if (!SolveLQRMatrix(matrix_c.A, matrix_c.B, matrix_c.Q, matrix_c.R, matrix_c.N, &matrix_k)){
            std::cout << "Compute matrix K failed!" << std::endl;
        }else{
            std::cout << matrix_k << std::endl;
        }
}

4 特点与应用

(1) 特点

  1. 最优性:LQR控制器通过最小化目标函数,使得系统性能达到最优。这种最优性是基于给定的性能指标进行衡量的,因此可以根据实际需求进行灵活调整。
  2. 适应性:LQR控制器可以适应不同的系统模型和性能指标,通过调整目标函数和控制器参数,可以实现对不同系统的有效控制。
  3. 稳定性:通过设计合适的控制器参数,LQR控制器可以保证系统的稳定性,避免出现过大的状态波动或控制误差。

(2)应用领域

        LQR控制器广泛应用于控制工程、机器人学、飞行器控制以及其他控制领域。在这些领域中,LQR控制器能够有效地处理线性系统的控制问题,实现精确、稳定的控制效果。

f55e224bddd14d99bd1f26f2f38e2e2d.png

5 总结

        综上所述,LQR控制器是一种基于状态反馈的最优控制策略,具有最优性、适应性和稳定性等特点。它在多个领域都有广泛的应用,并且与其他控制器相比具有优势。在实际应用中,可以根据具体需求选择和设计合适的LQR控制器,以实现精确、稳定的控制效果。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Websocket服务端结合内网穿透发布公网实现远程访问发送信息

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…

Audition 2024 for Mac/Win:音频录制与编辑的卓越之选

随着数字媒体的不断发展&#xff0c;音频内容创作已经成为各行各业中不可或缺的一部分。无论是音乐制作、广播节目、播客录制还是影视配音&#xff0c;都需要高品质的音频录制和编辑工具来实现专业水准的作品。在这个充满竞争的时代&#xff0c;要想在音频创作领域脱颖而出&…

如何合理使用群发短信呢?(短信接口JSON实例)

随着时代的发展&#xff0c;越来越多的营销推广也开始有线下转移到了线上&#xff0c;短信也变成了企业与用户之间交流沟通的桥梁&#xff0c;那么这么多的企业选择使用短信平台&#xff0c;到底群发短信好不好用呢&#xff1f;今天乐讯通短信平台就为大家来介绍一下群发短信营…

【C++进阶】深入STL之vector:构建高效C++程序的基石

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;模拟实现string &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STL之vector &#x1f4d2;1.ve…

NLP基础——序列模型(动手学深度学习)

序列模型 定义 序列模型是自然语言处理&#xff08;NLP&#xff09;和机器学习领域中一类重要的模型&#xff0c;它们特别适合处理具有时间顺序或序列结构的数据&#xff0c;例如文本、语音信号或时间序列数据。 举个例子&#xff1a;一部电影的评分在不同时间段的评分可能是…

【个数】滑动窗口-1004. 最大连续1的个数 III 1493. 删掉一个元素以后全为 1 的最长子数组

题目链接及描述 1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09; 题目分析 今日写到这个题目&#xff0c;是滑动窗口的标签&#xff0c;但首先看到后感觉和之前做过的滑动窗口题目有点区别&#xff0c;之前滑动窗口通过给定一个区间长度&#xff0c;随后区…

.NET集成DeveloperSharp实现图片的裁剪、缩放、与加水印

&#x1f3c6;作者&#xff1a;科技、互联网行业优质创作者 &#x1f3c6;专注领域&#xff1a;.Net技术、软件架构、人工智能、数字化转型、DeveloperSharp、微服务、工业互联网、智能制造 &#x1f3c6;欢迎关注我&#xff08;Net数字智慧化基地&#xff09;&#xff0c;里面…

第一篇 逻辑门(与门、或门、非门、异或门)

一、实验目的 了解DE1-SOC开发板一些外设。 掌握常用组合逻辑门电路的基本原理。 学习Verilog HDL的基本语法。 学习使用ModelSim工具对设计的电路进行仿真&#xff0c;包括编写Testbench仿真代码&#xff0c;以及ModelSim工具的使用。 熟悉使用Quartus软件从创建Quartus工…

el-tooltip使用记录

记录工作中使用el-toolitp的情况 需求一&#xff1a;列表项内容超出限制时&#xff0c;点击单元格展示Tooltip 需求描述&#xff1a;某列表项内容返回过多&#xff0c;超出最大限制时&#xff1a; 1.点击该单元格再显示tooltip&#xff1b; 2.点击下一行更新tooltip内容&…

《数字图像处理-OpenCV/Python》第15章:图像分割

《数字图像处理-OpenCV/Python》第15章&#xff1a;图像分割 本书京东 优惠购书链接 https://item.jd.com/14098452.html 本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html 第15章&#xff1a;图像分割 图像分割是由图像处理到图像分析的关键步骤…

关于gitee上传成功没有绿点

今天上传完代码以后&#xff0c;打开gitee看了一下&#xff0c;但是看到昨天和今天都没有小绿点&#xff0c;仔细思考了一番&#xff0c;是仓库满了&#xff1f;不对啊&#xff0c;如果满了的话&#xff0c;上传就会失败啊&#xff0c;那这是什么问题呢&#xff1f; 原来是因为…

Parallels Desktop for Mac 19.4.0更新了哪些内容?有什么改进?

带来了重新设计的共享 Mac 文件夹版本&#xff0c;这些文件夹现在是符号链接&#xff0c;像指针一样指向您的 Mac 文件夹中的文件&#xff0c;同时仍然显示在 Windows 的本地磁盘上。 修复了由于共享文件夹问题导致 NinjaTrader 无法正常启动的问题。 修复了由于共享文件夹问…

2024中国跨境电商海外营销观察报告

来源&#xff1a;霞光智库 近期历史回顾&#xff1a;战略测量的未来报告 2024影响力系列白皮书&#xff08;第五册&#xff09;——绿氢 2024年Z世代与千禧一代调研报告.pdf 2023中国车规级芯片产业白皮书.pdf 2024全球网文应用营销洞察报告.pdf 2024年Q1抖音女性卫生用品行业趋…

操作系统教材第6版——个人笔记1

第一章 计算机操作系统概述 操作系统是计算机系统中最重要的系统软件&#xff0c;它统一管理计算机系统的硬件资源与信息资源&#xff0c;控制与调度上层软件的执行并为其提供易于使用的接口。从资源管理、程序控制、操作控制、人机交互、程序接口、系统结构6个角度深入观察操…

JS冒泡排序案例详解

先看一下案例效果&#xff1a; HTML代码&#xff1a; <input type"text" value"" id"bubble-input"> <button onclick"bubbleSort()">冒泡排序</button> <h4 id"bubbleSort-result"></h4>J…

vue2 bug求助!!!(未解决,大概是浏览器缓存的问题或者是路由的问题)

我的vue2项目出现了一个超级恶心的bug 过程&#xff1a; 1 操作流程&#xff1a;页面a点击a标签->到页面b->页面b用户退出刷新页面->点击浏览器的返回按钮返回上一页 2 结果&#xff1a;返回页面后页面没有刷新导致用户名还显示着&#xff0c;页面没有发生任何变化&a…

5.3.2网安学习第五阶段第三周回顾(个人学习记录使用)

本周重点 ①网络安全攻防技术体系 ②Windows入侵排查 ③Linux入侵排查 ④僵蠕木毒排查与处理 本周主要内容 ①网络安全攻防技术体系 一、攻击层面 1、分类 &#xff08;1&#xff09;指定目标&#xff1a;APT攻击手段&#xff0c;对指定目标进行长期作战和渗透&#x…

从Multisim到Proteus,再到SmartEDA:电子设计软件的进化之旅

在电子设计领域&#xff0c;软件工具的演进犹如一条璀璨的轨迹&#xff0c;记录着科技进步的每一个步伐。从Multisim的初创&#xff0c;到Proteus的崛起&#xff0c;再到如今SmartEDA的崭露头角&#xff0c;这些电子设计软件不仅极大地提升了设计效率&#xff0c;更推动了整个行…

函数高级:函数的默认参数|函数的占位参数|函数重载

函数的默认参数 函数占位参数 函数重载 总结&#xff1a; 函数的形参&#xff0c;有自己的参数值就用参数值&#xff0c;没有就用形参列表的默认值。 参数列表中&#xff0c;某位置有自己的默认值&#xff0c;从该位置起&#xff0c;往后就都必须设有默认值。 函数声明和函数…

一键设置常用纸张和页面边距-Word插件-大珩助手

Word大珩助手是一款功能丰富的Office Word插件&#xff0c;旨在提高用户在处理文档时的效率。它具有多种实用的功能&#xff0c;能够帮助用户轻松修改、优化和管理Word文件&#xff0c;从而打造出专业而精美的文档。 【新功能】常用纸张和常用边距 1、一键设定符合中国人常用…