1 面试要求
国智汽-面试要求.jpg
2 薪资水平
24k ~ 27k x 14薪资
总包 33.6w ~ 63w
2 面试题目:
1 是否做过激光雷达相关slam?
答: 没有,只了解过pcl
2 vslam的前端和后端分别代表什么意思?
答: 答的不是很好,并未结合实际项目进行讲解,面试官是要我结合项目进行解释。
3 项目中深度相机的外参是如何确定的?
答: 直接拼接图像得到,并未答的很好。
4 项目中建图和定位分别是怎么做的?
答: 建图先建立好,定位是视觉进行角点匹配,完成定位。
5 优化模型是什么?角点匹配过程中产生的噪声是怎么处理的?
答: 模型口述
6 具体使用过哪些传感器,传感器的参数分别是什么?
答: 具体使用过深度相机、激光雷达、IMU、超声测距仪,具体参数不详。
3 面试题目解答
1 需要补充slam激光相关知识,包括ros。
2 前端 :
前端是一个求解运动变换的过程,并未后端提供初始的数据。大致可以分为特征的检测、特征匹配和运动变换估计三个步骤。
后端:
后端是一个优化求解的过程,一般可以分为构建位姿图、闭环检测、优化位姿图和生成轨迹和地图四个步骤。利用前端的处理结果构建出初始的点边位姿图,以相机的位姿信息为节点,以相邻位姿的运动转换信息为边构建约束图像,利用闭环检测添加闭环约束,在全局范围内对位姿图进行优化求解,进而获得优化后各个节点的新的位姿信息和运动转换信息,利用全局优化后的运动转换信息将点云进行拼接,最后生成全局一致性轨迹和地图。
todo: 需要更加详细的实例支撑
3 视觉照相机内参的确认: 张正友标定法
内参本质是空间中一物体P在相机坐标系下的坐标与像素坐标系下坐标的映射关系。
相机内参.png
视觉相机中外参的确认:
由于一般物体不可能以相机坐标系来处理,因此外参矩阵本质上是物体在世界坐标系下的坐标与相机坐标系的转换关系,两个坐标系的转换关系包括旋转和平移操作。
相机外参.png
在项目中,相机内参需要进行标定。其中世界坐标系的原点在墙面左下角,相机外参实际是最左侧相机坐标系到世界坐标系的映射,其余的相机根据最左侧的相机确定自己的位置。其中最左侧相机的位置相对于世界坐标系的R和t是可以计算出来的。并且多个深度相机需要拼图获得完整的深度图像,这里涉及如下坐标系。
世界坐标系: 以墙面左下角为原点,x轴垂直墙面,z轴向上
吊篮坐标系: 吊篮左下角,静止时,相对于世界坐标系有z轴上的平移
最左侧相机坐标系: 相对于吊篮有固定安装位置。
4 答: 建图时,根据事先测量好的信息得到2个矩阵,分别为深度矩阵和喷涂矩阵。其中深度矩阵表示地图的深度信息矩阵,其中将整体地图按照 50mm x 50mm 进行分割,将区域进行划分。喷涂矩阵是指用0、1来区分哪些需要喷涂,哪些不需要喷涂。
详细特征定位算法:
1 从当前地图中解析出地图中角点信息
2 根据激光雷达传感器深度信息,解析出当前激光雷达采集的角点信息
3 用当前激光雷达角点和地图角点进行匹配
MatchResult result = PointMatcher.Matching(mapcorners, ridarcorners);
匹配算法如下:
- 1 先提取激光雷达上角点和下角点信息。
- 2 再提取地图中上角点和下角点信息。
激光雷达角点提取算法:
根据梯度变化的方向,分别扫描出上水平边,下水平边,左垂直边,右垂直边
List<byte[,]> horiEdges = FindHorizontalEdgeInt(depthmatrix, threshold);
List<byte[,]> vertEdges = FindVerticalEdgeInt(depthmatrix, threshold);
points = FindUpperLeftCorner(edgeA, edgeD);
points = FindUpperRightCorner(edgeA, edgeB);
points = FindLowerRightCorner(edgeC, edgeB);
points = FindLowerLeftCorner(edgeC, edgeD);
水平边提取算法,本质还是通过梯度的变化分别提取上水平边和下水平边
// 这里threshold = 50 mm
private List<byte[,]> FindHorizontalEdgeInt(int[,] depthmatrix, int threshold)
{
int rowcount = depthmatrix.GetLength(0);
int colcount = depthmatrix.GetLength(1);
byte[,] EdgeA = new byte[rowcount, colcount];
byte[,] EdgeC = new byte[rowcount, colcount];
double[,] deltaArray = new double[rowcount, colcount];
for (int col = 0; col < colcount; col++)
{
EdgeA[0, col] = 0;
EdgeC[0, col] = 0;
}
double neg_threshold = -1 * threshold;
for (int row = 1; row < rowcount; row++)
{
for (int col = 0; col < colcount; col++)
{
double delta = depthmatrix[row - 1, col] - depthmatrix[row, col];
deltaArray[row, col] = delta;
if (delta > threshold)
{
EdgeC[row - 1, col] = 1;
}
if (delta < neg_threshold)
{
EdgeA[row, col] = 1;
}
}
}
List<byte[,]> array = new List<byte[,]>();
array.Add(EdgeA);
array.Add(EdgeC);
return array;
}
其中判断为角点的算法如下:
public int innerBond = 3;
public int borderBond = 5;
private List<int[]> FindLowerLeftCorner(byte[,] horiedge, byte[,] vertedge)
{
List<int[]> locations = new List<int[]>();
int matrixheight = horiedge.GetLength(0);
int matrixwidth = horiedge.GetLength(1);
for (int row = 3; row < matrixheight; row++)
{
for (int col = 0; col < matrixwidth - 3; col++)
{
int outcount = horiedge[row, col + 1] + horiedge[row, col + 2] + horiedge[row, col + 3] +
vertedge[row - 3, col] + vertedge[row - 2, col] + vertedge[row - 1, col];
int inercount = horiedge[row - 3, col + 1] + horiedge[row - 3, col + 2] + horiedge[row - 3, col + 3] +
horiedge[row - 2, col + 1] + horiedge[row - 2, col + 2] + horiedge[row - 2, col + 3] +
horiedge[row - 1, col + 1] + horiedge[row - 1, col + 2] + horiedge[row - 1, col + 3] +
vertedge[row - 3, col + 1] + vertedge[row - 3, col + 2] + vertedge[row - 3, col + 3] +
vertedge[row - 2, col + 1] + vertedge[row - 2, col + 2] + vertedge[row - 2, col + 3] +
vertedge[row - 1, col + 1] + vertedge[row - 1, col + 2] + vertedge[row - 1, col + 3];
// 判断是否为角点的充分必要条件为当前点的右侧和下方要有足够多的点落在边上,同时当前点内部要有足够少的点落在水平直线和垂直直线上。
if (outcount >= borderBond && inercount < innerBond)
{
locations.Add(new int[] { row, col });
}
}
}
return locations;
}
- 然后地图中的上角点和激光雷达中的上角点进行匹配
匹配时对比的是角点所在位置的行列值;
public MatchResult OffsetBasedOnPairs(CornerBase[] modelpairs, List<CornerBase[]> cloudpairs)
{
int deltarow = 0;
int deltacol = 0;
int error = 100;
int length = modelpairs[1].Col - modelpairs[0].Col;
foreach (CornerBase[] paris in cloudpairs)
{
int dist = Math.Abs(paris[1].Col - paris[0].Col);
if (Math.Abs(dist - length) < error)
{
error = Math.Abs(dist - length);
deltarow = modelpairs[0].Row - paris[0].Row;
deltacol = modelpairs[0].Col - paris[0].Col;
}
}
MatchResult result = new MatchResult();
result.DeltaRow = deltarow;
result.DeltaCol = deltacol;
result.Error = error;
return result;
}
匹配的时候,分别匹配上角点和下角点。根据计算当前设备相对于地图的偏移量,从而完成吊篮的定位工作。定位完成后再利用IMU结合螺旋桨对自身位姿的定位,以及PID算法调平,修正吊篮姿态。
5 喷涂吊篮的数学模型,优化方法
6 项目中使用的传感器
激光雷达
- 品牌名称: Livox 觅道 Mid-70 激光探测测距仪
参数.png
亦可参考:
https://www.livoxtech.com/cn/mid-70/specs
https://zhuanlan.zhihu.com/p/311315203
其中数据延迟 < 2ms, 点云输出100000 点/s, 项目中的数据传输频率选择的是10HZ,也就是100ms积分累加时间。
原理:
用成本较低的半导体原件实现激光生成和探测,采用非重复扫描技术。
Mid -70成为低速自动驾驶系统补盲的首选。但其实,觅道-70的探测距离可远至260米@80%反射率,在低速场景下完全可用作建图定位激光雷达。
深度相机:
- 品牌名称 realsense d435
参考: https://www.jianshu.com/p/9e3d31ba35da
IMU:
- 品牌名称 阿路比IMU
毫米波雷达
-
品牌名称
UWB: 唐恩科技
image.png
光流传感器
北航的一个硕士在淘宝上卖的
image.png
4 应聘者询问
1 公司目前的产品矩阵是什么样的?
2 公司的发展情况?
3 去公司后具体负责什么?
4 公司打算找一个什么样的人?
5 公司的薪资结构?
6 公司的激励措施?








网友评论