Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(二)
Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(二)
- 3. Joint optimization
- 3.1 Marginalization
- 3.1.1 什么是Marginalization
- 3.1.2 Basics of Multi-variate Gauss Distribution
- 3.1.3 Marginalization in covariance and information form
- 3.1.4 Schur Complement
3. Joint optimization
在上一个博客中,我们分别介绍了IMU预积分,LiDAR Relative Measurements,接下来就是非常重要优化环节了,优化过后才可以获得里程计计算结果。在这篇论文中,优化的目标函数主要由三部分构成:marginalization factor, imu-preintegration,以及LiDAR relative measurements,我们首先来看第一个marginalization factor。
3.1 Marginalization
3.1.1 什么是Marginalization
在上一博客中,我们已经知道该篇论文中引入了一个滑窗(Sliding Window),来限制待优化的状态向量数量。如下图所示,我们考虑这样一种情景,假设当前时刻窗口内的优化变量为x1,x2,...,x6x_1,x_2,...,x_6x1,x2,...,x6,且已经对里程计中的目标函数完成了优化,也就是相当于拟合出来了一个概率分布p(x1,x2,...,x6)p(x_1,x_2,...,x_6)p(x1,x2,...,x6),即多维高斯分布对应的均值μ\muμ和协方差矩阵KKK。此时在下一个优化时刻到来之前,我们需要将窗口往后移动一个格子,即开始优化此时窗口内的优化变量x2,x3,...,x7x_2,x_3,...,x_7x2,x3,...,x7,这种过程会贯穿整个估计过程,直至算法停止运行。那么一个明显的问题是,我们在优化拟合出来p(x2,x3,...,x7)p(x_2,x_3,...,x_7)p(x2,x3,...,x7)之前,该怎样处理概率分布p(x1,x2,...,x6)p(x_1,x_2,...,x_6)p(x1,x2,...,x6)呢?
为了更形象的说明这个问题,我们来假设这样一种情景。小明开车想从中国科学技术大学到之心城买件衣服,怕迷路,想时刻估计一下自己到哪了,因此搞了个滑窗,利用gps,轮速计来分析自己当前和过往几个时刻自己开车到哪了。通过各种融合算法,发现自己x1,x2,...,x6x_1,x_2,...,x_6x1,x2,...,x6时的位置分布为p(x1,x2,...,x6)p(x_1,x_2,...,x_6)p(x1,x2,...,x6)发现自己原来刚出东门。然后接着往前开啊,现在滑窗内的状态就是x2,x3,...,x7x_2,x_3,...,x_7x2,x3,...,x7了。那么如何估计我x2,x3,...,x7x_2,x_3,...,x_7x2,x3,...,x7时刻的位置呢?
一种方法就是继续像上一时刻那样用自身的gps和轮速计等融合p(x2,x3,...,x7)p(x_2,x_3,...,x_7)p(x2,x3,...,x7),也就是说我才不管你x1,x2,x3,...,x6x_1,x_2,x_3,...,x_6x1,x2,x3,...,x6时在哪,我只关心p(x2,x3,...,x7)p(x_2,x_3,...,x_7)p(x2,x3,...,x7),计算完发现我去怎么还在东门附近?不是刚路过了吗?是不是算错了?
这时,聪明的副驾驶提醒你,哎这孩子读书读傻了,笨不笨,明明(x1,x2,...,x6)(x_1,x_2,...,x_6)(x1,x2,...,x6)时刻都到p(x1,x2,...,x6)p(x_1,x_2,...,x_6)p(x1,x2,...,x6)了,你咋还给忘了?你这不是黑瞎子掰玉米掰一个扔一个吗?把p(x2,...,x6)p(x_2,...,x_6)p(x2,...,x6)也就是我们刚刚路过东门这个消息加到你的那个什么融合算法里,再算一算我们现在到哪了?小明这才计算出来原来已经到东门前的十字路口了。
这个例子说明,在更新计算p(x2,x3,...,x7)p(x_2,x_3,...,x_7)p(x2,x3,...,x7)时,总共有两种方法,第一种是直接丢掉之前窗口内拟合的分布p(x1,x2,...,x6)p(x_1,x_2,...,x_6)p(x1,x2,...,x6),重新计算估计p(x2,x3,...,x7)p(x_2,x_3,...,x_7)p(x2,x3,...,x7)。但是这种方法有一个比较重要的缺陷就是信息损失,可能p(x2,x3,...,x6)p(x_2,x_3,...,x_6)p(x2,x3,...,x6)内的估计非常准确,而你却把这么重要的信息给直接扔了,这不是败家吗你说?第二种方法就是将p(x1,x2,...,x6)p(x_1,x_2,...,x_6)p(x1,x2,...,x6)中的p(x2,x3,...,x6)p(x_2,x_3,...,x_6)p(x2,x3,...,x6)计算出来,并将p(x2,x3,...,x6)p(x_2,x_3,...,x_6)p(x2,x3,...,x6)作为先验信息加入到新窗口的估计中。那么问题来了,怎样根据p(x1,x2,...,x6)p(x_1,x_2,...,x_6)p(x1,x2,...,x6)计算p(x2,x3,...,x6)p(x_2,x_3,...,x_6)p(x2,x3,...,x6)呢?这个过程就叫做Marginalization。下图能比较清晰严谨的说明这个问题,数理基础比较好的话也能想到我们好像学过这个公式:p(xa)=∫xbp(xa,xb)p(x_a)=\int_{x_b}p(x_a,x_b)p(xa)=∫xbp(xa,xb)。接下来我们从数学的角度严谨的说明一下Marginalization。
3.1.2 Basics of Multi-variate Gauss Distribution
如下图所示,假设有一个系统长这个样子,其中y2y_2y2表示的是室外的温度,y1y_1y1表示的是房间1的温度,y3y_3y3表示的是房间3的温度,且他们之间的函数关系表示为:
{y2=v2y1=w1y2+v1y3=w3y2+v3vi−N(0,σi2),高斯噪声\begin{cases} y_2=v_2\\ y_1=w_1y_2+v_1\\ y_3=w_3y_2+v_3\\ v_i-N(0,\sigma_i^2),高斯噪声 \end{cases} ⎩⎪⎪⎪⎨⎪⎪⎪⎧y2=v2y1=w1y2+v1y3=w3y2+v3vi−N(0,σi2),高斯噪声
则状态向量y=[y1,y2,y3]Ty=[y_1,y_2,y_3]^Ty=[y1,y2,y3]T对应的协防差矩阵KKK为:
K11=E(y1y1)=w12σ22+σ12,K22=E(y2y2)=σ22,K33=E(y3y3)=w32σ22+σ32K12=K21=E(y1y2)=w12σ22,K13=K31=w1w3σ22,K23=K32=w3σ22K_{11}=E(y_1y_1)=w_1^2\sigma_2^2+\sigma_1^2,K_{22}=E(y_2y_2)=\sigma_2^2,K_{33}=E(y_3y_3)=w_3^2\sigma_2^2+\sigma_3^2 \\ K_{12}=K_{21}=E(y_1y_2)=w_1^2\sigma_2^2,K_{13}=K_{31}=w_1w_3\sigma_2^2,K_{23}=K_{32}=w_3\sigma_2^2 K11=E(y1y1)=w12σ22+σ12,K22=E(y2y2)=σ22,K33=E(y3y3)=w32σ22+σ32K12=K21=E(y1y2)=w12σ22,K13=K31=w1w3σ22,K23=K32=w3σ22
即:
K=(w12σ22+σ12w1σ22w1w3σ22w1σ22σ22w3σ22w1w3σ22w3σ22w32σ22+σ32)K= \left( \begin{matrix} w_1^2\sigma_2^2+\sigma_1^2 & w_1\sigma_2^2 & w_1w_3\sigma_2^2\\ w_1\sigma_2^2 & \sigma_2^2 & w_3\sigma_2^2\\ w_1w_3\sigma_2^2 & w_3\sigma_2^2 & w_3^2\sigma_2^2+\sigma_3^2 \end{matrix} \right) K=⎝⎛w12σ22+σ12w1σ22w1w3σ22w1σ22σ22w3σ22w1w3σ22w3σ22w32σ22+σ32⎠⎞
现在知道了该向量对应的协方差矩阵,只需要求解其逆矩阵就可以得到信息矩阵。不过直接求解其逆矩阵还是比较麻烦的,因此我们按照如下的方法求解。我们首先需要求解对应的联合概率分布,则根据贝叶斯公式可以得到:
p(y1,y2,y3)=p(y1,y3∣y2)p(y2)=p(y1∣y3,y2)p(y3∣y2)p(y2)p(y_1,y_2,y_3)=p(y_1,y_3|y_2)p(y_2)=p(y_1|y_3,y_2)p(y_3|y_2)p(y_2)p(y1,y2,y3)=p(y1,y3∣y2)p(y2)=p(y1∣y3,y2)p(y3∣y2)p(y2)
而由前面之间的关系我们知道,y1y_1y1是不依赖于y3y_3y3的,因此p(y1∣y3,y2)=p(y1∣y2)p(y_1|y_3,y_2)=p(y_1|y_2)p(y1∣y3,y2)=p(y1∣y2),因此上式可以化简为:
p(y1,y2,y3)=p(y1∣y2)p(y3∣y2)p(y2)p(y_1,y_2,y_3)=p(y_1|y_2)p(y_3|y_2)p(y_2)p(y1,y2,y3)=p(y1∣y2)p(y3∣y2)p(y2)
p(y2)=1Z2e−y222σ22p(y_2)=\frac{1}{Z_2}e^{-\frac{y_2^2}{2\sigma_2^2}}p(y2)=Z21e−2σ22y22
p(y1∣y2)=1Z1e−(y1−w1y2)22σ12p(y_1|y_2)=\frac{1}{Z_1}e^{-\frac{(y_1-w_1y_2)^2}{2\sigma_1^2}}p(y1∣y2)=Z11e−2σ12(y1−w1y2)2
p(y3∣y2)=1Z3e−(y3−w3y2)22σ32p(y_3|y_2)=\frac{1}{Z_3}e^{-\frac{(y_3-w_3y_2)^2}{2\sigma_3^2}}p(y3∣y2)=Z31e−2σ32(y3−w3y2)2
p(y1,y2,y3)=1Z′exp(−12(y22σ22+(y1−w1y2)2σ12+(y3−w3y2)2σ32))p(y_1,y_2,y_3)=\frac{1}{Z'}exp(-\frac{1}{2}(\frac{y_2^2}{\sigma_2^2}+\frac{(y_1-w_1y_2)^2}{\sigma_1^2}+\frac{(y_3-w_3y_2)^2}{\sigma_3^2}))p(y1,y2,y3)=Z′1exp(−21(σ22y22+σ12(y1−w1y2)2+σ32(y3−w3y2)2))
写成信息矩阵的形式既可以写为:
p(y1,y2,y3)=1Z′exp(−12[y1y2y3][1σ12−w1σ120−w1σ121σ22+w12σ12+w32σ32−w3σ320−w3σ321σ32][y1y2y3])p(y_1,y_2,y_3)=\frac{1}{Z'}exp(-\frac{1}{2}\left[\begin{matrix}y_1 & y_2 & y_3\end{matrix}\right]\left[\begin{matrix}\frac{1}{\sigma_1^2} & -\frac{w_1}{\sigma_1^2} & 0\\-\frac{w_1}{\sigma_1^2} & \frac{1}{\sigma_2^2}+\frac{w_1^2}{\sigma_1^2}+\frac{w_3^2}{\sigma_3^2} & -\frac{w_3}{\sigma_3^2}\\0 & -\frac{w_3}{\sigma_3^2} & \frac{1}{\sigma_3^2}\end{matrix}\right]\left[\begin{matrix}y_1 \\ y_2\\ y_3\end{matrix}\right])p(y1,y2,y3)=Z′1exp(−21[y1y2y3]⎣⎢⎡σ121−σ12w10−σ12w1σ221+σ12w12+σ32w32−σ32w30−σ32w3σ321⎦⎥⎤⎣⎡y1y2y3⎦⎤)
Ω=[1σ12−w1σ120−w1σ121σ22+w12σ12+w32σ32−w3σ320−w3σ321σ32]\Omega=\left[\begin{matrix}\frac{1}{\sigma_1^2} & -\frac{w_1}{\sigma_1^2} & 0\\-\frac{w_1}{\sigma_1^2} & \frac{1}{\sigma_2^2}+\frac{w_1^2}{\sigma_1^2}+\frac{w_3^2}{\sigma_3^2} & -\frac{w_3}{\sigma_3^2}\\0 & -\frac{w_3}{\sigma_3^2} & \frac{1}{\sigma_3^2}\end{matrix}\right] Ω=⎣⎢⎡σ121−σ12w10−σ12w1σ221+σ12w12+σ32w32−σ32w30−σ32w3σ321⎦⎥⎤
3.1.3 Marginalization in covariance and information form
对于3.1.2中的系统,现在我们想marginalize out状态变量y3y_3y3,也就是说现在的状态向量变为y‘=[y1,y2]Ty‘=[y_1,y_2]^Ty‘=[y1,y2]T,则该状态向量对应的协方差矩阵为:
K′=[w12σ22+σ12w1σ22w1σ22σ22]K'=\left[ \begin{matrix} w_1^2\sigma_2^2+\sigma_1^2 & w_1\sigma_2^2\\ w_1\sigma_2^2 & \sigma_2^2 \end{matrix} \right] K′=[w12σ22+σ12w1σ22w1σ22σ22]
从K′K'K′和KKK的对比中我们可以发现,在marginalize out y3y_3y3后,新的状态变量对应的协方差矩阵K′K'K′不过是将原来的协方差矩阵KKK的第3行和第3列删掉,那么信息矩阵是不是也是这样呢?我们一起来推导一下。
p(y1,y2)=p(y1∣y2)p(y2)=1Z′exp(−12(y22σ22+(y1−w1y2)2σ12))=1Z′exp(−12[y1y2][1σ12−w1σ12−w1σ121σ22+w12σ12][y1y2])p(y_1,y_2)=p(y_1|y_2)p(y_2)=\frac{1}{Z'}exp(-\frac{1}{2}(\frac{y_2^2}{\sigma_2^2}+\frac{(y_1-w_1y_2)^2}{\sigma_1^2}))\\=\frac{1}{Z'}exp(-\frac{1}{2}\left[ \begin{matrix}y_1 & y_2\end{matrix} \right]\left[ \begin{matrix} \frac{1}{\sigma_1^2} & -\frac{w_1}{\sigma_1^2}\\ -\frac{w_1}{\sigma_1^2} & \frac{1}{\sigma_2^2}+\frac{w_1^2}{\sigma_1^2} \end{matrix} \right]\left[ \begin{matrix}y_1 \\ y_2\end{matrix} \right]) p(y1,y2)=p(y1∣y2)p(y2)=Z′1exp(−21(σ22y22+σ12(y1−w1y2)2))=Z′1exp(−21[y1y2][σ121−σ12w1−σ12w1σ221+σ12w12][y1y2])
也就是说:
Ω′=[1σ12−w1σ12−w1σ121σ22+w12σ12]\Omega'=\left[ \begin{matrix} \frac{1}{\sigma_1^2} & -\frac{w_1}{\sigma_1^2}\\ -\frac{w_1}{\sigma_1^2} & \frac{1}{\sigma_2^2}+\frac{w_1^2}{\sigma_1^2} \end{matrix} \right] Ω′=[σ121−σ12w1−σ12w1σ221+σ12w12]
发现,咦,信息矩阵好像不像协方差矩阵那样直接把y3y_3y3对应的第3行和第3列去掉就可以了。也就是说对于一般情况来讲,假如一个状态向量为x=[aT,bT]Tx=[a^T,b^T]^Tx=[aT,bT]T,如果我们想marginalize out状态向量bbb,那么对于协方差矩阵仅需要将状态向量bbb对应的行和列删除就可以。可是信息矩阵不行啊,这怎么办呢?这时候就需要Schur Complement了。skir~~ skir~~
3.1.4 Schur Complement
为不失一般性,咱这次就不拿前两节中那个温度模型说事儿了。现在假设状态变量为x=[aT,bT]Tx=[a^T,b^T]^Tx=[aT,bT]T,其对应的协防差矩阵为:
K=[ACTCD]K=\left[ \begin{matrix} A & C^T\\ C & D \end{matrix} \right] K=[ACCTD]
其中,AAA和DDD为可逆方阵。
记其信息矩阵为Λ\LambdaΛ:
Λ=[ΛaaΛabΛbaΛbb]\Lambda = \left[ \begin{matrix} \Lambda_{aa} & \Lambda_{ab}\\ \Lambda_{ba} & \Lambda_{bb} \end{matrix} \right] Λ=[ΛaaΛbaΛabΛbb]
假设状态变量xxx满足多维高斯分布,则有下式:
p(x)=p0exp(−12E)p(x)=p_0exp(-\frac{1}{2}E) p(x)=p0exp(−21E)
E=[xaT,xbT]Λ[xaxb]=[xaT,xbT][ΛaaΛabΛbaΛbb][xaxb]\begin{matrix} E =\left[x_a^T,x_b^T\right]\Lambda\left[\begin{matrix}x_a\\x_b\end{matrix}\right]\\ = \left[x_a^T,x_b^T\right]\left[\begin{matrix}\Lambda_{aa}&\Lambda_{ab}\\\Lambda_{ba}&\Lambda_{bb}\end{matrix}\right]\left[\begin{matrix}x_a\\x_b\end{matrix}\right] \end{matrix} E=[xaT,xbT]Λ[xaxb]=[xaT,xbT][ΛaaΛbaΛabΛbb][xaxb]
将上式打开就可以得到下式:
E=xaTΛaaxa+2xbTΛbaxa+xbTΛbbxbE=x_a^T\Lambda_{aa}x_a+2x_b^T\Lambda_{ba}x_a+x_b^T\Lambda_{bb}x_b E=xaTΛaaxa+2xbTΛbaxa+xbTΛbbxb
容易发现上式就是一个二次型,比较遗憾的是存在一个xbx_bxb和xax_axa的交叉项。为了分离变量,就需要用到我们线性代数中学过的配方法求标准二次型问题了。考虑到这个东西可能离大家比较久远,我们首先来简单回顾一下这种方法,简单来说就比如说一个函数Q(x1,x2)=x12+x22+3x1x2Q(x_1,x_2)=x_1^2+x_2^2+3x_1x_2Q(x1,x2)=x12+x22+3x1x2,写成矩阵的形式就是:
Q(x1,x2)=[x1,x2][1301][x1x2]Q(x_1,x_2)=\left[x_1,x_2\right]\left[\begin{matrix}1&3\\0&1\end{matrix}\right]\left[\begin{matrix}x_1\\x_2\end{matrix}\right] Q(x1,x2)=[x1,x2][1031][x1x2]
我们说这个东西不是标准二次型就是因为中间的矩阵不是对角阵,右上角有一个比较烦人的数字3.那么怎么能把这个3搞没呢,这里就可以无脑用配方法啦。可以把Q函数改写成:
Q(x1,x2)=(x1+32x2)2−54x22Q(x_1,x_2)=(x_1+\frac{3}{2}x_2)^2-\frac{5}{4}x_2^2 Q(x1,x2)=(x1+23x2)2−45x22
如果另y1=x1+1.5×x2,y2=x2y_1=x_1+1.5\times x_2,y_2=x_2y1=x1+1.5×x2,y2=x2,然后上式就可以改写成:Q(y1,y2)=y12−1.25y22Q(y_1,y_2)=y_1^2-1.25y_2^2Q(y1,y2)=y12−1.25y22,也就是标准二次型的形式。
按照这种方法我们对EEE进行标准化则可以得到:
E=(xb+Λbb−1Λbaxa)TΛbb(xb+Λbb−1Λbaxa)+xaT(Λaa−ΛbaTΛbb−1Λba)xaE=(x_b+\Lambda_{bb}^{-1}\Lambda_{ba}x_a)^T\Lambda_{bb}(x_b+\Lambda_{bb}^{-1}\Lambda_{ba}x_a)+x_a^T(\Lambda_{aa}-\Lambda_{ba}^T\Lambda_{bb}^{-1}\Lambda_{ba})x_a E=(xb+Λbb−1Λbaxa)TΛbb(xb+Λbb−1Λbaxa)+xaT(Λaa−ΛbaTΛbb−1Λba)xa
所谓的Λaa−ΛbaTΛbb−1Λba\Lambda_{aa}-\Lambda_{ba}^T\Lambda_{bb}^{-1}\Lambda_{ba}Λaa−ΛbaTΛbb−1Λba,也就是我们经常在论文里面看到的Schur Complements了,将会给基于信心矩阵的边缘化带来极大方便。对化简后的概率分布求积分p(xa)=∫p(xa,xb)dxbp(x_a)=\int p(x_a,x_b)dx_bp(xa)=∫p(xa,xb)dxb就可以得到去掉xbx_bxb后的边缘分布啦,其信息矩阵就是这个schur complement。关于这部分的详细推导建议大家看这篇论文里面的定理1:
Manipulating the Multivariate Gaussian Density。
好了这篇博客就先到这里了,我们下篇博客见。
Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(二)相关推荐
- Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(一)
Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(一) 1. LiDAR inertial odometry and mapping简介 ...
- Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(四)
Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(四) 3. Joint optimization 3.3 IMU preintegrat ...
- Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(三)
Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(三) 3. Joint optimization 3.2 IMU preintegrat ...
- 激光SLAM系统Fast LOAM (Lidar Odometry And Mapping)源码解析
github地址:Fast LOAM (Lidar Odometry And Mapping) Fast LOAM提供了mapping和localization的两个节点,目前只使用其定位部分,以ve ...
- 【深度学习模型】智云视图中文车牌识别源码解析(二)
[深度学习模型]智云视图中文车牌识别源码解析(二) 感受 HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等. 代码不可谓不混乱(别忘了这是职业公司的准产品级代码 ...
- erlang下lists模块sort(排序)方法源码解析(二)
上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...
- Kubernetes学习笔记之Calico CNI Plugin源码解析(二)
女主宣言 今天小编继续为大家分享Kubernetes Calico CNI Plugin学习笔记,希望能对大家有所帮助. PS:丰富的一线技术.多元化的表现形式,尽在"360云计算" ...
- Mobx 源码解析 二(autorun)
前言 我们在Mobx 源码解析 一(observable)已经知道了observable 做的事情了, 但是我们的还是没有讲解明白在我们的Demo中,我们在Button 的Click 事件中只是对ba ...
- android网络框架retrofit源码解析二
注:源码解析文章参考了该博客:http://www.2cto.com/kf/201405/305248.html 前一篇文章讲解了retrofit的annotation,既然定义了,那么就应该有解析的 ...
最新文章
- ab测试nginx Nginx性能优化
- 如何为回归问题选择最合适的机器学习方法?
- MarkDown常用技巧总结
- JUC 中的多线程协作工具类:CountDownLatch 和 CyclicBarrier
- listview mysql查询_Sqlite 数据库分页查询(ListView分页显示数据)
- 使用pscp命令将windows系统里的文件传送到远程服务器
- 热狗树 树形dp(中国石油大学我要变强第九场)
- linux拷贝到新建文件夹命令行,Linux创建文件touch,复制文件cp,tab补全,链接文件ln命令...
- php 判断wap,php判断是否wap手机客户端的方法详解
- java servlet jsp 实例_Servlet+JSP例子
- 鸿蒙系统更新法定年龄,超25000位开发者参赛,华为首届鸿蒙开发者创新大赛创意满满...
- Mac实用技巧:怎样使用终端在macOS Big Sur Finder中锁定文件!
- AO*算法详解,附例子和算法详细步骤
- 华为交换机,登录密码忘记
- c语言需要什么硬件基础知识,学习c语言需要什么 基础c语言需要这些知识
- 数学知识-三角函数公式大全(值得收藏)
- 利用Excel可视化分析,柱形图、条形图、饼图、复合饼图,圆环图、组合图、漏斗图、地图的操作方法(适合小白)
- Wordress博客添加音乐播放器插件
- 《中国历代著名文学家评传》目录
- iOS仿微信录像和拍照(swift5.0)
热门文章
- 远程桌面常见问题及注意事项
- Android11谷歌安装器,谷歌Pixel5安卓11安装面具ROOT方案【赠送5G模块】
- 给谷歌安装es-head
- 手动安装Xposed5.1.1框架zip包,解决Could not found ZIP files报错
- LVGL hal indev(porting evdev)
- Mathpix公式识别使用教程
- 实践分享:一定要用OKR进行持续绩效管理的4个理由
- 2019互联网月饼大赏,你公司有上榜吗?
- 3分钟搞定高逼格PPT封底——简约型
- 计算机网络专业论文doc,计算机专业毕业论文(网络).doc