模型预测控制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

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

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

相关文章

希喂、K9、弗列加特主食冻干测评:这次,我们去了美国的实验室

主食冻干你有喂过吗? 作为有七年养猫经验的铲屎官,我强烈推荐,真的值得一试! 在宠物经济蓬勃发展的今天,养猫已经成为了一门学问。人们开始追求更加科学、健康的养猫方式。大量喂养案例表明,传统的商业猫粮…

【ARMv8/v9 GIC 系列 2.1 -- GIC SPI 中断的 pending 和 clear pending 配置】

文章目录 GIC Pending 和 Clear PendingGICD_ISPENDR<n>GICD_ICPENDR<n>参数<n>编号解释使用举例设置中断ID 100为挂起状态清除中断ID 100的挂起状态 代码实现小结 GIC Pending 和 Clear Pending 在ARMv8体系结构中&#xff0c;GICD_ISPENDR<n> 和 GI…

C# WPF入门学习番外篇——C#使用WPF连接MySQL数据库

在 C# 中使用 WPF 连接 MySQL 数据库涉及几个步骤&#xff0c;包括安装必要的库&#xff0c;配置连接字符串&#xff0c;编写代码以执行数据库操作等。下面是一个详细的入门教程&#xff0c;帮助你理解如何在 WPF 应用程序中使用 MySQL 数据库。 1. 安装 MySQL 数据库连接器 …

两个方法,批量替换PPT中的字体

经常制作ppt的朋友可能会遇到需要批量替换字体的情况&#xff0c;如果我们想要更换ppt中的字体&#xff0c;今天分享PPT批量替换字体的两个方法。 方法一&#xff1a; 找到功能栏中的编辑选项卡&#xff0c;点击替换 – 替换字体&#xff0c;在里面选择我们想要替换的字体就可…

Humanize,一个很有人情味的 Python 库

目录 01初识 Humanize 为什么选择 Humanize&#xff1f; 安装 Humanize 02时间与日期的处理 时间差的展示 日期的展示 03数字的处理 数字的单位转换 数字的精确度控制 数字的千位分隔符 04文件大小的处理 文件…

JAVA语言开发的一套(智慧工地监管系统源码)让工地变得更加“聪明”

JAVA语言开发的一套&#xff08;智慧工地监管系统源码&#xff09;让工地变得更加“聪明” 数字智慧工地是指利用物联网、大数据、云计算、人工智能等先进技术&#xff0c;对工地进行全面数字化改造和智能化升级&#xff0c;实现工地管理的精细化、高效化和智能化。它通过实时…

ETO MARKETS:美债高额利息——美国财政的不可承受之重

摘要 2024年&#xff0c;美国联邦政府债务的利息支出预计将达到8920亿美元&#xff0c;这一数字比国防开支还要多&#xff0c;凸显了政府债务和利率上升的双重压力。国会预算办公室&#xff08;CBO&#xff09;预测&#xff0c;利息支出占GDP的比例将继续上升&#xff0c;这意…

Apple Phone Memory

Apple Phone Memory 苹果手机内存查询&#xff0c;哪些应用程序&#xff08;app&#xff09;占用内存&#xff1a; 设置 通用 iPhone储存空间 清理下QQ音乐&#xff1a;

远程桌面无法连接,远程桌面连接登录没有成功

在信息技术领域&#xff0c;远程桌面连接作为一种便捷的管理和操作工具&#xff0c;对于企业和个人用户而言都具有极其重要的价值。然而&#xff0c;在实际使用过程中&#xff0c;远程桌面无法连接的问题时常出现&#xff0c;这不仅影响了工作效率&#xff0c;还可能对数据安全…

Matlab数学建模实战应用:案例2 - 传染病传播

目录 前言 一、问题分析 二、模型建立 三、Matlab代码实现 四、模型验证 灵敏度分析 五、模型应用 实例总结 总结 前言 传染病传播模型是公共卫生和流行病学的重要研究内容&#xff0c;通过数学建模可以帮助我们理解传染病的传播规律和趋势&#xff0c;以便制定有效的…

多组学双疾病串扰怎么做?PAN-AD九个机器学习+MR+单细胞,工作量不少

说在前面 “串扰”这个名词听起来高级了一个level&#xff0c;其实就是MR-通路的双疾病联合分析。虽然是筛选标志物的思路&#xff0c;但是工作量不小&#xff0c;作者还收集了13个不同AD自身免疫疾病数据集用于验证自己的机器学习模型&#xff0c;分析就是一些常规的WGCNA、P…

VMware虚拟机三种网络模式设置 - NAT(网络地址转换模式)

一、前言 在前一篇《Bridged&#xff08;桥接模式&#xff09;》中&#xff0c;我详细介绍了虚拟机网络模式设置中的桥接模式。今天详细讲解一下NAT&#xff08;网络地址转换模式&#xff09;。 在虚拟机&#xff08;VM&#xff09;中&#xff0c;NAT&#xff08;Network Addre…

CSS--解决图片变形的方法

原文网址&#xff1a;CSS--解决图片变形的方法_IT利刃出鞘的博客-CSDN博客 简介 本文介绍html文件中图片变形的解决方法。 问题描述 我们经常需要指定所有图片的大小&#xff0c;让它们排列起来时看起来更整齐。但是&#xff0c;如果我们指定了width和height&#xff0c;那…

使用Harbor搭建局域网私有docker镜像库

说明&#xff1a;本文只介绍使用http的方式访问Harbor镜像库&#xff0c;https访问的方式请自行查询。 一、安装harbo 前提条件&#xff1a;已安装好docker。 1.1、安装docker-compose sudo apt install docker-compose1.2、下载Harbor 从Harbor的官方github&#xff0c;下载…

聊聊探索性测试

探索性测试定义及来源&#xff1a;​ 特意度娘了一下&#xff0c;探索性测试的定义&#xff1a; 探索性测试可以说是一种测试思维技术。它没有很多实际的测试方法、技术和工具&#xff0c;但是却是所有测试人员都应该掌握的一种测试思维方式。探索性强调测试人员的主观能动性…

使用opencv合并两个图像

本节的目的 linear blending&#xff08;线性混合&#xff09;使用**addWeighted()**来添加两个图像 原理 (其实我也没太懂&#xff0c;留个坑&#xff0c;感觉本科的时候线代没学好。不对&#xff0c;我本科就没学线代。) 源码分析 源码链接 #include "opencv2/imgc…

Python-gui开发之Pycharm+pyside6/Pyqt6环境搭建

Python-gui开发之Pycharm+pyside6/Pyqt6环境搭建 软件版本一、软件安装1、Python安装2、Pycharm安装3、pyside6或pyqt6安装①安装pyside6②安装PyQt6和pyqt6-tools二、Pycharm项目配置1、插件安装2、新建项目以及环境配置3、包管理安装三、在Pycharm中配置PySide61、pyside6 Qt…

MySQL功能测试-之应用工程

MySQL功能测试-之应用工程 前言pom.xmlapplication.yml 文件common.vo 包ResultVO config 包properties 包DruidConfigPropertyDruidMonitorProperty AutoFillMetaObjectHandlerDruidConfigFluxConfigurationMyBatisPlusConfig controller 包ClientControllerDruidControllerWe…

人工智能产品经理,行业巨头争夺的稀缺人才

前言 在当今这个由数据驱动的时代&#xff0c;人工智能&#xff08;AI&#xff09;正迅速成为推动各行各业创新的核心力量。随着行业巨头纷纷布局人工智能领域&#xff0c;对于专业人才的需求也日益增长。特别是人工智能产品经理这一岗位&#xff0c;缺口高达6.8万&#xff0c…

[机器学习算法] Q学习

Q学习&#xff08;Q-Learning&#xff09;是一种基于值的强化学习算法&#xff0c;用于在给定状态下选择动作&#xff0c;以最大化累积奖励。它通过不断更新一个称为Q表&#xff08;Q-table&#xff09;的表来学习动作的价值。 一、理解基本概念 状态 (State, S) 这是环境的…