Interpolation - shading and occupy map(hector slam)
1. Introduction
最近学习hector slam (A Flexible and Scalable SLAM System with Full 3D Motion Estimation paper , github page) 的时候注意到里面对插值的使用。
同时,之前的时候也在unity使用shading的时候,研究过各种shading方法的使用。突然发现他们之间其实有很多共通的点,他们都会对一个场分布进行插值,对标量和向量插值(slam中对偏导方向插值,shading中对面的法向插值)。
所以打算自己总结一下,以便自己和后人方便回忆和学习。
2. slam - 拉格朗日插值
Hector SLAM使用的是最普通的拉格朗日插值法。
2.1 一维线性插值
对于函数y=f(x),已知函数对应点{ x_i }的值{ y_i }:
如果存在:
使得 成立,则称Ln(x)为f(x)的插值多项式。
可以证明Ln(x)存在且唯一
2.2 二维简单插值
Hector SLAM使用的就是上面的一维拉格朗日插值在二维的简单拓展。使用了只取最近邻四个点的简单形式。由于拉格朗日插值的存在唯一性,可以证明它使用的插值形式是正确的。
它的实现代码如下所示:
// the map coordinate of the current point
int cell_x, cell_y;
cell_x = floor((coords(0) - map->origin_x) / map->resolution) + map->size_x / 2;
cell_y = floor((coords(1) - map->origin_y) / map->resolution) + map->size_y / 2;
// transform (x, y) to (u, v)
double u = (coords(0) - map->origin_x) / map->resolution + map->size_x / 2 - (double)cell_x;
double v = (coords(1) - map->origin_y) / map->resolution + map->size_y / 2 - (double)cell_y;
// get the neighbour scores
double z1 = map(map,cell_x,cell_y);
double z2 = map(map,cell_x+1,cell_y);
double z3 = map(map,cell_x+1,cell_y+1);
double z4 = map(map,cell_x,cell_y+1);
// interpolate the score to get the field value
ans(0) = (1 - u)*(1 - v)*z1 + u*(1 - v)*z2 + u*v*z3 + (1 - u)*v*z4;
// calculate the derivatives
ans(1) = ( v*(z3 - z4) + (1 - v)*(z2 - z1) ) / map->resolution;
ans(2) = ( u*(z3 - z2) + (1 - u)*(z4 - z1) ) / map->resolution;
3. Smooth Shading
在这里主要比较两种常用的shading方法。
- Phong shading是使用向量进行插值,Gouraud shading使用的是标量进行插值。
- Phong shading的计算时间更久。
- Phong shading会得到更好的效果。在这个页面 show page 可以清晰地看出两种shading方法的效果比较。
另外可以参考 implentation unity shader 里面有作者进行的unity实现。
3.1 Gouraud shading
Gourand shading的过程和上面介绍的hector slam中的插值过程完全一样。使用的是bilinear interpolation wiki page。
下面是来自百科的公式推导,和上面使用的插值一模一样。在这里就不详细说明了。
3.2 Phong Shading
3.2.1 color
在phong shading中,对颜色进行了更加完善的处理,将颜色分为ambient color,diffuse color 和 specular color进行处理。如下(opengl实现)所示:
gl_FragColor = vec4(Ka * ambientColor +
Kd * lambertian * diffuseColor +
Ks * specular * specularColor, 1.0);
slerp
slerp interploation 主要用在向量插值上