3D激光里程计其四:点云线面特征提取

news2024/9/23 15:26:34

3D激光里程计其四:点云线面特征提取

  • 1. 点云线面特征提取
    • 1.1 按线数分割
    • 1.2 计算曲率
    • 1.3 按曲率大小筛选特征点
  • 2. 基于线面特征的位姿变化
    • 2.1 帧间关联
      • 2.1.1 点云位姿转换
      • 2.1.2 线特征关联
      • 2.1.3 面特征关联
    • 2.2 残差函数
      • 2.2.1 线特征
      • 2.2.2 面特征
    • 2.3 位姿优化
      • 2.3.1 线特征残差雅可比
      • 2.3.2 面特征残差雅可比
  • 3. 位姿代码实现
    • 3.1 ceres 基础知识
      • 3.1.1 基本概念
    • 3.2 自动求导与解析求导
      • 3.2.1 自动求导
      • 3.2.2 解析求导
      • 3.2.3 自动求导与解析求导的对比
    • 3.3 自动求导实现位姿优化(A-LOAM)
      • 3.3.1 线特征
      • 3.3.2 面特征
    • 3.4 解析求导实现位姿优化(F-LOAM)
      • 3.4.1 线特征
      • 3.4.2 面特征
  • 4. 相关开源里程计
    • 4.1. 基于特征的里程计实现流程
    • 4.2 LOAM
    • 4.3 [A-LOAM](https://github.com/HKUST-Aerial-Robotics/A-LOAM)
    • 4.4 [F-LOAM](https://github.com/wh200720041/floam)

Reference:

  1. 深蓝学院-多传感器融合
  2. LOAM论文和程序代码的解读

1. 点云线面特征提取

1.1 按线数分割

根据激光点坐标,可计算该束激光相比于雷达水平面的倾角 ω = arctan ⁡ z x 2 + y 2 \omega=\arctan \frac{z}{\sqrt{x^2+y^2}} ω=arctanx2+y2 z
根据倾角雷达内参(各扫描线的设计倾角),可知雷达属于哪条激光束
在这里插入图片描述

1.2 计算曲率

在这里插入图片描述

根据前后各5个点与当前点的长度(长度指激光点到雷达的距离)(应该是在同一线下的前后5个点),计算曲率大小(下面公式为LOAM代码中的实现方式,并不是传统意义上的曲率):
c = 1 ∥ X ∥ ∥ ∑ i ( X − X i ) ∥ c=\frac{1}{\|X\|}\left\|\sum_i\left(X-X_i\right)\right\| c=X1 i(XXi) (这里面的 ∑ \sum 是在范数内,没有问题)该计算方式很明显的体现了这个平面是否平的信息。
在这里插入图片描述

像这种在墙角的情况下,虽然在 x x x方向上很小,但是在 y y y方向很大。

1.3 按曲率大小筛选特征点

一个面上的曲率肯定是小的,而一个线的曲率肯定是大的,那么反过来讲,可以通过曲率大小来划分线特征还是面特征。

线特征和面特征内部的曲率还应该做一些差异上的区别。假如我们求一个点到线的距离的时候,假如这个线上有一百个点,不可能这一百个点都求一个点到线的距离,这个计算量会大到无法接受,这时只能选一部分点来计算点到直线的距离。应该将曲率最大的几个点选出来-----曲率大的点有更大的概率属于一个良好的线特征(错误归进来的点可能并不属于线特征,它们的曲率一般都是比较小的),反之亦然。这样就不会影响求取残差时的结果了。

共分4类:
a. 曲率特别大的点(sharp)
b. 曲率大的点(less_sharp)
c. 曲率特别小的点(flat)
d. 曲率小的点(less_flat)

实际使用时:
a. sharp 为“点到直线”中的“点”
b. sharp 和 less_sharp 为 “点到直线”中的直线
c. flat 为“点到平面”中的“点”
d. flat 和 less flat 为 “点到平面”中的“平面”

如下图所示,绿色点为velodyne 16线激光雷达的原始点云,扫描环境是卧室,大概就是一个长方体,能够看到点云在垂直方向大致分成了16条线。红色的小圆球是提取出来的角点(曲率特别大的点),蓝色的是平面点。可见,角点基本上位于房间的墙角和过渡较大的地方,例如物体(窗帘)的边缘。
在这里插入图片描述
接下来对特征点分的更细一些,除了角点和平面点,还使用了曲率 c c c 不太大的点(称为less sharp point),和曲率不太小的点(称为less flat point),下图中红色的小圆就是less sharp point,蓝色的小圆是less flat point。在右侧的图中我把门打开了,可以清晰地看到门口边界有更多的less sharp point

2. 基于线面特征的位姿变化

现在介绍一下,在得到线面特征之后,怎么进行位姿优化。

假设有两帧 k k k 帧和 k + 1 k+1 k+1 帧,两个里面都有线面特征,两帧之间理论上是有很多线是对应的,也就是说,在 k k k 帧和 k + 1 k+1 k+1 帧的线,有些打在了同样的物体上,这样属于同一个线/面,就可以做关联了。如果 k k k 帧和 k + 1 k+1 k+1 帧的线不重合,那肯定就是位姿和误差导致的。也就是说,我们可以通过线/面是否重合,来反推出第 k + 1 k+1 k+1 帧相对于第 k k k 帧是什么样子的,这就是我们想要的里程计了。

2.1 帧间关联

2.1.1 点云位姿转换

k + 1 k+1 k+1 帧与第 k k k 帧的相对位姿为: T = [ R t 0 1 ] T=\left[\begin{array}{ll}R & t \\ 0 & 1\end{array}\right] T=[R0t1]

k+1 帧中的点 p i p_i pi 转到第 k 帧坐标系: p ~ i = R p i + t \tilde{p}_i=R p_i+t p~i=Rpi+t

这里可以先使用第 k k k 帧与第 k − 1 k-1 k1 帧的相对位姿,先猜测一个第 k + 1 k+1 k+1 帧与第 k k k 帧的相对位姿的近似值。

2.1.2 线特征关联

p i p_i pi 为 sharp 时(用曲率大的点),在上一帧中搜索离 p ~ i \tilde{p}_i p~i 最近的线特征点,并在相邻线上再找一个线特征点,组成直线。这时用 k + 1 k+1 k+1 上的一个点,在第 k k k 帧中,找到了这个线特征对应的线,有了点和线,就可以求点到直线的距离了。
在这里插入图片描述

2.1.3 面特征关联

p i p_i pi 为 flat 时,在上一帧中搜索离 p ~ i \tilde{p}_i p~i 最近的面特征点,并在相邻线上找两个面特征点,组成平面。(同一个线上找一个,相邻线上再找一个,三个点构成一个面)
在这里插入图片描述

2.2 残差函数

2.2.1 线特征

在这里插入图片描述

点到直线的距离:
d E = ∣ ( p ~ i − p b ) × ( p ~ i − p a ) ∣ ∣ p a − p b ∣ d_{\mathcal{E}}=\frac{\left|\left(\tilde{p}_i-p_b\right) \times\left(\tilde{p}_i-p_a\right)\right|}{\left|p_a-p_b\right|} dE=papb(p~ipb)×(p~ipa)在实际代码中,使用的是矢量形式,而不是直接取模,其实在求残差函数时,都是求的 f T f f^Tf fTf,区别不大吗:
d E = ( p ~ i − p b ) × ( p ~ i − p a ) ∣ p a − p b ∣ d_{\mathcal{E}}=\frac{\left(\tilde{p}_i-p_b\right) \times\left(\tilde{p}_i-p_a\right)}{\left|p_a-p_b\right|} dE=papb(p~ipb)×(p~ipa)

2.2.2 面特征

在这里插入图片描述
点到平面的距离
d H = ∣ ( p ~ i − p j ) ∙ ( p l − p j ) × ( p m − p j ) ∣ ( p l − p j ) × ( p m − p j ) ∣ ∣ 【】】】】】】】】】】】】】】】】】】】】】】】】】】】】 d_{\mathcal{H}}=|\left(\tilde{p}_i-p_j\right) \bullet \frac{\left(p_l-p_j\right) \times\left(p_m-p_j\right)}{\left|\left(p_l-p_j\right) \times\left(p_m-p_j\right)\right|}| 【】】】】】】】】】】】】】】】】】】】】】】】】】】】】 dH=(p~ipj)(plpj)×(pmpj)(plpj)×(pmpj)【】】】】】】】】】】】】】】】】】】】】】】】】】】】】

2.3 位姿优化

根据非线性优化理论,只要求得残差关于待求变量的雅可比,便可采用高斯牛顿等进行优化。

2.3.1 线特征残差雅可比

J ε = ∂ d ε ∂ T = ∂ d ε ∂ p ~ i ∂ p ~ i ∂ T J_{\varepsilon}=\frac{\partial d_{\varepsilon}}{\partial T}=\frac{\partial d_{\varepsilon}}{\partial \tilde{p}_i} \frac{\partial \tilde{p}_i}{\partial T} Jε=Tdε=p~idεTp~i ∂ d ε \partial d_{\varepsilon} dε是残差,针对残差求导。 ∂ d ε ∂ T \frac{\partial d_{\varepsilon}}{\partial T} Tdε直接求导比较复杂,所以采用了链式求导法则。

等号右边第二项 ∂ p ~ i ∂ T \frac{\partial \tilde{p}_i}{\partial T} Tp~i与李代数相关,此处直接给出结论,推导过程见《视觉SLAM十四讲》第 4.3 4.3 4.3 节。
对平移的雅可比: ∂ p ~ i ∂ t = I \frac{\partial \tilde{p}_i}{\partial t}=I tp~i=I
对旋转的雅可比: ∂ p ~ i ∂ R = − ( R p i + t ) ∧ \frac{\partial \tilde{p}_i}{\partial R}=-\left(R p_i+t\right)^{\wedge} Rp~i=(Rpi+t)

等号右边第一项 ∂ d ε ∂ p ~ i \frac{\partial d_{\varepsilon}}{\partial \tilde{p}_i} p~idε可以根据外积的微分性质,推导得到:
∂ d ε ∂ p ~ i = 1 ∣ p a − p b ∣ ( ∂ ( p ~ i − p b ) ∧ ( p ~ i − p a ) ∂ p ~ i + ( p ~ i − p b ) ∧ ∂ ( p ~ i − p a ) ∂ p ~ i ) = 1 ∣ p a − p b ∣ ( − ( p ~ i − p a ) ∧ + ( p ~ i − p b ) ∧ ) = ( p a − p b ) ∧ ∣ p a − p b ∣ \begin{aligned} \frac{\partial d_{\varepsilon}}{\partial \tilde{p}_i} & =\frac{1}{\left|p_a-p_b\right|}\left(\frac{\partial\left(\tilde{p}_i-p_b\right)^{\wedge}\left(\tilde{p}_i-p_a\right)}{\partial \tilde{p}_i}+\frac{\left(\tilde{p}_i-p_b\right)^{\wedge} \partial\left(\tilde{p}_i-p_a\right)}{\partial \tilde{p}_i}\right) \\ & =\frac{1}{\left|p_a-p_b\right|}\left(-\left(\tilde{p}_i-p_a\right)^{\wedge}+\left(\tilde{p}_i-p_b\right)^{\wedge}\right) \\ & =\frac{\left(p_a-p_b\right)^{\wedge}}{\left|p_a-p_b\right|} \end{aligned} p~idε=papb1(p~i(p~ipb)(p~ipa)+p~i(p~ipb)(p~ipa))=papb1((p~ipa)+(p~ipb))=papb(papb)

该式推导过程:

  1. 线特征点到直线距离: d E = ( p ~ i − p b ) × ( p ~ i − p a ) ∣ p a − p b ∣ d_{\mathcal{E}}=\frac{\left(\tilde{p}_i-p_b\right) \times\left(\tilde{p}_i-p_a\right)}{\left|p_a-p_b\right|} dE=papb(p~ipb)×(p~ipa),上面可以变成 ( p ~ i − p b ) ∧ ( p ~ i − p a ) \left(\tilde{p}_i-p_b\right)^{\wedge}\left(\tilde{p}_i-p_a\right) (p~ipb)(p~ipa)
  2. 偏导有性质: ∂ x 1 x 2 ∂ y = ∂ x 1 ∂ y ⋅ x 2 + x 1 ⋅ ∂ x 2 ∂ y \frac{\partial x_1 x_2}{\partial y} = \frac{\partial x_1}{\partial y}\cdot x_2 + x_1\cdot \frac{\partial x_2}{\partial y} yx1x2=yx1x2+x1yx2
  3. ∂ ( p ~ i − p b ) ∧ ( p ~ i − p a ) \partial\left(\tilde{p}_i-p_b\right)^{\wedge}\left(\tilde{p}_i-p_a\right) (p~ipb)(p~ipa) ∂ ( p ~ i − p b ) ∧ \partial\left(\tilde{p}_i-p_b\right)^{\wedge} (p~ipb)是个矩阵不好求偏导,这时使用另一个性质: a ∧ b = − b ∧ a a^{\wedge}b=-b^{\wedge}a ab=ba又可推导出 ∂ a ∧ b ∂ a = − ∂ b ∧ a ∂ a = − b ∧ \frac{\partial a^{\wedge}b}{\partial a}=-\frac{\partial b^{\wedge}a}{\partial a}=-b^{\wedge} aab=aba=b
  4. − ( p ~ i − p a ) ∧ + ( p ~ i − p b ) ∧ -\left(\tilde{p}_i-p_a\right)^{\wedge}+\left(\tilde{p}_i-p_b\right)^{\wedge} (p~ipa)+(p~ipb)是矩阵,可以相互加减,抵消掉了 p ~ i \tilde{p}_i p~i,得到最终公式

2.3.2 面特征残差雅可比

J H = ∂ d H ∂ T = ∂ d H ∂ p ~ i ∂ p ~ i ∂ T J_{\mathcal{H}}=\frac{\partial d_{\mathcal{H}}}{\partial T}=\frac{\partial d_{\mathcal{H}}}{\partial \tilde{p}_i} \frac{\partial \tilde{p}_i}{\partial T} JH=TdH=p~idHTp~i等号右边第二项与线特征的一致。
残差函数为:
d H = ∣ ( p ~ i − p j ) ∙ ( p l − p j ) × ( p m − p j ) ∣ ( p l − p j ) × ( p m − p j ) ∣ ∣ d_{\mathcal{H}}=|\left(\tilde{p}_i-p_j\right) \bullet \frac{\left(p_l-p_j\right) \times\left(p_m-p_j\right)}{\left|\left(p_l-p_j\right) \times\left(p_m-p_j\right)\right|}| dH=(p~ipj)(plpj)×(pmpj)(plpj)×(pmpj)若令
X = ( p ~ i − p j ) ∙ ( p t − p j ) × ( p m − p j ) ∣ ( p t − p j ) × ( p m − p j ) ∣ X=\left(\tilde{p}_i-p_j\right) \bullet \frac{\left(p_t-p_j\right) \times\left(p_m-p_j\right)}{\left|\left(p_t-p_j\right) \times\left(p_m-p_j\right)\right|} X=(p~ipj)(ptpj)×(pmpj)(ptpj)×(pmpj)则有
∂ d H ∂ p ~ i = ∂ ∣ X ∣ ∂ p ~ i = ∂ ∣ X ∣ ∂ X ∂ X ∂ p ~ i = X ∣ X ∣ ∂ X ∂ p ~ i \frac{\partial d_{\mathcal{H}}}{\partial \tilde{p}_i}=\frac{\partial|X|}{\partial \tilde{p}_i}=\frac{\partial|X|}{\partial X} \frac{\partial X}{\partial \tilde{p}_i}=\frac{X}{|X|} \frac{\partial X}{\partial \tilde{p}_i} p~idH=p~iX=XXp~iX=XXp~iX关于 ∂ ∣ X ∣ ∂ X \frac{\partial|X|}{\partial X} XX是怎么得到 X ∣ X ∣ \frac{X}{|X|} XX的,假设 a = ( x , y , z ) a=(x,y,z) a=(x,y,z),那么 ∂ ∣ a ∣ ∂ a = ∂ x 2 + y 2 + z 2 ∂ ( x , y , z ) = ( x , y , z ) x 2 + y 2 + z 2 = a ∣ a ∣ \frac{\partial|a|}{\partial a}=\frac{\partial \sqrt{x^2+y^2+z^2}}{\partial (x,y,z)}=\frac{(x,y,z)}{\sqrt{x^2+y^2+z^2}}=\frac{a}{|a|} aa=(x,y,z)x2+y2+z2 =x2+y2+z2 (x,y,z)=aa

对于等号右边第二项,根据内积的微分性质,有
∂ X ∂ p ~ i = ( p l − p j ) × ( p m − p j ) ∣ ( p l − p j ) × ( p m − p j ) ∣ \frac{\partial X}{\partial \tilde{p}_i}=\frac{\left(p_l-p_j\right) \times\left(p_m-p_j\right)}{\left|\left(p_l-p_j\right) \times\left(p_m-p_j\right)\right|} p~iX=(plpj)×(pmpj)(plpj)×(pmpj)物理意义上,它代表的是平面的单位法向量。

3. 位姿代码实现

3.1 ceres 基础知识

3.1.1 基本概念

优化任务一般可以表示成如下形式:
min ⁡ x 1 2 ∑ i ρ i ( ∥ f i ( x i 1 , … , x i k ) ∥ 2 )  s.t.  l j ≤ x j ≤ u j \begin{aligned} & \min _{\mathbf{x}} \frac{1}{2} \sum_i \rho_i\left(\left\|f_i\left(x_{i_1}, \ldots, x_{i_k}\right)\right\|^2\right) \\ & \text { s.t. } \quad l_j \leq x_j \leq u_j \end{aligned} xmin21iρi(fi(xi1,,xik)2) s.t. ljxjuj其中,

  1. ρ i ( ∥ f i ( x i 1 , … , x i k ) ∥ 2 ) \rho_i\left(\left\|f_i\left(x_{i_1}, \ldots, x_{i_k}\right)\right\|^2\right) ρi(fi(xi1,,xik)2) 称为残差块,即 ResidualBlock;
  2. f i ( ⋅ ) f_i(\cdot) fi() 称为代价函数,对应之前讲的残差函数,即 CostFunction;
  3. [ x i 1 , … , x i k ] \left[x_{i_1}, \ldots, x_{i_k}\right] [xi1,,xik] 这一系列参数称为参数块待优化参数),即 ParameterBlock;
  4. ρ i ( ⋅ ) \rho_i(\cdot) ρi() 称为损失函数,即 LossFunction,对应之前的大F。

残差块ResidualBlock包含了代价函数(不止一个)、损失函数(可选)和待优化的参数块。

3.2 自动求导与解析求导

假设我们有一个残差,我们需要对残差求雅可比,如果将雅可比直接输到代码里,叫做解析求导,就是说已经解析式的,将求导的公式告诉算法了。自动求导是告诉代码残差和参数之间是什么关系,那么代码就可以自动的将雅可比求出来,不需要自己计算雅可比。

3.2.1 自动求导

以一个简单的例子来说明该问题,假设代价函数为: f ( x ) = 10 − x f(x)=10-x f(x)=10x
则首先编写 CostFunctor 的代码如下:

在这里插入图片描述
随后可直接构建 ceres 优化问题:
在这里插入图片描述

3.2.2 解析求导

解析求导的含义就是直接给出导数的解析形式,而不是ceres去推导
在这里插入图片描述
解析求导在没给出雅可比时,会转到自动求导上面去。

随后可构建优化问题:
在这里插入图片描述

这种使用方式,就是vio/lio中使用ceres构建优化问题的方式。

3.2.3 自动求导与解析求导的对比

• 自动求导实现方便,但效率会比解析求导低 (比较 A-LOAM 和 F-LOAM );
• 实际使用中,能够自动求导且效率没有形成障碍的,优先使用自动求导;
• 除这两种方法外,还有数值求导(SLAM问题中不常见,不过多介绍)

3.3 自动求导实现位姿优化(A-LOAM)

3.3.1 线特征

在这里插入图片描述

3.3.2 面特征

在这里插入图片描述

3.4 解析求导实现位姿优化(F-LOAM)

3.4.1 线特征

在这里插入图片描述

3.4.2 面特征

在这里插入图片描述

4. 相关开源里程计

4.1. 基于特征的里程计实现流程

在这里插入图片描述
帧到帧的方式,点云是比较稀疏的,会带来很多精度上的问题,比如:

  1. 上一帧打到树上了,这一帧没了;
  2. 上一帧和这一帧打到树上不同位置。

这时就引出了map的概念,也就是说,第 k + 1 k+1 k+1帧不是跟第 k k k帧,而是第 k k k帧之前的某些帧,共同构建出来了一个特征集合的map。不可能每一次都到map,map的运算量很大,那么实时性就没有意义了。这时就需要每个几帧再跟map匹配。这样累计误差也不会特别大,效率精度都能保证。

4.2 LOAM

LOAM: Lidar Odometry and Mapping in Real-time, Ji Zhang and Sanjiv Singh
代码比较乱,很多是没必要的操作。
在这里插入图片描述

4.3 A-LOAM

主要特点

  1. 去掉了和IMU相关的部分
  2. 使用Eigen(四元数)做位姿转换,简化了代码(将sin、cos去掉了)
  3. 使用ceres做迭代优化,简化了代码,但降低了效率(使用的自动求导)

4.4 F-LOAM

主要特点

  1. 整体和ALOAM类似,只是使用残差函数的雅可比使用的是解析式求导

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

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

相关文章

数据结构——二叉树2.0

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;数据结构——二叉树 &#x1f525;<3>创作者&#xff1a;我的代码爱吃辣 ☂️<4>开发环境&#xff1a;Visual Studio 2022 &#x1f4ac;<5>前言&#xff1a;上期讲了…

尚医通-医院接口设置(七)

&#xff08;1&#xff09;后台系统-医院设置接口-需求和准备 &#xff08;2&#xff09;后台系统-医院设置接口-创建基础类 &#xff08;3&#xff09;医院设置接口-查询和逻辑删除 &#xff08;4&#xff09;医院的设置接口-统一返回结果定义 &#xff08;5&#xff09;医…

[附源码]Python计算机毕业设计Django校园代取快递系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

知到/智慧树——大学生心理健康(华东政法大学)参考答案

目录 注&#xff1a;有些图片上传异常&#xff0c;请以参考答案为准&#xff0c;不要以蓝色选项为全部答案。 第一章测试 第二章测试 第三章测试 第四章测试 第五章测试 第六章测试 第七章测试 第八章测试 第九章测试 第十章测试 第十一章测试 第十二章测试 第一章…

传统技术如何阻碍零信任以及如何应对

随着组织采用零信任安全模型&#xff0c;传统技术制造了一些障碍。事实上&#xff0c;根据最近的一项研究&#xff0c;更换或重建现有的遗留基础设施是实施零信任的最大挑战。 通用动力公司的 2022 年零信任研究报告对美国联邦、民事和国防机构的 300 名 IT 和项目经理进行了调…

计算机毕设Python+Vue兴澜幼儿园管理系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

重定向和缓冲区

文章目录一个奇怪的现象缓冲区详解如何理解缓冲区缓冲区是谁给我提供的&#xff1f;缓冲区的源码体现案例&#xff1a;模拟实现FILE结构体第二个奇怪的现象重定向命令行上使用重定向操作dup2系统调用接口stdout和stderror一个奇怪的现象 首先&#xff0c;我们来看这样一段代码…

毕业设计 - 基于Java的聊天室系统设计与实现【源码+论文】

文章目录前言一、项目设计1. 模块设计服务器模块设计客户端模块设计2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 java 设计项目: 基于Java聊天室系统的设计与实现 一、项目设计 1. 模块设计 服务器模块设计 服务端的功能主要如下&#xff1a; 一&#xf…

R语言绘制森林图

在绘制森林图之前当然需要先下载RStudio软件啦&#xff0c;在下载后需要安装对应的rtool,最后将两者关联起来才能使用其中对应的包&#xff0c;否则只安装了软件很多功能不能使用而且还会报错&#xff0c;这篇文章主要是总结怎么使用forestploter包绘制森林图&#xff0c;本来是…

【Linux修炼手册:基本指令(完结)】

Life is about waiting for the right moment to act. 目录 1 zip/unzip指令 2 tar指令&#xff08;重要&#xff09;&#xff1a;打包/解包&#xff0c;不打开它&#xff0c;直接看内容 3 bc指令 4 uname –r指令 5 重要的几个热键[Tab],[ctrl]-c, [ctrl]-d 6 shutdown 7…

智能语音之远场关键词识别实践(二)

上篇&#xff08;智能语音之远场关键词识别实践&#xff08;一&#xff09;&#xff09;讲了“远场关键词识别”项目中后端上的实践。本篇将讲在前端上的一些实践以及将前端和后端连起来形成一个完整的方案。下图是其框图&#xff1a;&#xff08;麦克风阵列为圆阵且有四个麦克…

SpringMVC【学习笔记】

SpringMVC是什么? Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web 框架&#xff0c;即使用了MVC架构模式的思想&#xff0c;将web 层进行职责解耦&#xff0c;基于请求驱动指的就是使用请求-响应模型&#xff0c;框架的目的就是帮助我们简化…

看2022年卡塔尔世界杯有感

一、我印象中第一次看世界杯是2010年南非世界杯 自己第一次踢球是什么时候已经记不清了&#xff0c;大概是小学时候。因为我印象中第一次看世界杯是2010年南非世界杯&#xff0c;因为世界杯主题曲也比较好听&#xff0c;当然&#xff0c;我认为1998年法国世界杯的主题曲最为经…

Python中的魔法方法

python中的魔法方法是一些可以让你对类添加“魔法”的特殊方法,它们经常是两个下划线包围来命名的 Python的魔法方法&#xff0c;也称为dunder(双下划线)方法。大多数的时候&#xff0c;我们将它们用于简单的事情&#xff0c;例如构造函数(init)、字符串表示(str&#xff0c; r…

计算机毕设Python+Vue兴发农家乐服务管理系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Linux | 套接字(socket)编程 | UDP协议讲解

文章目录TCP与UDP的区别网络字节序套接字接口介绍sockaddr结构服务端UDP套接字设置客户端UDP套接字设置TCP与UDP的区别 TCPUDP传输层协议传输层协议有连接无连接可靠连接不可靠连接面向字节流面向数据报 首先&#xff0c;网络通信模型是分层的&#xff0c;模型的每一层都有属于…

深入jvm字节码

深入jvm字节码1.深入剖析class文件结构1.1初探class文件1.2 class文件结构解析1.2.1 魔数1.2.2 版本号1.2.3 常量池1.2.4 Access flags1.2.5 this_class,super_name,interfaces1.2.6 字段表1.2.7 方法表1.2.8 属性表1.3使用javap查看类文件2.字节码基础2.1字节码概述2.2java虚拟…

一文看懂---B树及其简单实现

目录 1.B树的引入 2.B树的概念 3.B树是如何插入的&#xff1f; 4.具体的代码实现 1.B树的引入 在以往我们在内存中搜索数据时&#xff0c;可以使用红黑树&#xff0c;平衡树&#xff0c;哈希表等数据结构&#xff0c;但是当数据量比较大&#xff0c;不能一次放进内存&…

[附源码]计算机毕业设计Python仓储综合管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

C++PrimerPlus 第七章 函数-C++的编程模块-7.9 递归

目录 7.9 递归 7.9.1 包含一个递归调用的递归 7.9.2 包含多个递归调用的递归 7.9 递归 下面介绍一些完全不同的内容。C函数有一种有趣的特点——可以调用自己&#xff08;然而&#xff0c;与C语言不同的是&#xff0c;C不允许main()调用自己&#xff09;&#xff0c;这种功能…