模型预测控制MPC详解(附带案例实现)

模型预测控制MPC详解(附带案例实现)

文章目录

  • 模型预测控制MPC详解(附带案例实现)
    • 1. 最优控制问题
    • 2. 什么是MPC
    • 3. 二次规划Quadratic Programming
    • 4. MPC为什么可以转换成QP问题(推导过程)
    • 5. MPC总结
      • 5.1 MPC的优势劣势
      • 5.2 MPC的衍生算法
    • 6. 示例实现
    • Reference

写在前面本文是记录学习B站博主Dr.can的学习笔记,如有侵权请联系笔者删除此文。

1. 最优控制问题

最优控制问题就是研究在约束条件下达到最优的系统表现,通常系统的表现是综合分析的结果。比如考虑一个单输入单输出的系统(SISO),状态变量 x x x,输出为 y y y,要求其输出能跟踪预设的参考值 r r r,误差可以表示为 e = y − r e=y-r e=yr,那么最优控制的目标是

min ⁡ ∫ 0 t e 2 d t \min \int_0^t e^2 dt min0te2dt

如果同时希望输入量 u u u也能越小越好(一般的目的是减少能耗),那最优控制的目标可以是

min ⁡ ∫ 0 t q × e 2 d t + r × u 2 d t \min \int_0^t q\times e^2 dt + r\times u^2 dt min0tq×e2dt+r×u2dt

其中 q , r q,r q,r分别是权重参数,用于调节两个目标的重要性。

考虑一个多输入多输出的系统(MIMO),系统的模型为:

d X d t = A X + B U Y = C X \begin{align*} \frac{dX}{dt} & = AX + BU \\ Y & = CX \end{align*} dtdXY=AX+BU=CX

那么可以将上述的最优化目标改写为:

J = ∫ 0 t E T Q E + U T R U d t J = \int^t_0 E^T Q E + U^T R U dt J=0tETQE+UTRUdt

举一个实际的例子,系统的模型如下所示:

d d t [ x 1 x 2 ] = A [ x 1 x 2 ] + B [ u 1 u 2 ] [ y 1 y 2 ] = [ x 1 x 2 ] \begin{align*} \frac{d}{dt} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} & = A \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} + B \begin{bmatrix} u_1 \\ u_2 \end{bmatrix} \\ \begin{bmatrix} y_1 \\ y_2 \end{bmatrix} & = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} \end{align*} dtd[x1x2][y1y2]=A[x1x2]+B[u1u2]=[x1x2]

设置的参考值 R R R为:

R = [ r 1 r 2 ] = [ 0 0 ] R = \begin{bmatrix} r_1 \\ r_2 \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \end{bmatrix} R=[r1r2]=[00]

那么可以推导出误差 E E E为:

E = [ e 1 e 2 ] = [ y 1 − r 1 y 2 − r 2 ] = [ x 1 x 2 ] E = \begin{bmatrix} e_1 \\ e_2 \end{bmatrix} = \begin{bmatrix} y_1 - r_1 \\ y_2 - r_2 \end{bmatrix} = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} E=[e1e2]=[y1r1y2r2]=[x1x2]

那么上述最优控制的目标函数可以写成:

E T Q E = [ x 1 x 2 ] T [ q 1 0 0 q 2 ] [ x 1 x 2 ] = q 1 x 1 2 + q 2 x 2 2 U T R U = [ u 1 u 2 ] T [ r 1 0 0 r 2 ] [ u 1 u 2 ] = r 1 u 1 2 + r 2 u 2 2 J = ∫ 0 t q 1 x 1 2 + q 2 x 2 2 + r 1 u 1 2 + r 2 u 2 2 \begin{align*} E^TQE & = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix}^T \begin{bmatrix} q_1 & 0 \\ 0 & q_2 \end{bmatrix}\begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = q_1 x_1^2 + q_2 x_2^2 \\ U^TRU & = \begin{bmatrix} u_1 \\ u_2 \end{bmatrix}^T \begin{bmatrix} r_1 & 0 \\ 0 & r_2 \end{bmatrix}\begin{bmatrix} u_1 \\ u_2 \end{bmatrix} = r_1 u_1^2 +r_2 u_2^2 \\ J & = \int^t_0 q_1 x_1^2 + q_2 x_2^2 + r_1 u_1^2 + r_2 u_2^2 \end{align*} ETQEUTRUJ=[x1x2]T[q100q2][x1x2]=q1x12+q2x22=[u1u2]T[r100r2][u1u2]=r1u12+r2u22=0tq1x12+q2x22+r1u12+r2u22

2. 什么是MPC

MPC(Model Predictive Control,模型预测控制)的基本思想是通过建立一个系统的动态模型,并在每一个控制时刻使用这个模型来预测系统未来的行为。基于这些预测,它可以生成一个优化控制序列,然后通过执行第一个控制动作来调整系统状态,接着在下一个时刻重新计算和执行。这个过程反复进行,以使系统能够在未来的一段时间内优化一个特定的性能指标。

通常来说,MPC包括以下四个基本步骤:

  • 系统模型化:建立描述系统动态行为的数学模型,通常是差分方程或微分方程。

  • 预测:在当前时刻基于系统状态和控制输入,使用模型预测未来一段时间内的系统响应。

  • 优化:基于预测的系统响应,通过求解一个优化问题来计算最优的控制输入序列,以最大化或最小化一个性能指标(如系统响应时间、能耗等)。

  • 执行:根据优化得到的控制输入序列中的第一个值,执行这个控制动作,并将实际的系统状态反馈到下一个控制周期中

在具体实施的过程中MPC主要分为下列的三个步骤:

k时刻:

  • step1:估计/测量/读取当前的系统状态;
  • step2:基于 u k , u k + 1 , ⋯ , u k + N \bold{u}_k, \bold{u}_{k+1}, \cdots, \bold{u}_{k+N} uk,uk+1,,uk+N来进行最优化
    J = ∑ k N − 1 E k T Q E k + U k T R U k + E N T F E N ⏟ Terminal Cost J = \sum_k^{N-1} E_k^TQE_k + U_k^T R U_k + \underbrace{E_N^TFE_N}_{\text{Terminal Cost}} J=kN1EkTQEk+UkTRUk+Terminal Cost ENTFEN
    其中Terminal Cost代表了模型滑动窗口的末端的控制误差。
  • step3:只取 u k \bold{u}_k uk,进行滚动优化控制。

3. 二次规划Quadratic Programming

为了能求解MPC问题,我们需要将其转换成二次规划(Quadratic Programming)的形式,对于二次规划已经有很多成熟的求解器了,我们只需要使用这些求解器就能顺利求解。

二次规划一般具有如下的形式:

min ⁡ x x T H x + f T x subject to . . . \begin{align*} & \min_\bold{x} \bold{x}^TH\bold{x} + f^T\bold{x} \\ & \text{subject to} \quad... \end{align*} xminxTHx+fTxsubject to...

其中 H H H是正定的对称矩阵, f f f x \bold{x} x是向量。

4. MPC为什么可以转换成QP问题(推导过程)

考虑一个离散的线性系统

x ( k + 1 ) = A n × n x ( k ) + B n × p u ( k ) x n × 1 = [ x 1 x 2 ⋮ x n ] , u p × 1 = [ u 1 u 2 ⋮ u p ] \bold{x}(k+1) = A_{n\times n}\bold{x}(k) + B_{n\times p}\bold{u}(k) \\ \bold{x}_{n\times 1} = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix}, \bold{u}_{p\times1} = \begin{bmatrix} u_1 \\ u_2 \\ \vdots \\ u_p \end{bmatrix} x(k+1)=An×nx(k)+Bn×pu(k)xn×1= x1x2xn ,up×1= u1u2up

假设滚动的窗口大小(预测区间,Predictive Horizon)为 N N N,在 k k k时刻,预测 k k k时刻的输入为 u ( k ∣ k ) \bold{u}(k|k) u(kk),预测 k + 1 k+1 k+1时刻的输入为 u ( k + 1 ∣ k ) \bold{u}(k+1|k) u(k+1∣k),以此类推预测,预测区间的最后一个时刻的输入为 u ( k + N − 1 ∣ k ) \bold{u}(k+N-1|k) u(k+N1∣k),将这些预测输入整合成一个向量

U k = [ u ( k ∣ k ) u ( k + 1 ∣ k ) ⋮ u ( k + i ∣ k ) u ( k + N − 1 ∣ k ) ] \bold{U}_k = \begin{bmatrix} \bold{u}(k|k) \\ \bold{u}(k+1|k) \\ \vdots \\ \bold{u}(k+i|k) \\ \bold{u}(k+N-1|k) \end{bmatrix} Uk= u(kk)u(k+1∣k)u(k+ik)u(k+N1∣k)

k k k时刻,系统的状态为 x ( k ∣ k ) \bold{x}(k|k) x(kk) k + 1 k+1 k+1系统的状态为 x ( k + 1 ∣ k ) \bold{x}(k+1|k) x(k+1∣k),以此类推预测,预测区间的最后一个时刻的系统的状态为 x ( k + N − 1 ∣ k ) \bold{x}(k+N-1|k) x(k+N1∣k),然后再加上区间结束后的第一个状态 x ( k + N ∣ k ) \bold{x}(k+N|k) x(k+Nk),将这些系统的状态整合成一个向量

X k = [ x ( k ∣ k ) x ( k + 1 ∣ k ) ⋮ x ( k + i ∣ k ) x ( k + N ∣ k ) ] \bold{X}_k = \begin{bmatrix} \bold{x}(k|k) \\ \bold{x}(k+1|k) \\ \vdots \\ \bold{x}(k+i|k) \\ \bold{x}(k+N|k) \end{bmatrix} Xk= x(kk)x(k+1∣k)x(k+ik)x(k+Nk)

假设系统的输出 y = x \bold{y}=\bold{x} y=x,设定的参考值 r = 0 \bold{r}=0 r=0,那么系统的误差为 e = y − r = x − 0 = x \bold{e}=\bold{y}-\bold{r}=\bold{x}-0 = \bold{x} e=yr=x0=x,为了最优化误差和最优化输入,我们可以这样表示代价函数(Cost Function)

min ⁡ u J = ∑ i = 0 N − 1 ( x ( k + i ∣ k ) T Q x ( k + i ∣ k ) + u ( k + i ∣ k ) T R u ( k + i ∣ k ) ) + x ( k + N ) T F x ( k + N ) ⏟ Terminal Cost \min_\bold{u} J = \sum^{N-1}_{i=0} \Big(\bold{x}(k+i|k)^TQ \bold{x}(k+i|k) + \bold{u}(k+i|k)^TR \bold{u}(k+i|k) \Big) + \underbrace{\bold{x}(k+N)^T F \bold{x}(k+N)}_{\text{Terminal Cost}} uminJ=i=0N1(x(k+ik)TQx(k+ik)+u(k+ik)TRu(k+ik))+Terminal Cost x(k+N)TFx(k+N)

但是乍一看这并不是二次规划的形式,我们可以通过化简将其转化为标准的二次规划形式。

k k k时刻,我们的系统状态可以表示为

x ( k ∣ k ) = x k x ( k + 1 ∣ k ) = A x ( k ∣ k ) + B u ( k ∣ k ) = A x k + B u ( k ∣ k ) x ( k + 2 ∣ k ) = A x ( k + 1 ∣ k ) + B u ( k ∣ k ) = A 2 x k + A B u ( k ∣ k ) + B u ( k + 1 ∣ k ) ⋮ x ( k + N ∣ k ) = A N x k + A N − 1 B u ( k ∣ k ) + ⋯ + B u ( k + N − 1 ∣ k ) \begin{align*} \bold{x}(k|k) & = \bold{x}_k \\ \bold{x}(k+1|k) & = A \bold{x}(k|k) + B\bold{u}(k|k) = A\bold{x}_k + B\bold{u}(k|k) \\ \bold{x}(k+2|k) & = A \bold{x}(k+1|k) + B\bold{u}(k|k) = A^2\bold{x}_k + AB\bold{u}(k|k) + B\bold{u}(k+1|k) \\ \vdots \\ \bold{x}(k+N|k) & = A^N \bold{x}_k + A^{N-1}B\bold{u}(k|k) + \cdots + B \bold{u}(k+N-1|k) \end{align*} x(kk)x(k+1∣k)x(k+2∣k)x(k+Nk)=xk=Ax(kk)+Bu(kk)=Axk+Bu(kk)=Ax(k+1∣k)+Bu(kk)=A2xk+ABu(kk)+Bu(k+1∣k)=ANxk+AN1Bu(kk)++Bu(k+N1∣k)

左边即为 X k \bold{X}_k Xk,然后将右边写成矩阵的形式

X k = [ I A A 2 ⋮ A N ] ⏟ M x k + [ 0 0 ⋯ 0 ⋮ ⋮ ⋱ ⋮ 0 0 ⋯ 0 B 0 ⋯ 0 A B B ⋯ 0 ⋮ ⋮ ⋱ ⋮ A N − 1 B A N − 2 B ⋯ B ] ⏟ C U k X k = M x k + C U k \begin{align*} \bold{X}_k & = \underbrace{\begin{bmatrix} I \\ A \\ A^2 \\ \vdots \\ A^N \end{bmatrix}}_{M} \bold{x}_k + \underbrace{\begin{bmatrix} 0 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 0 \\ B & 0 & \cdots & 0 \\ AB & B & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ A^{N-1}B & A^{N-2}B & \cdots & B \end{bmatrix}}_{C} \bold{U}_k \\ \bold{X}_k & = M \bold{x}_k + C \bold{U}_k \end{align*} XkXk=M IAA2AN xk+C 00BABAN1B000BAN2B0000B Uk=Mxk+CUk

其中 M M M的前 n n n行都是 0 0 0。接下来,我们来将代价函数化成QP的形式

J = ∑ i = 0 N − 1 ( x ( k + i ∣ k ) T Q x ( k + i ∣ k ) + u ( k + i ∣ k ) T R u ( k + i ∣ k ) ) + x ( k + N ) T F x ( k + N ) = x ( k ∣ k ) T Q x ( k ∣ k ) + x ( k + 1 ∣ k ) T Q x ( k + 1 ∣ k ) + ⋯ + x ( k + N − 1 ∣ k ) T Q x ( k + N − 1 ∣ k ) + x ( k + N ∣ k ) T Q x ( k + N ∣ k ) + ∑ i = 0 N − 1 u ( k + i ∣ k ) T R u ( k + i ∣ k ) = [ x ( k ∣ k ) x ( k + 1 ∣ k ) ⋮ x ( k + i ∣ k ) x ( k + N ∣ k ) ] T [ Q Q Q ⋱ F ] ⏟ Q ˉ [ x ( k ∣ k ) x ( k + 1 ∣ k ) ⋮ x ( k + i ∣ k ) x ( k + N ∣ k ) ] + [ u ( k ∣ k ) u ( k + 1 ∣ k ) ⋮ u ( k + i ∣ k ) u ( k + N − 1 ∣ k ) ] T [ R R R ⋱ R ] ⏟ R ˉ [ u ( k ∣ k ) u ( k + 1 ∣ k ) ⋮ u ( k + i ∣ k ) u ( k + N − 1 ∣ k ) ] = X k T Q ˉ X k + U k R ˉ U k \begin{align*} J & = \sum^{N-1}_{i=0} \Big(\bold{x}(k+i|k)^TQ \bold{x}(k+i|k) + \bold{u}(k+i|k)^TR \bold{u}(k+i|k) \Big) + \bold{x}(k+N)^T F \bold{x}(k+N) \\ & = \bold{x}(k|k)^TQ\bold{x}(k|k) + \bold{x}(k+1|k)^TQ\bold{x}(k+1|k) + \cdots + \bold{x}(k+N-1|k)^TQ\bold{x}(k+N-1|k) + \bold{x}(k+N|k)^TQ\bold{x}(k+N|k) \\ & + \sum^{N-1}_{i=0}\bold{u}(k+i|k)^TR\bold{u}(k+i|k) \\ & = \begin{bmatrix} \bold{x}(k|k) \\ \bold{x}(k+1|k) \\ \vdots \\ \bold{x}(k+i|k) \\ \bold{x}(k+N|k) \end{bmatrix}^T \underbrace{\begin{bmatrix} Q & & & &\\ & Q & & &\\ & & Q & &\\ & & & \ddots & \\ & & & & F \end{bmatrix}}_{\bar{Q}}\begin{bmatrix} \bold{x}(k|k) \\ \bold{x}(k+1|k) \\ \vdots \\ \bold{x}(k+i|k) \\ \bold{x}(k+N|k) \end{bmatrix} + \begin{bmatrix} \bold{u}(k|k) \\ \bold{u}(k+1|k) \\ \vdots \\ \bold{u}(k+i|k) \\ \bold{u}(k+N-1|k) \end{bmatrix}^T \underbrace{\begin{bmatrix} R & & & &\\ & R & & &\\ & & R & &\\ & & & \ddots & \\ & & & & R \end{bmatrix}}_{\bar{R}}\begin{bmatrix} \bold{u}(k|k) \\ \bold{u}(k+1|k) \\ \vdots \\ \bold{u}(k+i|k) \\ \bold{u}(k+N-1|k) \end{bmatrix} \\ & = \bold{X}_k^T \bar{Q} \bold{X}_k + \bold{U}_k \bar{R} \bold{U}_k \end{align*} J=i=0N1(x(k+ik)TQx(k+ik)+u(k+ik)TRu(k+ik))+x(k+N)TFx(k+N)=x(kk)TQx(kk)+x(k+1∣k)TQx(k+1∣k)++x(k+N1∣k)TQx(k+N1∣k)+x(k+Nk)TQx(k+Nk)+i=0N1u(k+ik)TRu(k+ik)= x(kk)x(k+1∣k)x(k+ik)x(k+Nk) TQˉ QQQF x(kk)x(k+1∣k)x(k+ik)x(k+Nk) + u(kk)u(k+1∣k)u(k+ik)u(k+N1∣k) TRˉ RRRR u(kk)u(k+1∣k)u(k+ik)u(k+N1∣k) =XkTQˉXk+UkRˉUk

然后再将前面推导的条件带入

J = X k T Q ˉ X k + U k R ˉ U k = ( M x k + C U k ) T Q ˉ ( M x k + C U k ) + U k R ˉ U k = x k T M T Q ˉ M x k + U k T C T Q ˉ M x k + x k T M T Q ˉ C ⏟ 2 x T C T Q ˉ M U k U k + U k T C T Q ˉ C U k + U k R ˉ U k = x k T M T Q ˉ M x k + 2 x T C T Q ˉ M U k U k + U k T C T Q ˉ C U k + U k R ˉ U k \begin{align*} J & = \bold{X}_k^T \bar{Q} \bold{X}_k + \bold{U}_k \bar{R} \bold{U}_k \\ & = (M \bold{x}_k + C \bold{U}_k)^T \bar{Q}(M \bold{x}_k + C \bold{U}_k) + \bold{U}_k \bar{R} \bold{U}_k \\ & = \bold{x}_k^TM^T\bar{Q}M\bold{x}_k + \underbrace{\bold{U}_k^TC^T\bar{Q}M\bold{x}_k + \bold{x}_k^TM^T\bar{Q}C}_{2\bold{x}^TC^T\bar{Q}M\bold{U}_k} \bold{U}_k + \bold{U}_k^TC^T\bar{Q}C \bold{U}_k + \bold{U}_k \bar{R} \bold{U}_k \\ & = \bold{x}_k^TM^T\bar{Q}M\bold{x}_k + 2\bold{x}^TC^T\bar{Q}M\bold{U}_k \bold{U}_k + \bold{U}_k^TC^T\bar{Q}C \bold{U}_k + \bold{U}_k \bar{R} \bold{U}_k \end{align*} J=XkTQˉXk+UkRˉUk=(Mxk+CUk)TQˉ(Mxk+CUk)+UkRˉUk=xkTMTQˉMxk+2xTCTQˉMUk UkTCTQˉMxk+xkTMTQˉCUk+UkTCTQˉCUk+UkRˉUk=xkTMTQˉMxk+2xTCTQˉMUkUk+UkTCTQˉCUk+UkRˉUk

其中 G = M T Q ˉ M G=M^T\bar{Q}M G=MTQˉM E = C T Q ˉ M E=C^T\bar{Q}M E=CTQˉM H = C T R ˉ C + R ˉ H=C^T\bar{R}C+\bar{R} H=CTRˉC+Rˉ,那么 J J J可以化简为:

J = x k T G x k + 2 x k T E U k + U k T H U k J = \bold{x}_k^T G \bold{x}_k + 2\bold{x}_k^T E \bold{U}_k + \bold{U}_k^T H \bold{U}_k J=xkTGxk+2xkTEUk+UkTHUk

其中 x k T G x k \bold{x}_k^T G \bold{x}_k xkTGxk是初始状态,是一个常量,在优化的过程中可以忽略。最终的代价函数可以表示为

min ⁡ U J = x k T G x k + 2 x k T E U k + U k T H U k G = M T Q ˉ M E = C T Q ˉ M H = C T R ˉ C + R ˉ Q ˉ = [ Q ⋯ ⋮ Q ⋮ ⋯ F ] , R ˉ = [ R ⋯ ⋮ ⋱ ⋮ ⋯ R ] \min_\bold{U} J = \bold{x}_k^T G \bold{x}_k + 2\bold{x}_k^T E \bold{U}_k + \bold{U}_k^T H \bold{U}_k \\ G=M^T\bar{Q}M \\ E=C^T\bar{Q}M \\ H=C^T\bar{R}C+\bar{R} \\ \bar{Q} = \begin{bmatrix} Q & \cdots & \\ \vdots & Q & \vdots \\ & \cdots & F \end{bmatrix}, \bar{R} = \begin{bmatrix} R & \cdots & \\ \vdots & \ddots & \vdots \\ & \cdots & R \end{bmatrix} UminJ=xkTGxk+2xkTEUk+UkTHUkG=MTQˉME=CTQˉMH=CTRˉC+RˉQˉ= QQF ,Rˉ= RR

这就是一个标准的QP问题。

5. MPC总结

5.1 MPC的优势劣势

😄MPC的优势在于:

  • 可以处理多输入多数出的系统(MIMO),PID控制只能在一个PID环内控制一个系统状态,当系统状态相互影响的时候PID控制往往难以设计,MPC就体现出了其优势
  • MPC的另一个优势在于可以处理约束条件,约束很重要,因为违反它们会导致不良后果。

😄MPC的不足在于:

  • MPC是在线滚动优化的,所以需要比较强的算力。

5.2 MPC的衍生算法

😄如何选择合适的MPC?

自适应MPC(Adaptive MPC)

在自适应MPC 中,线性模型是随着工作条件的变化而动态计算的,并且在每个时间步长,您都可以使用此线性模型更新。MPC控制器使用的内部被控对象模型,请注意,在自适应MPC 中,优化问题的结构在不同的工作点上保持不变。这意味着在预测范围内,状态数量和约束数量不会因不同的操作条件而改变。

Image

增益调度MPC(Gain-scheduled MPC)

如果它们确实发生了变化,则应使用增益调度MPC。在增益调度MPC 中,您可以在感兴趣的工作点进行离线线性化,并为每个工作点设计一个线性MPC控制器。每个控制器彼此独立,因此可能具有不同数量的状态和不同数量的约束。

Image

小结:

如果被控对象是非线性的,但可以通过线性模型逼近,则可以使用自适应MPC 控制器和如果被控对象是非线性的且状态的维度和约束的数量会发生变化,那么应该使用增益调度的MPC控制器。如果优化问题的结构在不同的工作条件下没有变化,则应使用自适应 MPC;但是,如果该结构有变化,则使用增益调度 MPC;如果因您有一个无法通过线性化进行良好逼近的高度非线性系统,从而导致以上这些方法都不起作用,则可以使用非线性MPC。具体可以如下图所示:

Image

6. 示例实现

待完善

Reference

[1]MPC模型预测控制器
[2]Understanding Model Predictive Control
[3]CasADi_MPC_MHE_Python
[4]MPC-and-MHE-implementation-in-MATLAB-using-Casadi
[5]MPC and MHE implementation in Matlab using Casadi

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

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

相关文章

基于51单片机的篮球计分器设计

一.硬件方案 本设计用由AT89C51编程控制LED七段数码管作显示的球赛计时计分系统。该系统具有赛程定时设置、赛程时间暂停、及时刷新甲乙双方的成绩等功能。 电路主要由STC89C52单片机最小系统数码管显示模块数码管驱动模块蜂鸣器模块按键模块; 二.设计功能 &…

哔哩哔哩视频URL解析原理

哔哩哔哩视频URL解析原理 视频网址解析视频的原理通常涉及以下几个步骤: 1、获取视频页面源代码:通过HTTP请求获取视频所在网页的HTML源代码。这一步通常需要处理反爬虫机制,如验证码或用户登录。 2、解析页面源代码:分析HTML源代…

Transformer学习理解

1.前言 本文介绍当下人工智能领域的基石与核心结构模型——Transformer,为什么说它是基石,因为以ChatGPT为代表的聊 天机器人以及各种有望通向AGI(通用人工智能)的道路上均在采用的Transformer。 Transformer也是当下NLP任…

【上海交大】博士生年度进展报告模板

上海交通大学 博士生年度进展报告模板 比较不好找,在交我办中发起申请流程后才能看到链接,链接如下: https://www.gs.sjtu.edu.cn/xzzx/pygl/15

爬取CSDN博文到本地(包含图片,标签等信息)

文章目录 csdnToMD改进将CSDN文章转化为Markdown文档那有什么办法快速得到md文档?例如:获取单个文章markdown获取所有的文章markdown 项目中待解决的问题 csdnToMD 项目原作者:https://gitee.com/liushili888/csdn-is—mark-down 改进后仓库…

Z语言学习——基于通讯案例

目录 1数据类型 2初始状态 3 Alice的消息发送 4 Bob接收与发送消息 5 Alice接收消息 6消息的增删改查 6.1 删除消息 6.2查询消息 6.3修改/增加消息 7定理证明——重要目的 案例背景: (1)构建一个交互式的通讯方案; (2)攻击者控制了所有的通讯…

眼见不一定为实之MySQL中的不可见字符

目录 前言 一、问题的由来 1、需求背景 2、数据表结构 二、定位问题 1、初步的问题 2、编码是否有问题 3、依然回到字符本身 三、深入字符本身 1、回归本质 2、数据库解决之道 3、代码层解决 四、总结 前言 在开始今天的博客内容之前,正在看博客的您先来…

Element-UI实现el-dialog弹框拖拽功能

在实际开发中,会发现有些系统,弹框是可以在浏览器的可见区域自由拖拽的,这极大方便用户的操作。但在查看Element-UI中弹框(el-dialog)组件的文档时,发现并未实现这一功能。不过也无须担心,vue中…

Day 28:2748. 美丽下标对的数目

Leetcode 2748. 美丽下标对的数目 给你一个下标从 0 开始的整数数组 nums 。如果下标对 i、j 满足 0 ≤ i < j < nums.length &#xff0c;如果 nums[i] 的 第一个数字 和 nums[j] 的 最后一个数字 互质 &#xff0c;则认为 nums[i] 和 nums[j] 是一组 美丽下标对 。 返回…

Linux系统之ARP命令的基本使用

Linux系统之ARP命令的基本使用 一、ARP介绍二、ARP命令帮助2.1 ARP的help帮助信息2.2 ARP命令的帮助解释 三、ARP命令的基本使用3.1 查看ARP缓存3.2 显示详细信息3.3 添加静态arp映射3.4 删除指定主机的ARP条目3.5 从文件读取并添加条目3.6 清除ARP缓存 四、注意事项五、总结 一…

wins系统资源监视器任务管理器运行监控CPU、内存、磁盘、网络运行状态

目录 1.Windows系统资源监视器的详细介绍2.通过任务管理器打开资源监视器3.任务管理中总体观察观察cpu、pid、应用程序、I/O次数或者说读写字节数 4.观察CPU观察cpu核心数&#xff0c;以及哪些占用cpu频率过高 5.观察内存观察各个应用占用的内存大小和对应线程 6.观察磁盘活动观…

【前端技巧】css篇

利用counter实现计数器 counter-reset&#xff1a;为计数器设置名称&#xff0c;语法如下&#xff1a; counter-rese: <idntifier><integer>第一个参数为变量名称&#xff0c;第二个参数为初始值&#xff0c;默认为0 counter-increment&#xff1a;设置计数器增…

LabVIEW与3D相机开发高精度表面检测系统

使用LabVIEW与3D相机开发一个高精度表面检测系统。该系统能够实时获取三维图像&#xff0c;进行精细的表面分析&#xff0c;广泛应用于工业质量控制、自动化检测和科学研究等领域。通过真实案例&#xff0c;展示开发过程中的关键步骤、挑战及解决方案&#xff0c;确保系统的高性…

宕机了, redis如何保证数据不丢?

前言 如果有人问你&#xff1a;"你会把 Redis 用在什么业务场景下&#xff1f;" 我想你大概率会说&#xff1a;"我会把它当作缓存使用&#xff0c;因为它把后端数据库中的数据存储在内存中&#xff0c;然后直接从内存中读取数据&#xff0c;响应速度会非常快。…

【Linux从入门到放弃】进程地址空间

&#x1f9d1;‍&#x1f4bb;作者&#xff1a; 情话0.0 &#x1f4dd;专栏&#xff1a;《Linux从入门到放弃》 &#x1f466;个人简介&#xff1a;一名双非编程菜鸟&#xff0c;在这里分享自己的编程学习笔记&#xff0c;欢迎大家的指正与点赞&#xff0c;谢谢&#xff01; 进…

如何更换OpenHarmony SDK API 10

OpenHarmony社区已经发布OpenHarmony SDK API 10 beta版本&#xff0c;有些 Sample案例 也有需要API10。那么如何替换使用新的OpenHarmony SDK API 10呢&#xff1f;本文做个记录。 1、如何获取OpenHarmony SDK 1.1 每日构建流水线 可以从OpenHarmony每日构建站点获取最新的…

【网络安全的神秘世界】已解决Failed to start proxy service on 127.0.0.1:8080

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 解决burpsuite无法在 127.0.0.1&#xff1a;8080 上启动代理服务端口被占用以及抓不到本地包的问题 Burpsuite无法启动proxy…

定个小目标之刷LeetCode热题(25)

这道题采用的解法是桶排序&#xff0c;画草图如下 代码如下 //基于桶排序求解「前 K 个高频元素」 class Solution {public int[] topKFrequent(int[] nums, int k) {HashMap<Integer, Integer> map new HashMap();for (int num : nums) {if (map.containsKey(num)) {m…

【安防天下】模拟视频监控系统——模拟监控系统的构成视频采集设备

文章目录 1 模拟监控系统的构成2 视频采集设备2.1 摄像机相关技术2.1.1 摄像机的工作原理2.1.2 摄像机的分类2.1.3 摄像机的主要参数 2.2 镜头相关介绍2.2.1 镜头的主要分类2.2.2 镜头的主要参数 1 模拟监控系统的构成 模拟视频监控系统又称闭路电视监控系统&#xff0c; 一般…

htb_Blurry

端口扫描 80 按照教程注册安装clear ml 加载configuration的时候会报错 将json里的API&#xff0c;File Store的host都添加到/etc/hosts中 即可成功初始化 查找clear ml漏洞 发现一个cve-2024-24590 下面是一个利用脚本&#xff0c;但不能直接用 ClearML-vulnerability-…