写在前面:
  本文为科研理论笔记的第二篇,其余笔记目录传送门:

理论笔记专栏目录

  介绍结束下面开始进入正题:

1 基本概念

1.1 最优控制

​   最优控制(optimal control):在约束条件下的最优表现,约束条件即物理限制,而对于最优的评判往往需要具体问题具体分析。

​   一个SISO系统的框图如下所示:


​ 对于误差 e e e,从轨迹跟踪的角度出发, ∫ 0 t e 2 d t \int_{0}^{t} {e^2}dt ∫0t​e2dt 越小表示系统追踪效果越好;而从输入的角度出发, ∫ 0 t u 2 d t \int_{0}^{t}{u^2}dt ∫0t​u2dt 越小表示系统的输入(能耗)越小。在上述条件下,即可构造系统的代价函数(cost function): J = ∫ 0 t q e 2 + r u 2 d t J=\int_{0}^{t}{qe^2+ru^2}dt J=∫0t​qe2+ru2dt。其中的 q q q和 r r r称为调节参数,最优化过程即使设计一个控制器使得 J = J m i n J=J_{min} J=Jmin​。若使得 q > > r q>>r q>>r 则表示在最优化的过程中更看重误差,反之若 r > > q r>>q r>>q 则表示在最优化的过程中更看重输入。

​   拓展到MIMO系统,系统的状态空间方程一般可以描述为:
{ x ˙ = A x + B u y = C x \begin{cases} \dot x=Ax+Bu\\ y=Cx \end{cases} {x˙=Ax+Buy=Cx​
​其中 x = [ x 1 , ⋯ , x n ] T x=[x_1,\cdots,x_n]^T x=[x1​,⋯,xn​]T为系统状态, u = [ u 1 , ⋯ , u n ] T u=[u_1,\cdots,u_n]^T u=[u1​,⋯,un​]T为系统输入。

​   类似SISO系统,可设 J = ∫ 0 x e T Q e + u T R u d t J=\int_0^x{e^TQe+u^TRu}dt J=∫0x​eTQe+uTRudt 。其中对角阵 Q = [ q 1 ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ q n ] Q=\begin{bmatrix}q_1&\cdots &0 \\ \vdots&\ddots&\vdots \\0&\cdots&q_n\end{bmatrix} Q=⎣⎢⎡​q1​⋮0​⋯⋱⋯​0⋮qn​​⎦⎥⎤​和 R = [ r 1 ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ r n ] R=\begin{bmatrix}r_1&\cdots &0 \\ \vdots&\ddots&\vdots \\0&\cdots&r_n\end{bmatrix} R=⎣⎢⎡​r1​⋮0​⋯⋱⋯​0⋮rn​​⎦⎥⎤​称为调节矩阵, q 1 ⋯ q n 、 r 1 ⋯ r n q_1\cdots q_n、r_1\cdots r_n q1​⋯qn​、r1​⋯rn​ 称为最优化过程中的权重系数,可相应的调整 x 1 ⋯ x n 、 u 1 ⋯ u n x_1\cdots x_n、u_1\cdots u_n x1​⋯xn​、u1​⋯un​ 的优化权重。

1.2 MPC

​   MPC(model predictive control):模型预测控制,指通过模型预测系统在某一未来时间段内的表现来进行优化控制,因为其多用于数位控制,所以在分析时主要采用离散型状态空间表达式来进行分析,例如对于四轮阿克曼底盘的小车,其离散状态空间表达式可参考前一篇笔记:

四轮移动机器人(小车)数学建模

​   基于模型的预测:在MPC算法中,需要一个描述对象动态行为的模型,这个模型的作用是预测系统未来的动态,即能够根据系统 k k k时刻的状态 x k x_k xk​和 k k k时刻的控制输入 u k u_k uk​,预测到 k + 1 k+1 k+1时刻的输出 y k + 1 y_{k+1} yk+1​。在这里 k k k时刻的输入正是用来控制系统 k + 1 k+1 k+1时刻的输出,使其最大限度的接近 k + 1 k+1 k+1时刻的输出期望值。故我们强调的是该模型的预测作用,而不是模型的形式。

​   预测区间:规定了希望未来能被预测到多久。从当前时刻 k k k到 k + N k+N k+N的时间区间。

​   控制区间:控制区间的选择就是一个最优化的问题,其代价函数 J = ∑ i = 0 N − 1 e k + i T Q e k + i + u k + i T R u k + i + e k + N T F e k + N J=\sum_{i=0}^{N-1}{e_{k+i}^TQe_{k+i}+u_{k+i}^TRu_{k+i}+e_{k+N}^TFe_{k+N}} J=∑i=0N−1​ek+iT​Qek+i​+uk+iT​Ruk+i​+ek+NT​Fek+N​ ,其中 e k + N T F e k + N e_{k+N}^TFe_{k+N} ek+NT​Fek+N​ 表示最终代价,即最后 k + N k+N k+N时刻的误差代价。

​   MPC主要分为三步:

​   step1:在 k k k时刻(当前时刻),测量或估计系统的当前状态 x k x_k xk​ (若 x k x_k xk​不可直接测得,则一般采用状态观测器进行估计);

​   step2:基于预测控制量 u k 、 u k + 1 . . . u k + N − 1 u_k、u_{k+1}...u_{k+N-1} uk​、uk+1​...uk+N−1​ 来进行最优化控制;

​   step3:只将 u k u_k uk​ 施加给系统,进行滚动优化控制。

2 最优化建模

​   MPC的重点在于step2中如何进行最优化控制,最优化的方法很多,下面主要推导一种常用的二次规划(Quadratic Programming)的方法。

​   二次规划的一般形式为: m i n ( Z T Q Z + C T Z ) min(Z^TQZ+C^TZ) min(ZTQZ+CTZ),其中 Z T Q Z Z^TQZ ZTQZ为二次型项, C T Z C^TZ CTZ为线性项。对于二次规划问题的处理当前Matlab、Python、C++等都有很成熟的方法了,所以关键就在于如何将自己的模型化为二次规划的一般形式。

​   设系统的线性离散状态空间表达式为 x ( k + 1 ) = A x ( k ) + B u ( k ) x_{(k+1)}=Ax_{(k)}+Bu_{(k)} x(k+1)​=Ax(k)​+Bu(k)​ ,其中 x = [ x 1 , ⋯ , x n ] T , u = [ u 1 , ⋯ , u p ] T x=[x_1,\cdots,x_n]^T,u=[u_1,\cdots,u_p]^T x=[x1​,⋯,xn​]T,u=[u1​,⋯,up​]T,状态矩阵 A A A为 n × n n\times n n×n矩阵,输入矩阵 B B B为 n × p n\times p n×p矩阵。

​   在 k k k时刻,定义:
X k = [ x ( k ∣ k ) x ( k + 1 ∣ k ) ⋮ x ( k + N ∣ k ) ] ( N + 1 ) n × 1 ; U k = [ u ( k ∣ k ) u ( k + 1 ∣ k ) ⋮ u ( k + N − 1 ∣ k ) ] N p × 1 X_k=\begin{bmatrix} x_{(k|k)}\\ x_{(k+1|k)}\\ \vdots\\ x_{(k+N|k)}\\ \end{bmatrix}_{(N+1)n\times1} ; U_k=\begin{bmatrix} u_{(k|k)}\\ u_{(k+1|k)}\\ \vdots\\ u_{(k+N-1|k)}\\ \end{bmatrix}_{Np\times1} Xk​=⎣⎢⎢⎢⎡​x(k∣k)​x(k+1∣k)​⋮x(k+N∣k)​​⎦⎥⎥⎥⎤​(N+1)n×1​;Uk​=⎣⎢⎢⎢⎡​u(k∣k)​u(k+1∣k)​⋮u(k+N−1∣k)​​⎦⎥⎥⎥⎤​Np×1​
其中 N N N为预测区间,以 x ( k + 1 ∣ k ) x{(k+1|k)} x(k+1∣k)为例,括号内|左边的 k + 1 k+1 k+1表示预测的 k + 1 k+1 k+1时刻的状态量,括号内|右边的 k k k表示在 k k k时刻做出的预测。

​   为了简化分析,设输入 y = x y=x y=x,参考量 r = 0 r=0 r=0,则误差 e = y − r = x e=y-r=x e=y−r=x,代价函数可化为:
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 ∣ k ) T F x ( k + N ∣ k ) 即 : J = 误 差 加 权 和 + 输 入 加 权 和 + 终 端 误 差 J=\sum_{i=0}^{N-1}{x_{(k+i|k)}^TQx_{(k+i|k)}+u_{(k+i|k)}^TRu_{(k+i|k)}+x_{(k+N|k)}^TFx_{(k+N|k)}}\\ 即:J=误差加权和+输入加权和+终端误差 J=i=0∑N−1​x(k+i∣k)T​Qx(k+i∣k)​+u(k+i∣k)T​Ru(k+i∣k)​+x(k+N∣k)T​Fx(k+N∣k)​即:J=误差加权和+输入加权和+终端误差
​ 由系统初始条件 x ( k ∣ k ) = x ( k ) x_{(k|k)}=x_{(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 + 1 ∣ 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 ) ; x_{(k+1|k)}=Ax_{(k|k)}+Bu_{(k|k)}=Ax_{(k)}+Bu_{(k|k)};\\ x_{(k+2|k)}=Ax_{(k+1|k)}+Bu_{(k+1|k)}=A^2x_{(k)}+ABu_{(k|k)}+Bu_{(k+1|k)};\\ \vdots \\ x_{(k+N|k)}=A^nx_{(k)}+A^{N-1}Bu_{(k|k)}+\cdots+Bu_{(k+N-1|k)}; x(k+1∣k)​=Ax(k∣k)​+Bu(k∣k)​=Ax(k)​+Bu(k∣k)​;x(k+2∣k)​=Ax(k+1∣k)​+Bu(k+1∣k)​=A2x(k)​+ABu(k∣k)​+Bu(k+1∣k)​;⋮x(k+N∣k)​=Anx(k)​+AN−1Bu(k∣k)​+⋯+Bu(k+N−1∣k)​;
​ 整理上面 N + 1 N+1 N+1个式子可得(其中的 0 0 0表示 n × p n\times p n×p 的零矩阵):
X k = [ I A A 2 ⋮ A N ] x ( k ) + [ 0 0 ⋯ 0 B 0 ⋯ 0 A B B ⋯ 0 ⋮ ⋮ ⋱ ⋮ A N − 1 B A N − 2 B ⋯ B ] U k X_k=\begin{bmatrix}I\\ A\\ A^2\\ \vdots\\ A^N\end{bmatrix}x_{(k)}+ \begin{bmatrix}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}U_k Xk​=⎣⎢⎢⎢⎢⎢⎡​IAA2⋮AN​⎦⎥⎥⎥⎥⎥⎤​x(k)​+⎣⎢⎢⎢⎢⎢⎡​0BAB⋮AN−1B​00B⋮AN−2B​⋯⋯⋯⋱⋯​000⋮B​⎦⎥⎥⎥⎥⎥⎤​Uk​
​ 定义:
M = [ I A A 2 ⋮ A N ] ( N + 1 ) n × n ; C = [ 0 0 ⋯ 0 B 0 ⋯ 0 A B B ⋯ 0 ⋮ ⋮ ⋱ ⋮ A N − 1 B A N − 2 B ⋯ B ] ( N + 1 ) n × N p M=\begin{bmatrix}I\\ A\\ A^2\\ \vdots\\ A^N\end{bmatrix}_{(N+1)n\times n}; C=\begin{bmatrix}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}_{(N+1)n\times Np} M=⎣⎢⎢⎢⎢⎢⎡​IAA2⋮AN​⎦⎥⎥⎥⎥⎥⎤​(N+1)n×n​;C=⎣⎢⎢⎢⎢⎢⎡​0BAB⋮AN−1B​00B⋮AN−2B​⋯⋯⋯⋱⋯​000⋮B​⎦⎥⎥⎥⎥⎥⎤​(N+1)n×Np​
​ 即有: X k = M x ( k ) + C U k X_k=Mx_{(k)}+CU_k Xk​=Mx(k)​+CUk​,其意义是由 k k k时刻的状态量和预测输入量可得出预测状态量。

​   再来将代价函数 J J J化为紧凑形式,例如其中误差加权和及终断误差可化为:
∑ i = 0 N − 1 x ( k + i ∣ k ) T Q x ( k + i ∣ k ) + x ( k + N ∣ k ) T F x ( k + N ∣ k ) = 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 F x ( k + N ∣ k ) = X k T [ Q ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ F ] X k \sum_{i=0}^{N-1}{x_{(k+i|k)}^TQx_{(k+i|k)}}+x_{(k+N|k)}^TFx_{(k+N|k)}\\ =x_{(k|k)}^TQx_{(k|k)}+x_{(k+1|k)}^TQx_{(k+1|k)}+\cdots+x_{(k+N-1|k)}^TQx_{(k+N-1|k)}+x_{(k+N|k)}^TFx_{(k+N|k)}\\ =X_k^T\begin{bmatrix}Q&\cdots&0\\ \vdots&\ddots&\vdots\\ 0&\cdots&F\end{bmatrix}X_k i=0∑N−1​x(k+i∣k)T​Qx(k+i∣k)​+x(k+N∣k)T​Fx(k+N∣k)​=x(k∣k)T​Qx(k∣k)​+x(k+1∣k)T​Qx(k+1∣k)​+⋯+x(k+N−1∣k)T​Qx(k+N−1∣k)​+x(k+N∣k)T​Fx(k+N∣k)​=XkT​⎣⎢⎡​Q⋮0​⋯⋱⋯​0⋮F​⎦⎥⎤​Xk​
​ 定义:
Q ‾ = [ Q ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ F ] ; R ‾ = [ R ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ R ] \overline Q=\begin{bmatrix}Q&\cdots&0\\ \vdots&\ddots&\vdots\\ 0&\cdots&F\end{bmatrix};\overline R=\begin{bmatrix}R&\cdots&0\\ \vdots&\ddots&\vdots\\ 0&\cdots&R\end{bmatrix} Q​=⎣⎢⎡​Q⋮0​⋯⋱⋯​0⋮F​⎦⎥⎤​;R=⎣⎢⎡​R⋮0​⋯⋱⋯​0⋮R​⎦⎥⎤​
​ 则有:
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 ∣ k ) T F x ( k + N ∣ k ) = X k T Q ‾ X K + U k T R ‾ U k J=\sum_{i=0}^{N-1}{x_{(k+i|k)}^TQx_{(k+i|k)}+u_{(k+i|k)}^TRu_{(k+i|k)}+x_{(k+N|k)}^TFx_{(k+N|k)}}\\ =X_k^T\overline QX_K+U_k^T\overline RU_k J=i=0∑N−1​x(k+i∣k)T​Qx(k+i∣k)​+u(k+i∣k)T​Ru(k+i∣k)​+x(k+N∣k)T​Fx(k+N∣k)​=XkT​Q​XK​+UkT​RUk​
​ 将 X k = M x ( k ) + C U k X_k=Mx_{(k)}+CU_k Xk​=Mx(k)​+CUk​代入 J = X k T Q ‾ X k + U k T R ‾ U k J=X_k^T\overline QX_k+U_k^T\overline RU_k J=XkT​Q​Xk​+UkT​RUk​:
J = X k T Q ‾ X K + U k T R ‾ U k = ( M x ( k ) + C U k ) T Q ‾ ( M x ( k ) + C U k ) + U k T R ‾ U k = ( x ( k ) T M T + U k T C T ) Q ‾ ( M x ( k ) + C U k ) + U k T R ‾ U k = x ( k ) T M T Q ‾ M x ( k ) + x ( k ) T M T Q ‾ C U k + U k T C T Q ‾ M x ( k ) + U k T C T Q ‾ C U k + U k T R ‾ U k = x ( k ) T M T Q ‾ M x ( k ) + 2 x ( k ) T M T Q ‾ C U k + U k T ( C T Q ‾ C + R ‾ ) U k J=X_k^T\overline QX_K+U_k^T\overline RU_k\\ =(Mx_{(k)}+CU_k)^T\overline Q(Mx_{(k)}+CU_k)+U_k^T\overline RU_k\\ =(x_{(k)}^TM^T+U_k^TC^T)\overline Q(Mx_{(k)}+CU_k)+U_k^T\overline RU_k\\ =x_{(k)}^TM^T\overline QMx_{(k)}+x_{(k)}^TM^T\overline QCU_k+U_k^TC^T\overline QMx_{(k)}+U_k^TC^T\overline QCU_k+U_k^T\overline RU_k\\ =x_{(k)}^TM^T\overline QMx_{(k)}+2x_{(k)}^TM^T\overline QCU_k+U_k^T(C^T\overline QC+\overline R)U_k J=XkT​Q​XK​+UkT​RUk​=(Mx(k)​+CUk​)TQ​(Mx(k)​+CUk​)+UkT​RUk​=(x(k)T​MT+UkT​CT)Q​(Mx(k)​+CUk​)+UkT​RUk​=x(k)T​MTQ​Mx(k)​+x(k)T​MTQ​CUk​+UkT​CTQ​Mx(k)​+UkT​CTQ​CUk​+UkT​RUk​=x(k)T​MTQ​Mx(k)​+2x(k)T​MTQ​CUk​+UkT​(CTQ​C+R)Uk​
​ 定义: G = M T Q ‾ M 、 E = M T Q ‾ C 、 H = C T Q ‾ C + R ‾ G=M^T\overline QM、E=M^T\overline QC、H=C^T\overline QC+\overline R G=MTQ​M、E=MTQ​C、H=CTQ​C+R;即有:
J = x ( k ) T G x ( k ) + U k T H U k + 2 x ( k ) T E U k J=x_{(k)}^TGx_{(k)}+U_k^THU_k+2x_{(k)}^TEU_k J=x(k)T​Gx(k)​+UkT​HUk​+2x(k)T​EUk​
​ 注意到上式第一项 x ( k ) T G x ( k ) x_{(k)}^TGx_{(k)} x(k)T​Gx(k)​仅与初始状态 x ( k ) x_{(k)} x(k)​有关,不影响后续优化,后两项形同 Z T Q Z + C T Z Z^TQZ+C^TZ ZTQZ+CTZ,即可用于二次规划得到理想的输入。
  至此MPC算法就介绍完成啦,上面的公式希望大家初学的时候都能手推一遍以便于更好的理解,最后附上一个简单的matlab例程供大家参考。

MPC例程github传送门,注意科学上网

MPC(模型预测控制)_附matlab例程相关推荐

  1. MPC模型预测控制原理和Matlab以及Python代码实现

    MPC模型预测控制原理和代码 一. 介绍模型预测控制(MPC)原理 简要解释一下最优控制最优控制的目标是在一定的约束条件下达到最优的系统表现,那么要让系统达到最优表现,一般是通过定义损失函数J,通过最 ...

  2. MPC模型预测控制及在Matlab中实现函数定义

    基于b站DR_CAN老师的MPC控制视频[MPC模型预测控制器]4_数学建模推导--Matlab代码详解_哔哩哔哩_bilibili的学习分享如下: 一.研究目的 在约束条件(物理限制)下达到最优的系 ...

  3. MPC模型预测控制+matlab代码实现+simulink仿真实现

    MPC模型预测控制+matlab代码实现 MPC模型预测控制 原理 步骤 matlab代码实现 程序 主程序 函数 参数调试 MPC模型预测控制 原理 步骤 matlab代码实现 程序 主程序 cle ...

  4. MPC模型预测控制学习笔记-2021.10.27

    MPC模型预测控制学习笔记-点击目录就可以跳转 1. 笔者介绍 2. 参考资料 3. MPC分类 4. 数据的标准化与归一化 5. MATLAB-MPC学习笔记 5.1 获取测试信号:gensig( ...

  5. 数学规划模型总结(附MatLab代码)

    数学规划模型总结(附MatLab代码) 概述 定义 一般形式 分类 线性规划(linear programming) 非线性规划(nonlinear programming) 整数规划(integer ...

  6. 基于MPC 模型预测控制的轨迹跟随,横向控制模型,车道保持

    基于MPC 模型预测控制的轨迹跟随,横向控制模型,车道保持,simulink模型 采用二自由度车辆动力学模型,可以自定义车辆参数,自定义目标轨迹,图中为单移线目标轨迹与实际轨迹偏差 ID:485067 ...

  7. 模型预测控制_模型预测控制(MPC)算法之一MAC算法

    引言 随着自动驾驶技术以及机器人控制技术的不断发展及逐渐火热,模型预测控制(MPC)算法作为一种先进的控制算法,其应用范围与领域得到了进一步拓展与延伸.目前提出的模型预测控制算法主要有基于非参数模型的 ...

  8. MPC模型预测控制(二)-MATLAB代码实现

    update:MPC的QQ群 第一个群已经满500人(贫穷使我充不起鹅厂会员),这是第二个群. 群都满了. https://blog.csdn.net/tingfenghanlei/article/d ...

  9. python预测控制_无人驾驶——4.控制之MPC模型预测控制

    源自:<无人驾驶无人驾驶车辆模型预测控制>--龚建伟 参考:https://wenku.baidu.com/view/8e4633d519e8b8f67c1cb9fa.html 0.车辆模 ...

最新文章

  1. mysql int 默认值 为ull_mysql的 约束 数据库设计 数据库 存储 触发器 mysql 权限问题...
  2. linux pid t 头文件_linux系统调用相关头文件
  3. python--从入门到实践--chapter 9 类
  4. 批量部署Linux操作系统的一场革命----Cobbler
  5. ROS入门笔记(七):详解ROS文件系统
  6. 交互式SHELL脚本对话框(whiptail)
  7. WINDOWS对文件签名,算法如何由sha1改为sha256/sha512
  8. OOM框架AutoMapper基本使用(2)
  9. 驱动精灵、人生限速曲线救国
  10. 无盘服务器秒卡 锐起0359,锐起无盘系统问题汇集
  11. 单片机零基础入门(8-5)模块化编程
  12. 【零基础】一文读懂CPU(从二极管到超大规模集成电路)
  13. 忠实履行职责,热忱完成工作,坚持必胜信念,成就辉煌人生——《西点军校的经典法则》
  14. AutoCAD二次开发学习记录一:批量统计dwg文件数据
  15. 基于MATLAB的AM调制解调
  16. 阿里技术专家十五问,真题面试刀刀见肉,走进面试间(答案解析)
  17. 瑞星谷歌合作推免费杀毒软件
  18. 调试AKM4432 DAC驱动问题记录
  19. 测试工程师的一点自省感悟
  20. linux yum安装mysql及配置

热门文章

  1. 加入域提示“不能访问网路位置” 的解决方法
  2. 如何实现外网访问内网ip?公网端口映射或内网映射来解决
  3. 关于Sql语句中的模糊查询like关键字详解
  4. MATLAB Support Package Installer无法正常打开的问题
  5. 期刊论文发表见刊是什么意思
  6. 微信jssdk图片上传给服务器,使用微信JSSDK进行图片选择和上传
  7. 说极路由牛逼的人们,你们用过Tomato DualWAN吗?(三)
  8. 通过硬盘iso文件安装ubuntu
  9. JAVA 开发命名规范——阿里巴巴Java开发手册
  10. back-end 后端开发面试题