LOAM误差函数、代价函数的雅克比矩阵详细推导,点到线和点到面误差函数求导

2023-11-05

LOAM误差函数的导数详细推导

前言

LOAM对于激光SLAM的发展起到了举足轻重的作用,他提出了点到线和点到面的误差函数,通过优化的方法,得到了非常不错的激光里程计效果。我猜测作者Zhang Ji很可能是从点到线和点到面的ICP算法中找到的灵感。

在LOAM的论文中以及Zhang Ji早期开源的代码中,对于代价函数求解使用的是欧拉角的方式进行求导解算的。一方面由于未采用矩阵的形式进行推导,导致整个推导过程非常复杂,另一方面在代码实现中,有大量的中间运算过程,实际上对效率也带来了一部分影响。

在后续研究中F LOAM,采用了更加优雅的方式,在SE(3)的理论基础之上推导出了更加规整的雅克比矩阵,并借用ceres进行了实现,也确实对于精度和速度有一定的提升。

LOAM这种使用欧拉角的方式进行优化的方式,一直继承了下来,在LEGO-LOAM、LIO-SAM中均能看到。

在这篇博客中,我将在SO(3)的基础之上进行雅克比矩阵的详细推导,它与F LOAM的SE(3)推导区别并不大,只是我更加喜欢使用SO(3)方式。另外在国内的网站上有较少博客去做这件事,所以我将我的一些理解,向你分享。如果有理解偏颇的地方,烦请斧正。

预备知识

本篇博客会比较偏理论一些,需要你有一些先验知识:

(1)简单的矩阵运算;

(2)向量、矩阵求导;

(3)熟悉最优化理论;

(4)了解LOAM的误差函数的意义,本篇重点是探索误差函数的求解,所以不会去介绍误差函数的由来。

1. 点到直线(Point to Edge)

1.1 点到直线误差函数

d e = ∥ ( R p s + t − p t ) × n ⃗ e ∥ 2 (1) d_e = \|(Rp_s + t -p_t) \times \vec n_e\|_2 \tag{1} de=(Rps+tpt)×n e2(1)

d e d_e de:点到直线的距离(标量);
p t p_t pt:目标(地图)点云中的角点;
p s p_s ps:源(当前帧)点云中的角点;
n ⃗ e \vec n_e n e:近邻角点组成的直线对应的单位向量。

1.2 误差函数对R(旋转)和t(平移)的求导结果

∂ d e ∂ R = ( n ⃗ e × ( R p s ) ∧ ) T ∗ ( R p s + t − p t ) × n ⃗ e ∥ ( R p s + t − p t ) × n ⃗ ∥ 2 ∂ d e ∂ t = ( − n ⃗ e × I 3 × 3 ) T ∗ ( R p s + t − p t ) × n ⃗ e ∥ ( R p s + t − p t ) × n ⃗ e ∥ 2 (2) \frac{\partial d_e}{\partial R} = (\vec n_e \times (Rp_s)^{\wedge})^T * \frac{(Rp_s + t -p_t) \times \vec n_e}{\|(Rp_s + t -p_t) \times \vec n\|_2} \\ \frac{\partial d_e}{\partial t} = (-\vec n_e \times I_{3\times3})^T *\frac{(Rp_s + t -p_t) \times \vec n_e}{\|(Rp_s + t -p_t) \times \vec n_e\|_2} \tag{2} Rde=(n e×(Rps))T(Rps+tpt)×n 2(Rps+tpt)×n etde=(n e×I3×3)T(Rps+tpt)×n e2(Rps+tpt)×n e(2)

I 3 × 3 I_{3\times 3} I3×3:单位矩阵;
× \times ×:该运算符表示向量叉乘;
∗ * :该运算符表示一般的向量、矩阵之间的乘法。

1.3 预备数学公式

在推导公式(1)之前,先解释一下用到的一些数学公式:

二范数的导数
∂ ∥ x ∥ 2 ∂ x = x ∥ x ∥ 2 (3) \frac{ \partial\|x\|_2 } {\partial x} = \frac{x}{\|x\|_2} \tag{3} xx2=x2x(3)

其中: x = [ x 0 , x 1 , x 2 , ⋅ ] T x = [x_0,x_1,x_2,\cdot]^{T} x=[x0,x1,x2,]T ∥ x ∥ 2 = x 0 2 + x 1 2 + ⋯ \|x\|_2 = \sqrt{x_0^2+x_1^2+\cdots} x2=x02+x12+

标量对向量求导的链式法则

例如: z z z是关于 y y y的函数, y y y是关于 x x x的函数,它们的传递过程是: x − > y − > z x -> y->z x>y>z. 其中 z z z是标量, y y y是向量, x x x是向量,则求导的链式法则如下:
∂ z ∂ x = ( ∂ y ∂ x ) T ∂ z ∂ y (4) \frac{\partial z}{\partial x} = (\frac{\partial y}{\partial x})^T \frac{\partial z}{\partial y} \tag{4} xz=(xy)Tyz(4)

叉乘的交换性质
u × v = − v × u (5) u \times v = -v\times u \tag{5} u×v=v×u(5)
旋转矩阵左扰动求导

由于旋转矩阵不满足加法性质,所以采用扰动模型进行求导,这里采用的是对其左乘一个微小转动量 δ R \delta R δR,其对应的李代数 ϕ \phi ϕ,于是得到如下结论:(由于求导推导比较简单,并且资料较多,这里只给出结论)
∂ R p ∂ ϕ = − ( R p ) ∧ (6) \frac{\partial Rp}{\partial \phi} = -(Rp)^{\wedge} \tag{6} ϕRp=(Rp)(6)

∧ \wedge :该符号表示向量的反对称矩阵

1.4 误差函数对R和t的求导推导

根据以上数学性质,我们开始完成loam代价函数公式的求导,从而得到雅克比矩阵:

关于R的导数
∂ d e ∂ R = ∥ ( R p s + t − p t ) × n ⃗ e ∥ 2 ∂ R (7) \frac{\partial d_e}{\partial R} = \frac{\|(Rp_s + t -p_t) \times \vec n_e\|_2}{\partial R} \tag{7} Rde=R(Rps+tpt)×n e2(7)
对(7)式使用(4)式对应的链式求导法则:
∂ d e ∂ R = ∥ ( R p s + t − p t ) × n ⃗ e ∥ 2 ∂ R = ( ∂ ( ( R p s + t − p t ) × n ⃗ e ) ∂ R ) T ∗ ( R p s + t − p t ) × n ⃗ e ∥ ( R p s + t − p t ) × n ⃗ ∥ 2 (8) \frac{\partial d_e}{\partial R} = \frac{\|(Rp_s + t -p_t) \times \vec n_e\|_2}{\partial R} \\ = (\frac{\partial((Rp_s + t -p_t) \times \vec n_e)}{\partial R} )^{T} * \frac{(Rp_s + t -p_t) \times \vec n_e}{\|(Rp_s + t -p_t) \times \vec n\|_2} \tag{8} Rde=R(Rps+tpt)×n e2=(R((Rps+tpt)×n e))T(Rps+tpt)×n 2(Rps+tpt)×n e(8)
对于(8)式中第二行前半部分的偏导数计算:
∂ ( ( R p s + t − p t ) × n ⃗ e ) ∂ R = ∂ ( − n ⃗ e × ( R p s + t − p t ) ) ∂ R = ∂ ( − n ⃗ e × ( R p s ) ) ∂ R = − n ⃗ e × ( − ( R p s ) ∧ ) (9) \frac{\partial((Rp_s + t -p_t) \times \vec n_e)}{\partial R} \\ = \frac{\partial( -\vec n_e \times(Rp_s + t -p_t))}{\partial R} \\ = \frac{\partial( -\vec n_e \times(Rp_s))}{\partial R} \\ = -\vec n_e \times(-(Rp_s)^{\wedge}) \tag{9} R((Rps+tpt)×n e)=R(n e×(Rps+tpt))=R(n e×(Rps))=n e×((Rps))(9)
整理之后,得到关于点到线的误差函数关于R的导数:
∂ d e ∂ R = ( n ⃗ e × ( R p s ) ∧ ) T ∗ ( R p s + t − p t ) × n ⃗ e ∥ ( R p s + t − p t ) × n ⃗ ∥ 2 (10) \frac{\partial d_e}{\partial R} = (\vec n_e \times (Rp_s)^{\wedge})^T * \frac{(Rp_s + t -p_t) \times \vec n_e}{\|(Rp_s + t -p_t) \times \vec n\|_2} \tag{10} Rde=(n e×(Rps))T(Rps+tpt)×n 2(Rps+tpt)×n e(10)
关于t的导数
∂ d e ∂ t = ∥ ( R p s + t − p t ) × n ⃗ e ∥ 2 ∂ t = ( ∂ ( ( R p s + t − p t ) × n ⃗ e ) ∂ t ) T ∗ ( R p s + t − p t ) × n ⃗ e ∥ ( R p s + t − p t ) × n ⃗ ∥ 2 (11) \frac{\partial d_e}{\partial t} = \frac{\|(Rp_s + t -p_t) \times \vec n_e\|_2}{\partial t} \\ = (\frac{\partial((Rp_s + t -p_t) \times \vec n_e)}{\partial t} )^{T} * \frac{(Rp_s + t -p_t) \times \vec n_e}{\|(Rp_s + t -p_t) \times \vec n\|_2} \tag{11} tde=t(Rps+tpt)×n e2=(t((Rps+tpt)×n e))T(Rps+tpt)×n 2(Rps+tpt)×n e(11)
对于(11)式第二行左半部分的偏导数计算:
∂ ( ( R p s + t − p t ) × n ⃗ e ) ∂ t = − n ⃗ e × ∂ ( t ) ∂ t = − n ⃗ e × I 3 × 2 (12) \frac{\partial((Rp_s + t -p_t) \times \vec n_e)}{\partial t} \\ = \frac{ -\vec n_e \times \partial(t)}{\partial t} \\ = -\vec n_e \times I_{3\times 2} \tag{12} t((Rps+tpt)×n e)=tn e×(t)=n e×I3×2(12)
整理之后,得到关于点到线的误差函数关于t的导数:
∂ d e ∂ t = ( − n ⃗ e × I 3 × 3 ) T ∗ ( R p s + t − p t ) × n ⃗ e ∥ ( R p s + t − p t ) × n ⃗ e ∥ 2 (13) \frac{\partial d_e}{\partial t} = (-\vec n_e \times I_{3\times3})^T *\frac{(Rp_s + t -p_t) \times \vec n_e}{\|(Rp_s + t -p_t) \times \vec n_e\|_2} \tag{13} tde=(n e×I3×3)T(Rps+tpt)×n e2(Rps+tpt)×n e(13)

2. 点到平面(Point to Surface)

2.1 点到平面误差函数

d p = ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 (14) d_p = \| (Rp_s + t - p_t)^T * \vec n \|_2 \tag{14} dp=(Rps+tpt)Tn 2(14)

p t p_t pt:目标(地图)点云中的平面点;
n ⃗ s \vec n_s n s:近邻平面点组成的平面对应的法向量。

2.2 误差函数对R(旋转)和t(平移)的求导结果

∂ d p ∂ R = ( − ( R p s ) ∧ ) T ∗ n ⃗ ∗ ( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 ∂ d p ∂ t = I 3 × 3 ∗ n ⃗ ∗ ( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 (15) \frac{\partial d_p}{\partial R} = (-(Rp_s)^{\wedge})^T*\vec{n}* \frac{ (Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2}\\ \frac{\partial d_p}{\partial t} = I_{3\times3} *\vec{n} * \frac{(Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2} \tag{15} Rdp=((Rps))Tn (Rps+tpt)Tn 2(Rps+tpt)Tn tdp=I3×3n (Rps+tpt)Tn 2(Rps+tpt)Tn (15)

2.3 误差函数对R和t的求导推导

根据第1节的推导过程,对于点到平面误差函数的推导就非常容易了!

关于R的导数
∂ d p ∂ R = ∂ ( ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 ) ∂ R = ( ∂ ( ( R p s + t − p t ) T ∗ n ⃗ ) ∂ R ) T ∗ ( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 = ( ∂ ( ( R p s ) T ∗ n ⃗ ) ∂ R ) T ∗ ( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 = ( − ( R p s ) ∧ ) T ∗ n ⃗ ∗ ( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 (16) \frac{\partial{d_p}}{\partial R} = \frac{\partial(\|(Rp_s + t - p_t)^T * \vec n \|_2)}{\partial R} \\ = ( \frac{\partial((Rp_s + t - p_t)^T * \vec n)}{\partial R})^T * \frac{(Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2} \\ = ( \frac{\partial((Rp_s)^T * \vec n)}{\partial R})^T * \frac{(Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2} \\ =(-(Rp_s)^{\wedge})^T*\vec{n}* \frac{ (Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2} \tag{16} Rdp=R((Rps+tpt)Tn 2)=(R((Rps+tpt)Tn ))T(Rps+tpt)Tn 2(Rps+tpt)Tn =(R((Rps)Tn ))T(Rps+tpt)Tn 2(Rps+tpt)Tn =((Rps))Tn (Rps+tpt)Tn 2(Rps+tpt)Tn (16)
关于t的导数
∂ d p ∂ t = ∂ ( ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 ) ∂ t = ( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 ∗ ∂ ( ( R p s + t − p t ) T ∗ n ⃗ ) ∂ t = ( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 ∗ ∂ ( t ) T ∗ n ⃗ ∂ t = ( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 ∗ I 3 × 3 ∗ n ⃗ (17) \frac{\partial{d_p}}{\partial t} = \frac{\partial(\|(Rp_s + t - p_t)^T * \vec n \|_2)}{\partial t} \\ = \frac{(Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2}* \frac{\partial((Rp_s + t - p_t)^T * \vec n)}{\partial t} \\ = \frac{(Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2} * \frac{\partial(t)^T * \vec n}{\partial t} \\ = \frac{(Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2} * I_{3\times3} *\vec{n} \tag{17} tdp=t((Rps+tpt)Tn 2)=(Rps+tpt)Tn 2(Rps+tpt)Tn t((Rps+tpt)Tn )=(Rps+tpt)Tn 2(Rps+tpt)Tn t(t)Tn =(Rps+tpt)Tn 2(Rps+tpt)Tn I3×3n (17)

3. 对于loam代价函数的总结

loam的总体代价函数

如下:
d = ∑ N d e + ∑ M d s = ∑ N ∥ ( R p s + t − p t ) × n ⃗ e ∥ 2 + ∑ M ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 (18) d = \sum_N d_e + \sum_M d_s \\ = \sum_N \|(Rp_s + t -p_t) \times \vec n_e\|_2 + \sum_M \| (Rp_s + t - p_t)^T * \vec n \|_2 \tag{18} d=Nde+Mds=N(Rps+tpt)×n e2+M(Rps+tpt)Tn 2(18)
根据1和2小节的求导,可以得到每一个误差的导数,组成一个大的雅克比矩阵(也有可能是向量),有了雅克比矩阵之后带入高斯牛顿或者LM算法即可以求解最优的R和t。该过程是属于最优化理论相关的内容,是比较成熟的理论,不是本篇博客要探索的,不在此做细致介绍。

是否有更好的代价函数形式?

我在复现loam的过程中发现,其中点到线的误差项,也就是 ∑ d e \sum d_e de,它实际优化过程中对于R和t求解的贡献比较小,其主要原因是点到面的误差项 ∑ d s \sum d_s ds中M的数量比较庞大,在16线激光雷达中,经过我的验证M几乎是N的20倍以上,所以实际过程中,如果我们省略掉点到线的误差项,对于最终的精度并未产生明显影响。也许在插满了细长柱子的环境中点到线的误差项才会有明显作用。否则我认为多数真实环境下,点到面的误差项实际上已经涵盖住了点到线的误差。所以在后来一些开源项目中,例如r3live、fast-lio都只计算点到面的误差。

另外,我也尝试对loam的代价函数做了一些改变,如下式,构建成两个最小二乘项的求和:
d = ∑ N ( d e ) 2 + ∑ M ( d s ) 2 = ∑ N ∥ ( R p s + t − p t ) × n ⃗ e ∥ 2 2 + ∑ M ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 2 (19) d = \sum_N (d_e)^2 + \sum_M (d_s)^2 \\ = \sum_N \|(Rp_s + t -p_t) \times \vec n_e\|_2^2 + \sum_M \| (Rp_s + t - p_t)^T * \vec n \|_2^2 \tag{19} d=N(de)2+M(ds)2=N(Rps+tpt)×n e22+M(Rps+tpt)Tn 22(19)
也就是说,对代价函数计算平方二范数误差。在我的意识中,平方二范数会有更好的收敛性,上式应该会比loam的二范数收敛的更好。但是后来的实验中证明我的想法是错误的,上式的求解得到的R和t与真值差距较大。大家可以去思考一下是什么原因导致的?如果有想法的话,可以在评论区留下你的看法。

算法实现过程中的一些小细节

对于式(16)和(17),它们均包含下式:
( R p s + t − p t ) T ∗ n ⃗ ∥ ( R p s + t − p t ) T ∗ n ⃗ ∥ 2 (20) \frac{(Rp_s + t - p_t)^T * \vec n}{\| (Rp_s + t - p_t)^T * \vec n \|_2} \tag{20} (Rps+tpt)Tn 2(Rps+tpt)Tn (20)
观察可以发现,它的值是-1或者1,如果你没看出来,可以花些时间想一想,并不难!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LOAM误差函数、代价函数的雅克比矩阵详细推导,点到线和点到面误差函数求导 的相关文章

  • 从 Invoke 方法获取 RETURN

    我正在尝试从另一个线程上的列表框项目中读取值 我尝试创建一种新方法来运行调用命令 我可以设法将命令发送到列表框 例如通过调用方法添加 但我似乎无法得到响应 我似乎无法获取该项目的值 我尝试了几种方法 一旦我将它从空变为字符串 事情就开始变得
  • EventHandler 应该始终用于事件吗?

    我一直在愉快地使用自定义委托类型和通用编写事件Action委托类型 没有真正考虑我在做什么 我有一些很好的扩展助手Action and EventHandler这使我倾向于使用那些预定义的委托类型而不是我自己的委托类型 但除此之外 除了惯例
  • 如何使用 C# 以编程方式编辑 Power BI Desktop 文档参数或数据源?

    我有一个在 Power BI Desktop 中内置的报告模板 并保存为 pbix 或 pbit 文件 该模板使用DirectQuery SQL数据库作为数据源 而服务器地址和数据库名称被提取到参数中 还有一个参数包含一个ReportId
  • MSMQ接收和删除

    是否有任何选项可以在读取消息后将其从 MSMQ 中删除 比如 接收 删除可以作为原子操作运行吗 听起来您想查看下一条消息 然后在处理完成后接收它 Message message Queue Peek Queue ReceiveById me
  • 关闭整数的最右边设置位

    我只需要关闭最右边的设置位即可 我的方法是找到最右边位的位置 然后离开该位 我编写这段代码是为了这样做 int POS int n int p 0 while n if n 2 0 p else break n n 2 return p i
  • 名称查找、实例化点 (POI) 和基本类型

    以下代码针对 X 进行编译 但不适用于 double struct X void foo double void foo X namespace NN struct A void foo A foo double error foo not
  • 如何增加ofstream的缓冲区大小

    我想增加 C 程序的缓冲区大小 以便它不会过于频繁地写入 默认缓冲区是 8192 字节 我尝试使用 pubsetbuf 将其增加到 200K 原始代码 ofstream fq fastq1 cstr ios out fastq1 is a
  • 如何设置消息队列的所有者?

    System Messaging MessageQueue 类不提供设置队列所有权的方法 如何以编程方式设置 MSMQ 消息队列的所有者 简短的答案是 p invoke 对 windows api 函数的调用MQSetQueueSecuri
  • 编写具有多种类型的泛型扩展方法时的类型推断问题

    我正在为 IEnumerable 编写一个通用扩展方法 用于将对象列表映射到另一个映射对象列表 这就是我希望该方法的工作方式 IList
  • 在 C 语言中替换宏内的宏

    我正在尝试使代码部分可重用 我下面的评论片段没有达到我想要的效果 define NAME ABC define LOG SIZE NAME LEN 我想LOG SIZE决心ABC LEN 我尝试过使用 但没能让它发挥作用 LOG SIZE在
  • 在 mvc4 中创建通用 mvc 视图

    我以前也提过类似的问题 没有得到答案 如何创建一个通用的 mvc4 视图 该视图可以显示传递给它的模型列表或单个模型 模型可以是个人 组织或团体 无论传递给它的是什么 如果您正在寻找类似的东西 model MyViewModel
  • 用数组或向量实现多维数组

    我想使用单个数组或向量实现多维数组 可以像通常的多维数组一样访问它 例如 a 1 2 3 我陷入困境的是如何实施 操作员 如果数组的维数为 1 则 a 1 应该返回位于索引 1 处的元素 但是如果维数大于一怎么办 对于嵌套向量 例如 3 维
  • 将日期时间显示为 MM/dd/yyyy HH:mm 格式 C#

    在数据库中 日期时间以 MM dd yyyy HH mm ss 格式存储 但是 我想以 MM dd yyyy HH mm 格式显示日期时间 我通过使用 String Format 进行了尝试 txtCampaignStartDate Tex
  • 使用 IdentityDbContext 和 Code First 自动迁移表位置和架构的实体框架?

    我正在尝试使用 IdentityDbContext 类设置自动迁移更新 并将更改传播到整个数据库的实际 DbContext 在进入代码之前 在使用自动迁移实现 IdentityDbContext 时 我收到此错误 影响迁移历史系统表位置的自
  • 对多个对象使用事件处理程序

    我有 20 件物品List
  • MSVC编译器下使用最大成员初始化联合

    我正在尝试初始化一个LARGE INTEGER在 C 库中为 0 确切地说是 C 03 以前 初始化是 static LARGE INTEGER freq 0 在 MinGW 下它产生了一个警告 缺少成员 LARGE INTEGER Hig
  • Unity,c++ 本机插件字节数组不匹配

    在我的 C 本机插件中 我有一个调用 vector
  • IDisposable 的显式实现

    虽然有很多关于IDisposable在 SO 上找到 我还没有找到答案 我通常遵循这样的做法 当我的一个班级拥有一个IDisposable对象然后它也实现IDisposable并打电话Dispose在拥有的对象上 然而最近我遇到了一个类 它
  • 如何在c中断言两个类型相等?

    在 C 中如何断言两种类型相等 在 C 中 我会使用 std is same 但搜索 StackOverflow 和其他地方似乎只能给出 C 和 C 的结果 在C中没有办法做到这一点吗 请注意 这不是询问变量是否具有某种类型 而是询问两个类
  • 是否可以使用 Dapper 流式传输大型 SQL Server 数据库结果集?

    我需要从数据库返回大约 500K 行 请不要问为什么 然后 我需要将这些结果保存为 XML 更紧急 并将该文件通过 ftp 传输到某个神奇的地方 我还需要转换结果集中的每一行 现在 这就是我正在做的事情 TOP 100结果 使用 Dappe

随机推荐

  • Python使用Selenium WebDriver的入门介绍及安装教程

    Selenium WebDriver 入门 一 什么是Selenium WebDriver 二 安装Selenium WebDriver 2 1 安装selenium类库 2 2 安装浏览器驱动 2 3 配置环境变量 三 编写第一个Sele
  • 【Tableau案例】神奇宝贝属性及实力强弱|数据可视化

    提前声明 神奇宝贝的数据分析仅供参考 不涉及对于神奇宝贝的各种评价 另外我是初学tableau 涉及到使用的tableau操作可能很简单 复杂的还掌握不熟练 之后会拿时间系统学习tabelau 数据预处理 该数据集有721个口袋妖怪 分别包
  • 挂载VMware esxi服务器文件夹到本地ubuntu

    概述 开发安卓项目 需要在公司服务器搭建的环境 VMware esxi 上编译代码 可以将服务器上的文件挂载到本地 在本地编辑好代码后再去服务器上编译 登录服务器 使用ssh user host方式登录 例如ssh rk3566 192 1
  • 深入理解Solidity——独立汇编

    独立汇编 Standalone Assembly 上面介绍的在Solidity中嵌入的内联汇编语言也可以单独使用 实际上 它是被计划用来作为编译器的一种中间语言 在这个目的下 它尝试达到下述的目标 使用它编写的代码要可读 即使代码是从Sol
  • 图像处理(1) : 图像增强

    图像增强就是指通过某种图像处理方法对退化的某些图像特征 如边缘 轮廓 对比度等进行处理 以改善图像的视觉效果 提高图像的清晰度 或是突出图像中的某些 有用 压缩其他 无用 信息 将图像转换为更适合人或计算机分析处理的形式 图像增强可以分为两
  • Apache Beam适时有状态计算

    在先前的Apache Beam中的有状态计算中 介绍了Apache Beam中有状态计算的基础知识 重点介绍了对每个元素的处理中添加的状态特性 所谓的适时处理 是有状态计算的补充 是通过设置定时器来 在将来某个时间点上的 有状态的 进行回调
  • 编写一个Vue插件,上传NPM官网开源使用

    插件开发及上传NPM流程 完成组件封装 组件完成统一封装成插件 插件入口文件配置 src main js 中引入口文件 安装插件 配置 package json 文件 npm run lib 打包 umd min js 配置到 packag
  • JavaFX与后台交互

    目前JavaFX相关的资料都是基本语法 以及界面相关 而JavaFX面向的是RIA RIA就肯定需要和后台交互 个人研究了一下 遇到了不少问题 共享给大家 D 首先先看看JavaFX的api 一眼就能看到javafx io http包 包里
  • unity踩坑日记

    花费了一天时间一直在找bug unity打包出来的程序 我勾选了调试模式 因为的确在调试 关闭时就会停止工作 因为涉及到线程一直怀疑自己写退出时候关闭线程的有问题 但是看来看去没找到问题 就去看错误日志 Mono path 0 E Proj
  • 服务器双机热备系统,双机热备

    1 集群技术 在了解双机热备之前 我们先了解什么是集群技术 集群 Cluster 技术是指一组相互独立的计算机 利用高速通信网络组成一个计算机系统 每个群集节点 即集群中的每台计算机 都是运行其自己进程的一个独立服务器 这些进程可以彼此通信
  • Keil 5使用ST-LINK调试STM32程序

    1 下载并安装STM32 ST LINK Utility 含有驱动 2 启动STM32 ST LINK Utility 点击菜单 ST LINK Firmware 更新固件 3 打开Keil工程 设置Debug 4 开始调试
  • C语言的可变参数

    C语言可变参数原理与使用 1 原理与实现 我们定义C语言的几个宏定义来表达这个想法 使用这几个宏定义来实现可变参数函数 2 调用库函数实现 3 可变参函数的封装 1 原理与实现 C语言可变参数 void func char fmt C语言的
  • 《C#入门到精通》学习笔记 -- Console类

    第1章 知识点扩展 1 Main必须是静态 static 方法 指定了程序的唯一入口 2 Console类是内建类 通过其方法 可以在屏幕上显示消息或者从键盘获取输入 表示控制台应用程序的标准输入流 输出流和错误流 Console类继承于S
  • 网络安全毕业设计选题推荐

    0 简介 毕业季马上就要开始了 不少同学询问学长网安专业选题以及开题相关的问题 今天跟大家分享信息安全毕设选题 最新的信息安全 网络安全 专业毕设选题 难度适中 适合作为毕业设计 大家参考 学长整理的题目标准 相对容易 工作量达标 题目新颖
  • ue4 unreal NDisplay插件 简易使用 三折幕 详细...

    仅支持4 27版本 NDisplay文档 https docs unrealengine com 4 27 en US WorkingWithMedia IntegratingMedia nDisplay Overview Switchbo
  • 2020-04-09

    每日书单 每日书单 1 There is only one time in a person s life when he can make a difference That is the moment 2 Can coral be ke
  • Tracy vue3 小笔记 2 - 和 Vue 2 的区别汇总

    1 可以有多个根元素 2 子传父的 emit 多了一步在default 里预定义
  • 什么是java句柄_JAVA中的术语:句柄是啥意思

    句柄的本质 一个唯一的整数 作为对象的身份id 区分不同的对象 和同类中的不同实例 程序可以通过句柄访问对象的部分信息 句柄不代表对象的内存地址 句柄和指针的区别 程序不能通过句柄直接阅读文件中的信息 指针是可以的 从所起的作用这点来说 句
  • IDEA整合Tomcat服务器(IDEA没有Application Server选项)

    IDEA整合Tomcat服务器 IDEA没有Application Server选项 我使用的IDEA创建Java Enterprise的界面如下 没有Application Server选项 不要慌 在Settings中设置Applica
  • LOAM误差函数、代价函数的雅克比矩阵详细推导,点到线和点到面误差函数求导

    LOAM误差函数的导数详细推导 前言 LOAM对于激光SLAM的发展起到了举足轻重的作用 他提出了点到线和点到面的误差函数 通过优化的方法 得到了非常不错的激光里程计效果 我猜测作者Zhang Ji很可能是从点到线和点到面的ICP算法中找到