1.感知

机器感知系统根据各种各样的传感器来获取汽车周围的驾驶环境,包括Lidar,Camera,Radar,超声波雷达以及拾音器等。相对人类而言,机器感知是全覆盖,并且感知精度更高,能够达到厘米级别,但是机器感知在语义感知方面相差太大。

人类和汽车感知

在地图定位方面,机器感知系统则依赖高精地图。高精地图和导航地图的最大差别是有参考线,汽车需要根据参考线进行行驶,而人很大程度上是根据经验驾驶。
输出信息的比较,人类驾驶员的感知信息输出主要是大脑输出,一是道路信息,包括车道线位置,是左转还是右转车道,是否限速,实线还是虚线等。第二是动态障碍物信息,主要包括障碍物位置、类别、形状大小、相对速度、行为意图等。除此之外,人还需要通过眼睛感知交通信号灯的状态。无人车感知的信息输出主要是各个传感器的数据,固定目标更多的是依赖高精地图,减少在线识别。道路信息以高精地图作为参考,障碍物信息通常使用障碍物检测技术获取,包括检测障碍物的位置(3D位置)、类别、形状以及障碍物跟踪。此外还需要根据不同的传感器数据进行传感器融合获得更精确的感知,保证安全驾驶。
当前无人车感知主要通过摄像头来获取交通信号灯的颜色,灯的语义信息可以由地图提前标注好,长远的目标是通过V2X实现交通信号灯的感知。
相对人类驾驶而言,无人车系统为机器做了很多的工作,把固定信息都嵌入到地图里面,在线识别只针对最小集进行处理,以保证系统的高效和鲁棒性。无人车感知的缺点是强烈依赖高精地图。

多维度

感知模块可以划分为两个维度:

  • 小感知主要是完成感知任务需要具备的功能模块,包括检测、分割、识别、跟踪、融合等技术。
  • 大感知是指感知要真正的为无人车系统服务,需要考虑上下游,例如标定,定位,障碍物行为预测等,也是当前的一种研发趋势。

感知模块的维度可以根据划分目标而不同,这里给出一种感知模块的维度划分案例,包括以下6个维度:

  • 传感器维度,也称输入。主要有Lidar,Camera,Radar,Ultrasonic高精地图等。
  • 输出,主要包括障碍物,车道线和道路边界,红绿灯等。
  • 问题空间维度,例如感知模块中涉及的一些算法或者要处理的问题,包括2D算法,3D算法(高度、距离、朝向角)。按照时间可以分为静态帧检测和时序处理等。
  • 机器视觉维度,分为高语义和低语义问题,例如模型计算和几何计算。
  • 机器学习维度,分为深度学习驱动的感知和通过先验知识进行启发式设计的方法,称之为后处理。
  • 系统维度,包括硬件和软件,以及软硬件一体化。在无人车系统里,感知的硬件显得更为重要,软件需要同步于硬件。

2.传感器选择和安装

2.1传感器硬件

激光雷达

激光雷达的测距原理是激光头发射光束,打到障碍物上反射回来,到接收器接收到之反射信号的时间间隔乘以光速再除以二得到障碍物的距离,叫做TOF(Time of flight,飞行时间测距法)。
激光雷达传感器的好处在于自带光源不受外界干扰,白天晚上都可以,而且测距准确度高(厘米级的精度)。其缺点是多线激光雷达扫描还比较稀疏,尤其是当障碍物距离比较远的时候,因此,激光雷达目前并不适合做识别任务。
另外,激光雷达需要发射激光,功率限制其不能发射很远,发射太远反弹回来的信号就会很弱。目前,64线激光雷达的感知距离只有60~70米,对于高速行驶的无人车还不够。

相机

相机是最像人的一个传感器。它是被动式的,接受自然可见光的反射最后成像,受光照影响很大,白天的算法在晚上使用,开路灯和不开路灯的对感知结果影响很大,所以对算法研发挑战很大。它的优点是可以稠密感知,比如说现在的1080p图像,可以感知所有细节。
另外通过配置焦距,相机可以感知很远距离的物体,例如可以看到几百米外的物体。相机传感器的缺点是单目相机测距不准,无法做到激光雷达厘米级的测距精度。

Radar毫米波

毫米波雷达的原理和激光类似,只不过发射的是毫米波。由于它也是主动式感知设备,不太受天气、光照的影响。同时毫米波雷达还有多普勒频移效应可以测量与障碍物之间的相对速度。
其优点是测距、测速比较准,缺点是噪点很多,例如在空旷的地方反馈很多的回波,实际可能是路面的反馈信号而不是障碍物。其次它对于非金属的反射信号比较弱,召回比较低,例如在它面前走过行人有可能漏掉。最后毫米波雷达也是稀疏感知,无法做识别任务。
除了以上三种常见的传感器,还有一些用的相对少的传感方法,例如超声波,高精地图,Image-Lidar。
超声波的感知距离有限,对金属感知距离3米左右,对非金属只有1~2米。此外它的发射头是扇形的,扇形之外无法感知。
高精地图是先把静态元素储存好做成先验知识。它的优点是可以无差错的精确感知,减轻现场感知负担和依赖,其缺点是加重了整个系统对高精度地图和高精度定位的依赖。
Image-Lidar同时集结了激光和图像的好处,接收器同时对可见光、激光都有响应。

2.2传感器选择

首先需要对车辆建立,可以由厂家提供CAD模型,在真正安装之前,需要在软件环境里面放传感器,考虑以下因素对传感器的安装位置做出最合适的决定。第一是障碍物遮挡情况,这就是为什么很多无人驾驶车的传感器安装在车顶的原因。第二是方便传感器融合。传感器的融合需要不同传感器在视野上有重叠,否则很难进行传感器融合。

3.传感器标定

传感器标定是通过实验建立传感器输出与输入之间的关系并确定不同使用条件下的误差这样一个过程。

标定的核心概念是得到传感器之间的相对位置,将不同传感器的数据在同一个坐标系中表示。
标定分为内参标定和外参标定。

  • 内参:传感器自身性质,有些是厂家提供,有些需要自行标注,例如Camera焦距的定期矫正,Lidar中各激光管的垂直朝向角。
  • 外参:传感器之间的相对位置和朝向,用3自由度的旋转矩阵和3自由度的平移向量表示。

3.1传感器标定算法

有些算法是在搭建的标定间完成,有些是在自然环境中完成,在自然环境中标定对算法的依赖度比较强。

  • Lidar内参标定:相对于摄像头,激光雷达的内参标定有一定的特殊性。
  • Lidar-to-GPS外参标定:计算出Lidar与车上GPS的相对位置。GPS的位置由世界坐标系中的3D点表示,因此计算出外参之后可以计算得到Lidar在世界坐标系中的位置。
  • Lidar-to-Lidar外参标定:计算不同Lidar之间的相对位置。
  • Lidar-to-Camera外参标定:计算Lidar和相机之间的相对位置。
  • Camera-to-Camera外参标定:计算不同相机之间的相对位置。
  • 自然场景中的Lidar-to-Camera外参标定:在自然环境中,驾驶车辆进行两种不同传感器之间的位置关系求解。
  • 自然场景中的Bifocal Camera外参标定:双焦点摄像头之间外参的计算,也是就是不同焦点的相对位置。
  • Camera-to-Radar外参标定:摄像机到毫米波雷达的外参计算。
标定案例:3D标定间制作

在空旷房间的墙面贴满不同的二维码Apriltag,在标定间中间放置一个基于激光雷达的毫米级高精度Rigel激光扫描仪,通过对墙上二维码的多次扫描,完成3D建模,获得了标定间任何一个点的3D位置。
根据建模结果输出一个查找表,查找表由两栏组成,第一栏是Tag_ID,表示各个二维码的ID编号,第二栏是二维码四个角的3D位置信息。之后即可在标定间进行不同传感器的参数标定。

Camera-to-Camera外参标定

假设在采集车前部安装双Camera,Camera1是60度广角短焦距相机,Camera2为30度广角长焦距相机,两者视角部分重叠。
将车开到标定间,双Camera采集标定间的二维码,获得多个二维码对应四个角点的UV坐标,同时通过查找表得到对应点在3D世界坐标系(Rigel)中的坐标。
求解采集点的PNP问题的,得到相机相对于世界坐标系的位移矩阵Ts和Tl,将这两个相对位移矩阵相互传递,得到二者之间的相对位置。

需要注意的是,标定完传感器之后需要进行验证。相机标定的验证方法为,将长焦相机的图像投影到广角相机图像中,看看重合度如何。如果出现重影或者连接不好,则需要重新标定。

Lidar-to-Camera外参标定

将Camera看到的所有Tag角点与Rigel扫出的对应点的3D坐标进行匹配,求解PNP问题,得到Camera相对于Rigel世界坐标系的相对位置。
将Lidar激光雷达扫描得到的点云与Rigel是稠密的点云之间进行ICP(Iterative Closest Point,迭代最近点)匹配,得到激光雷达相对于Rigel的位置。最后将两个位置矩阵相互传递得到Camera 和 Lidar之间的相对位置。

其标定结果验证方法是将激光雷达感知到的3D点云投影到Camera拍摄的图像上,看边界是否一致,如果不一致需要重新标定。

Lidar-to-Lidar外参标定

将每一个Lidar 激光雷达扫描得到的点云与Rigel是稠密的点云之间进行ICP匹配,分别得到激光雷达相对于Rigel的位置。最后将两个位置矩阵相互传递得到Lidar和 Lidar之间的相对位置。
验证方法为:将两个激光雷达采集到的点云都投到真实物理世界中,看点云是否模糊、是否锐利。如果比较模糊,则需要重新标定。

Lidar内参标定

借助Rigel,在开阔平坦的场景下进行完整扫描,得到场景的点云。然后,将要标定的激光雷达对同一个场地进行同样的扫描。之后对两次扫描的点云进行匹配,如果激光雷达的内参不准确,会出现远距离地面点浮在空中的现象。

Lidar-to-GPS外参标定

将车辆在空旷地区绕八字行驶多次,记录多个时间点GPS给出的车辆位置信息(相对于GPS为原点的世界坐标系),将Lidar捕捉的多帧点云投影到世界坐标系中,并进行拼接,求解优化获得外参。

自然场景的Lidar-to-Camera外参标定

由于没有了Rigel-Tag,需要在标定的场景中寻找具有明显边缘的物体作为参照物,将该参照物的点云边缘和Camera拍摄图像的边缘对齐作为参数标定效果的考量指标,如果对齐,这表示标定结果良好。
过程类似于Camera-to-Camera外参标定,但是需要在自然场景中找到边缘锐利的物体作为参照物。

Camera-to-Radar外参标定的重点是得到Radar相对于Camera的Pitch角的上下倾斜问题。通常情况下Radar是水平安装的,问题就转换为求得Camera相对于地面的Pitch角。由于Camera-to-Lidar已经标定好,可以通过Lidar采集到的平面信息解决倾角问题。

4.感知算法

4.1Lidar点云感知(检测)

点云障碍物感知的主要任务是感知障碍物的位置、大小、类别、朝向、轨迹、速度等。核心是点云检测分割技术,可以用启发式算法NCut和深度学习算法CNNSeg完成。

启发式方法:Ncut

基本思想:基于空间平滑性假设,即空间上接近的点来自同一个障碍物。

  • 首先,利用地图信息对点云进行预处理,ROI过滤,降低点云复杂度。
  • 基于点云构建加权图G=(V, E, W);
  • 将点云检测问题建模为图分割问题,可以利用图聚类的算法求解,最终求解的每一个cluster就代表一个障碍物。

优点:解释性好;
缺点:分割规则过于简单,难以应对实际情况(草丛、绿化带),主要原因在于缺乏语义信息。

DL方法:CNNSeg

主要思想:利用卷积神经网络来处理激光雷达捕获的点云数据,并对点云中的目标进行识别。
深度学习是数据驱动的,把人工构造特征的任务交给机器和算法去完成(即特征学习)。

在百度的深度学习感知实现过程中,团队尝试了很多方法,下面就简单介绍算法研发的历程:

  1. 将所有点云都投到前视图(front-view)(投影面是一个圆柱面)来构造特征,将点云问题转化为矩阵问题,进而使用深度学习进行处理。通过构建全卷积神经网络对前向视图进行处理。
  2. 借助自采集车队,采集更多的实际数据,并且扩展数据视角,制作俯视图,通过将俯视图+前视图相结合的方式进行训练。同时,修改Loss函数,包括使用3D回归和Segmentation的损失函数。经过多次实验,发现基于俯视图的Segmentation方法效果最好。该方法目前已经在Apollo中开源。
  3. 俯视图没有高度信息,因此把前视图和Camara图像加进来进行辅助检查,利用Lidar的测距准和Camera识别准优势完成了Middle-Level Fusion方法(Multi-View 3D Object Detection Network for Autonomous Driving),发表在CVPR 2017。该方法使用俯视图提取Proposal,利用前视图和光学图像辅助进行更加精准的位置回归。

4.2视觉感知(全面)

视觉感知最早从ADAS发展而来。随着深度学习技术的发展,尤其是在视觉领域的巨大成功,视觉感知的主流技术路线已经变为“深度学习+后处理计算”的方法。该方法带来了以下几个变化:要求计算硬件升级、数据的需求量大增、如何评估保证安全性。
面向自动驾驶的深度学习算法具有以下几个特点:

  • 2D感知向3D感知渗透,模型输出更丰富(后处理需要的3D信息、跟踪信息、属性信息等都会放在CNN中进行学习)
  • 环视能力构建(传统方法靠一个Camera完成前向检测、碰撞检测、车道线检测。无人驾驶需要环视)
  • 感知+定位+地图紧密结合

CNN检测

CNN检测,从最开始的AlexNet,VggNet到ResNet等,持续提高了ImageNet图像检测的精度,更多的细节和最新进展可以参考Kaiming He(何凯明)的系列工作。

需要注意的是,目前发表的大部分关于检测的成果都是面向计算机视觉应用的,与自动驾驶领域的检测还有很大的区别:

  • 自动驾驶的几何约束很多,用来辅助检测;
  • 自动驾驶中的检测模型需要输出的信息更多,包括障碍物的尺寸、朝向。
    同时自动驾驶还需要考虑时序性,称为局部的End-to-End,检测、2D到3D转换、跟踪三步是自动驾驶视觉感知的组成,后面两步都由CNN来学习,减少人工干预。
  • 自动驾驶需要多任务学习、网络结构适配。自动驾驶需要针对不同的障碍物特征(车道线,道路边界,定位元素)进行识别。
  • 自动驾驶需要属性识别,即除了障碍物级别的输出以外,还需了解速度类别朝向等问题,例如车尾灯状态,车门开闭状态。通过标注数据,由数据驱动的深度学习来自动学习这些更细的属性。

CNN分割

分割(Segmentation)与detection在本质上是一样的,是对一个目标的不同力度的刻画。分割是一种更细粒度刻画物体边界信息的检测方法,不再是画框,而是进行边缘分割。
在感知中,对于不规则物体,往往需要进行分割处理。例如

  • 场景分割,可以用于多传感器融合,例如对绿植进行分割,结合LiDAR点云,就可以测出绿植的类别和距离。
  • 可行驶区域感知,可以对一些非结构化道路的路径规划提供支持。

在车道线感知中,应视具体情况使用分割或者检测方法。

后处理

后处理直接针对下游模块,对后续的影响比较直接。在视觉感知中,后处理主要分为三个部分:
(1)2D-to-3D的几何计算。2D到3D的转换需要考虑的因素包括:

  • 相机pose的影响
  • 接地点
  • 稳定性

(2) 时序信息计算。针对跟踪处理,需要注意以下几点:

  • 对相机帧率和延时有要求,要求跟踪必须是一个轻量级的模块,因为检测已经占据大部分时间;
  • 充分利用检测模型的输出信息(特征、类别等)进行跟踪;
  • 可以考虑轻量级Metric Learning

(3)多相机的环视融合

  • 相机布局决定融合策略,要做好视野重叠 。

4.3红绿灯感知

红绿灯感知是百度无人车第一个使用深度学习、使用Camera的模块。
红绿灯感知的任务是在距离停止线50~-2米的范围内精准识别红绿灯亮灯状态。
难点在于:

  • 检测精度要求非常高,必须达到三个九(99.9%),否则会出现闯红灯,违法交规的情况。
    另外召回也不能太低,影响通过率和体验。

  • 红绿灯感知需要应对各种环境,包括天气和光照。

  • 红绿灯的制式非常多,包括距离、高度、横纵、信号状态等,红绿灯感知都需要识别。

基于深度学习的红绿灯感知模块

自动驾驶中使用深度学习进行红绿灯感知模块的构建,主要分为以下几步:

  1. 相机选择和安装。相机选择需要注意几个重要的参数:
    一是相机的高动态比HDR要高于100db;
    二是拍摄图像的分辨率要达到1080P,满足15pixel大小的灯能够看得到。
    在实际应用中,使用双Camera,长短焦切换,六毫米适用于近距离。
  2. 高精地图的交互。需要把一些固定信息交给高精地图去完成,算法只实现在线变化的一些因素。地图提供灯组3D坐标和交通含义,算法只看RoI区域,避免形状识别出错。
  3. 使用深度学习识别灯颜色的变化。主要分为检测和颜色分类两步。

实际使用过程中可能会更复杂。如果一条道路上有很多红绿灯,检测算法会把所有的灯都检测出来。把对应关系匹配起来,需要做3D到2D的投影,投影又受到标定、定位、同步、地图等因素的影响,需要综合考虑才能解决好这个问题

4.4 Radar感知

下图右边是Radar的点云信号投影的成像。图中有很多的点,但是并不是所有的点都是障碍物,存在很大的噪音,需要进行鉴别。
图中明显成一条线的点是对路边界金属栅栏的感知结果。因为金属的反射信号比较好,所以雷达点会成直线分布。基于该特征,可以用Radar反射信号来做高速路道路边缘栅栏的检测。

4.5超声波感知

超声波只能进行近距离感知,并且无法感知具体的位置。对无人驾驶来说,行驶过程中帮助并不大,更多的是用于倒车和特别近距离的感知。

举例,在车上布了12个超声波传感器,每个超声波探头覆盖一个角度,大概检测到三米范围内的障碍物。当某个地方有障碍物,传感器发送超声波,收到回波信号以后可以得到障碍物的距离信息,但是并不能确定在覆盖范围内哪个地方有障碍物,如图中的绿线。如果两个探头感知范围存在over lap,这两个传感器的两根绿线会交接,就可以确定障碍物的准确位置。

5.机器学习与感知

自动驾驶感知中的机器学习对感知的准确率、召回率和响应延时要求很高。
例如在自动驾驶中的感知机器学习出现一些障碍物的漏检、误检会带来安全问题。漏检会带来碰撞,影响事故;误检会造成一些急刹,带来乘车体验的问题。同时要求低延时。

5.1机器学习

应对corner base

机器学习里面存在一个普遍的假设:训练集和测试集是独立同分布的。但是无人车感知的训练集是封闭的,而测试集是开放的。

为了应对corner case:或者拓展模型能力,提高识别泛化能力;或者升级对应用场景的全面识别,将corner base最小化。

可解释性的需要

如何评估模型?如何回归测试?如何得到使用边界?

目前认为可解释性可以通过测试来体现,如果大量测试得到相同的结果,那么原理是不是真正的可解释也就没那么重要。

深度学习之外
  • 还需要其他非机器学习方法,需要融合两种方法;
    在感知模块中,后处理阶段等由公式表示的几何计算问题是不需要深度学习的。另外,Common sense也不需要深度学习,而且深度学习的效果不好。
    现在主要是基于Double check来提升安全性,还需要其他方法来进行更好的融合。
  • 需要其他机器学习方法。
    如果数据量小,特征很难从原始数据学习,深度学习的效果可能就受到影响,因此诸如SVM或者随机森林这些机器学习算法,可能需要结合场景选择。

5.2 感知的未来

Sensor迭代

成本问题

深度学习+仿真数据+AI芯片

深度学习计算量很大,专门研究车载AI芯片是对这一问题的很好解决方案。
现在很耗时的CNN模型以后都不是瓶颈,而且定制AI芯片的功耗可以足够低,满足车载需求。
深度学习需要大量数据的问题,可以通过仿真来弥补。目前,点云仿真相对简单一些,图像仿真相对困难点。另外,仿真+深度学习不断循环迭代,是非常有前景的。

智能交通设施

自动驾驶都是在车上安装传感器进行感知,感知的范围、鲁棒性都有待提高。
如果将这套传感器布置在道路上、灯上,然后将实时感知结果传输给无人车。如果车上的传感器失灵,那么路面上的传感器会告知无人车障碍物信息,保证系统安全性。另外在驾驶环境中部署传感器可以拓展感知距离,做到足够安全,提前告知远处的信息。

Apollo自动驾驶进阶课(5)——Apollo感知技术相关推荐

  1. Apollo自动驾驶进阶课(4)——Apollo无人车定位技术

    1.无人车自定位系统 1.1自定位系统 无人车的自动定位系统:相对一个坐标系,确定无人车的位置和姿态. 这个坐标系可以是一个局部的坐标系,也可以是一个全局的坐标系,比如全球坐标系,可以知道一个很精确的 ...

  2. Apollo自动驾驶进阶课(3)——高精度地图

    1.高精度地图与自动驾驶 在SAE的六等级分类方法中,L0级别是人类驾驶,L1到L3级别是辅助驾驶,L3以上是自动驾驶.L3级别以下不需要高精地图,但在L3.L4级别,高精地图是标配. 1.1高精度地 ...

  3. apollo自动驾驶入门课-高精地图

    apollo自动驾驶入门课-高精地图 文章目录 apollo自动驾驶入门课-高精地图 前言 一.高精地图与传统地图的区别 二.高精度地图与感知.定位.规划的关系 2.1 高精地图与感知 2.2 高精地 ...

  4. Apollo自动驾驶开发笔记47——apollo编译报错this rule is missing dependency declarations for the following files

    Apollo自动驾驶开发笔记47--apollo编译报错this rule is missing dependency declarations for the following files 报错信 ...

  5. Apollo自动驾驶入门课程第⑤讲 — 感知(下)

    目录 1. 卷积神经网络 2. 检测与分类 3. 跟踪 4. 分割 5. Apollo感知 6. 传感器数据比较 7. 感知融合策略 本文转自微信公众号:Apollo开发者社区 原创: 阿波君 Apo ...

  6. Apollo自动驾驶入门课程第④讲 — 感知(上)

    目录 1. 感知的概述 2. 计算机视觉 3. 摄像头图像 4. LiDAR图像 5. 机器学习 6. 神经网络 7. 反向滤波法 本文转自微信公众号:Apollo开发者社区 原创: 阿波君 Apol ...

  7. apollo自动驾驶进阶学习之:canbus模块代码分析

    文章目录 封面 代码架构 内容结构 封面 apollo自动驾驶:canbus模块代码讲解及测试(1)引言 apollo自动驾驶:canbus模块代码讲解及测试(2)框架讲解 代码架构 但是apollo ...

  8. Apollo自动驾驶实践课(4)——车辆动力学标定

    通过Apollo软件进行车辆踏板标定的基本原理和方法步骤,了解车辆标定的作用,掌握标定后的数据处理过程,通过实际操作演示标定过程,帮助开发者快速掌握车辆方法和标定流程. 1.标定的目的和基本原理 Ap ...

  9. apollo自动驾驶进阶学习之:如何调试减速带通行限速参数

    首先需要理解Planning模块是基于Scenario.Stage.Task这样的层次来进行的,即:场景->步骤->具体的决策方法.Apollo可以应对自动驾驶所面临的不同道路场景,都是通 ...

最新文章

  1. request.getParameterMap()的坑
  2. python零基础实例-Python初学零基础也不怕,从0开始!
  3. Xcode 6 allows VECTOR image assets… any idea how to use them?
  4. mysql 查看端口_新手连接MySQL数据库,再也不怕连不上了
  5. 润乾ajax,通过异步请求实现报表组功能
  6. mybatis:延迟加载时不要在get/set方法上面添加final关键字(原创)
  7. 从 TFS 迁移源代码到 git
  8. C++主要操作符重载的定义和总结
  9. 美股本周第二次熔断:道指大跌近10% 费城半导体指数大跌11%
  10. 特斯拉自动驾驶遭遇中国性价比强敌!纽劢(mài)L3方案发布,成本1万3
  11. sql server 多用户 并发_Tinyid:滴滴开源千万级并发的分布式ID生成器
  12. Python 标准库 —— os 模块
  13. WEB前端使用SheetJS读写excel文件
  14. 西门子plc软件 linux,西门子PLC编程软件
  15. Anaconda 安装步骤
  16. 搭建第一个springBoot 摘抄自蚂蚁课堂
  17. 虚拟机安装VMware tools
  18. matlab误差平方和
  19. 计算机组成原理第三部: 总线与IO系统
  20. 杀了一个程序员祭天换来今天的正常推送:仿知乎APP源码分享

热门文章

  1. Java征途:行者的地图
  2. 自动化测试 - 单元测试
  3. C#/VB.NET 创建PDF/UA文件
  4. 大数据术语英文翻译及详解
  5. OSChina 周四乱弹 ——产品经理被黑的最惨的一次
  6. oppoR9m降级 root刷机 Magiskroot 解锁system文件夹
  7. Unity技术-开发规范
  8. 腾讯云[HiFlow】| 自动化 -------HiFlow:还在复制粘贴?
  9. 关于自驾海边扎营的一些经验
  10. Unity实现对电脑文件夹和文件的重命名方法