《点云库PCL学习教程》第3章 PCL基础.ppt





《《点云库PCL学习教程》第3章 PCL基础.ppt》由会员分享,可在线阅读,更多相关《《点云库PCL学习教程》第3章 PCL基础.ppt(104页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第3章 PCL基础本章首先简述了PCL C+编程规范,为以后章节的阅读和读者编写出PCL风格的代码做一定铺垫,为了让用户基于PCL开发出自己的扩展,紧接着通过实例详细介绍了在PCL框架下如何建立用户自定义类,最后介绍了PCL中点的已有类型以及如何自定义点类型以满足扩展需求。掌握第3章的内容之后,读者可轻松阅读PCL源码和后续章节中的例子程序,也为读者后续自行开发奠定了基础。本章各小节目录3.1 PCL C+编程规范3.2 如何编写新的PCL类3.3 PCL已有点类型介绍和增加自定义的点类型3.4 PCL中异常处理机制3.1 PCL C+编程规范架构师为了确保在PCL中所有代码风格的一致性,使得
2、其他开发者及用户容易理解源码,PCL开发者制定并遵循着一套严格的编写规范,PCL的开发者都默认此规范,除非有充足的理由才可以不遵循这些规范。当然这些规范也并不是一成不变的,但提出和更改规则的人需要考虑兼容性,那就是让新加的规则与现有的所有代码相适应。3.1.1 PCL推荐的命名规范推荐的命名规范1.文件命名文件命名(1)所有的文件名单词之间应该用下划线隔开,例如unordered_map.hpp。(2)头文件的扩展名为.h。(3)模板类实现文件的扩展名是.hpp。(4)源文件的扩展名是.cpp。2.目录命名目录命名所有的目录及其子目录命名应该符合,如果由多个单词组成,其之间用下划线隔开,PCL
3、中各个目录遵循以下规则:(1)头文件都应放在源码目录树中的include/下。(2)模板类实现文件都应放在目录树中的include/impl/下。(3)源文件都应放在目录树中的src/下。3.Include语句语句当文件在同一目录下时Include指示语句用双引号,在其他情况下则用尖括号,例如:#include#include#include“file_name.cpp”/在同一目录下4.宏定义命名宏定义命名宏定义中字母都采用大写格式,为头文件所定义的宏最后面还需要加上下划线,并且名称从include下目录开始,例如pcl/filters/bilateral.h对应PCL_FILTERS_BI
4、LATERL_H_。#ifndef和#define定义放在BSD协议后面代码前面。#endif定义一直在文件结尾,并且加上一句注释掉的宏对应头文件的宏定义,例如:/the BSD license#ifndef PCL_MODULE_NAME_IMPL_FILE_NAME_HPP_/为避免重复包含头文件而定义的宏#define PCL_MODULE_NAME_IMPL_FILE_NAME_HPP_/the code#endif/PCL_MODULE_NAME_IMPL_FILE_NAME_HPP_5.命名空间命名命名空间命名命名空间多于一个单词的,单词之间应该用下划线连接,例如:namespac
5、e pcl_io 6.类类/结构命名结构命名类名(和其他自定义类型的名称)应该是CamelCased(驼峰命名)命名规范,也就是连写单词组成命名,每个单词首字母大写。但是有例外:如果类名包含一个缩写,这个缩写应该全部大写,类名和结构名最好是名词组成的名字,例如PFHEstimation代替了EstimatePFH,下面是正确的命名代码例子:class ExampleClass;class PFHEstimation;7.函数函数/成员函数命名成员函数命名函数和类的成员函数的命名应该采用camelCased,也就是连写单词组成命名,除了首个单词首字母小写其他单词首字母大写,它们的参数命名单词之间
6、用下划线隔开,函数和类的成员函数命名最好采用动词,应该确保这些名字能清楚的表达函数和类成员函数的功能,例如,checkForErrors()而不是errorCheck(),dumpDataToFile()而不是dataFiledump(),正确的用法:intapplyExample(int example_arg);8.变量命名变量命名变量的命名应该单词之间用下划线隔开例如:int my_variable;(1)迭代子变量命名。迭代子变量应该反应出它们迭代的对象,例如:std:list pid_list;std:list:iterator pid_it;/指示迭代的对象为点的索引(2)常量命名
7、。常量的名字应该是全大写,例如:const static int MY_CONSTANT=1000;(3)成员变量命名。类的成员变量命名单词之间用下划线隔开并且以下划线结尾,例如:int example_int_;/对阅读PCL源码很有帮助,可明显区分成员变量与局部变量9.Return语句语句return语句需要在圆括号中设返回值,即规定return语句必须有返回值,大家知道,return如果没有返回值也会编译,例如:int main()return(0);3.1.2 PCL推荐的缩进与格式推荐的缩进与格式在PCL中每个代码块的标准缩进是两个空格,在任何情况下可以用制表符或者其他空格间隔的方式
8、进行格式化代码,PCL利用多样化的GNU类型的格式。1.1.命名空间缩进格式命名空间缩进格式在头文件里,命名空间的内容应该缩进两个空格,例如:namespace pcl class Foo ;在一个实现文件里,对每一个类成员函数或函数的命名必须添加命名空间限定,例如:void pcl:Foo:bar()2.类格式类格式一个模板类的模板参数必须与类定义在不同行,例如:templateclass Foo 3.函数函数/类成员函数格式类成员函数格式每一个函数的返回类型声明必须与函数声明放在不同的行,例如:voidbar();在函数实现的时候也一样,返回类型声明必须与函数声明放在不同的行,例如:voi
9、dbar()或者:voidFoo:bar()或者:templatevoidFoo:bar()4.花括号花括号花括号成对出现,与上一句代码另起一行定义,必须闭合才组成合理的程序块,例如:if(ab)else 下面的情况花括号可以省略,例如:if(ab)x=2*a;5.空格格式空格格式让我们再来强调一次,在PCL中的每一个代码块的标准缩进是两个空格,这里用单个空格来隔开函数/类成员函数名字与其参数列表,例如:intexampleMethod(int example_arg);如果在头文件内嵌套应用了命名空间名,需要将其缩进两个空格,例如:namespace foonamespace barvoid
10、method(int my_var);类和结构成员采用两个空格进行缩进,访问权限限定(public,private and protected)与类成员一级,而在其限定下的成员则需要缩进两个空格。例如:namepsace fooclass Barint i;public:voidbaz();6.自动格式化代码PCL提供下面一套规则文件通过多种不同的集成开发环境、编辑器等可以自动格式化编码。(1)Emacs,可以利用PCL C/C+配置文件(http:/dev.pointclouds.org/attachments/download/748/pcl-c-style.el),下载并存储此文件,再按
11、如下操作进行:3.1.3 设计结构设计结构1.类和应用程序接口类和应用程序接口对于PCL的大多数类而言,调用接口(所有public成员)是不含公开成员变量而只有采用两种成员方法(不排除有部分类公开成员):(1)固定的类型,它允许通过get/set修改或添加参数以及输入数据。(2)实际实现功能的函数,例如运算、滤波、分割、配准等处理功能。2.参数传递参数传递get/set类型的方式遵循下面的规则:(1)如果大量的数据需要传送(常见的例子是在PCL中输入数据)优先采用boost共享指针,而不是传送实际的数据。(2)成对的get与set类型成员函数总是需要采用一致的数据类型。(3)对于get类型成员
12、函数而言,如果只有一个参数需要被传递则会通过返回值,如果是两个或两个以上的参数需要传递,则通过引用方式进行传递。对于运算、滤波、分割等类型的参数遵循以下规则:(1)无论传递数据的大小,返回参数最好是非指针型参数。(2)总是通过引用方式来传递输出参数。3.2 如何编写新的PCL类把代码转换成符合PCL思路和句法的代码,对于第一次接触该基础架构的人会显得比较困难,会提出若干疑问。本小节介绍如何编写新的PCL类以及经常碰到的问题,也解释了在PCL目录树下与全球PCL用户共享你的代码有哪些优势,这里提倡共享,读者也可以把这种观念应用于其他类似的项目中,无论读者是自己直接写还是改写已有代码,本节的内容都
13、很有帮助,最重要的是可以帮助读者快速阅读了解PCL中的源码。3.2.1 优势:为什么加入优势:为什么加入PCL开源开发模式开源开发模式开发者不可能事先考虑他们编写的代码片段可能所有的用途,但也奠定了一定基础由于有限的资源和时间,发现解决方案以及应用程序中所有可能出现的漏洞是困难的,由于资源的限制,可能开始的时候进行处理也是不合适的。除了上面介绍到的,用户的贡献可能会有以下众多的作用:(1)别人以用户的代码为基础建立新的项目。(2)学习其他人新的用法。(3)无忧无虑的维护者身份。(4)在社区名声会提高。为了举例说明代码转换过程,我们选择下面的例子实现对给定点云中的强度数据应用双边滤波器,把结果保
14、存到磁盘。首先,在本书提供光盘的第3章例1文件夹中,打开名为mainBilateralFilter.cpp的代码文件,这里打开的源代码段包括以下步骤:(1)输入/输出代码块:从磁盘读数据,向磁盘写数据;(2)初始化代码块:用kd树建立一种搜索最近邻的方法;(3)实际算法代码块:对每个点进行双边滤波处理。我们的目的是把给出的源码程序转换成PCL的类,以便能够在其他地方重复使用。3.2.2 建立文件结构建立文件结构有两种不同的方法来建立文件结构:分别编写代码,作为独立的PCL类在PCL代码树之外;直接把文件建立的PCL代码目录树中,我们来阐述后者的操作方式,因为后者是最终结果有利于PCL库发展壮大
15、,也是因为它有一点复杂(也就是,它包含几个附加的步骤)。对于前者,可以同样操作,只是不需要在PCL代码目录树中建立对应的文件组织形式,也不需要了解CMake的使用。假设我们想要新的算法成为PCL滤波库的一部分,我们开始先在代码树目录filters下新建3个不同的文件:(1)include/pcl/filters/bilateral.h包含所有的定义和声明;(2)include/pcl/filters/impl/bilateral.hpp包含模板类的具体实现;(3)src/bilateral.cpp包含具体的不同点类型的模板类实例化。我们需要给新的类命名,把它称做BilateralFilter,
16、PCL滤波器接口规定每个算法必须有两个声明和实现可供使用:一个操作PointCloud,一个操作PointCloud2。本小节只讲前者操作PointCloud的实现。1.bilateral.h前面提到过,bilateral.h头文件包含所有和BilateralFilter类相关的声明,下面是最小的框架:#ifndef PCL_FILTERS_BILATERAL_H_#define PCL_FILTERS_BILATERAL_H_#include namespace pcltemplateclass BilateralFilter:public Filter/Filter类 ;#endif/PC
17、L_FILTERS_BILATERAL_H_2.bilateral.hpp新建bilateral.hpp和bilateral.cpp两个文件,首先是bilateral.hpp:#ifndef PCL_FILTERS_BILATERAL_IMPL_H_#define PCL_FILTERS_BILATERAL_IMPL_H_#include#endif/PCL_FILTERS_BILATERAL_H_这个应该是明确的,还没有给BilateralFilter声明任何方法,因此它没有任何具体实现。3.bilateral.cpp再编写bilateral.cpp文件:#include#include 因
18、为在PCL(1.X)中编写模板代码,这里模板参数是点的类型,我们要显式地在bilateral.cpp中说明所有点类型对应模板类的定义,因此用户在使用我们定义的BilateralFilter编译代码的时候不必花费额外的编译时间。为此,我们需要添加include模板类实例化头文件(bilateral.hpp)。4.CMakeLists.txt把所有新建的文件增加到PCL滤波器的CMakeLists.txt(在PCL源码根目录filters下)文件中,就可以开始编译链接过程,对于CMakeLists.txt的更改就完成了,剩下就是下面对类相关文件内容的填充了。#Find“set(srcs”,and
19、add a new entry there,e.g.,set(srcssrc/conditional_removal.cpp#.src/bilateral.cpp/为该类而添加的语句)#Find“set(incs”,and add a new entry there,e.g.,set(incsinclude pcl/$SUBSYS_NAME/conditional_removal.h#.include pcl/$SUBSYS_NAME/bilateral.h/为该类而添加的语句 )将编写的类添加进源码#Find“set(impl_incs”,and add a new entry there,
20、e.g.,set(impl_incs include/pcl/$SUBSYS_NAME/impl/conditional_removal.hpp#.include/pcl/$SUBSYS_NAME/impl/bilateral.hpp/为该类而添加的语句)3.2.3 填写类的内容填写类的内容如果用户正确无误地编辑了以上所有文件,在适当的地方使用新的滤波器类重编译PCL源码应该没有问题。这一小节中开始填充每一个文件中的代码,我们从bilateral.cpp文件开始,因为它的内容是最短的。1.bilateral.cpp如前所述,我们准备为BilateralFilter类实例化并预编译实例化若干模板
21、。尽管这可能增加PCL滤波库的编译时间,但是在用户编写的代码中使用该类的时候,能够使编译模板速度提高。为此最简单的做法像下面的在bilateral.cpp文件中手工添加模板实例化代码,每行对应一个需要手工预编译的模板实例:#include#include#includetemplate class PCL_EXPORTS pcl:BilateralFilter;template class PCL_EXPORTS pcl:BilateralFilter;template class PCL_EXPORTS pcl:BilateralFilter;/然而,随着PCL支持的点的类型增加,上面一一对
22、应的定义方式会使文件迅速增大,随后在维护PCL更新时变的更麻烦。因此,我们准备使用一个特殊的叫做PCL_INSTANTIATE的宏,并对以上代码做如下改变:#include#include#include#include PCL_INSTANTIATE(BilateralFilter,PCL_XYZ_POINT_TYPES);这个例子可以对所有在point_types.h文件中定义的XYZ点类型对应的BilateralFilter模板类进行实例化,继而在编译类的时候就省去了PCL用户使用时的编译时间。仔细看例子中的代码,我们注意到像cloud-pointspoint_id.intensity这
23、样的引用表明滤波器需要在点类型中有强度成员,因此,使用PCL_XYZ_POINT_TYPES就不起作用,因为不是所有声明了的类型都有强度数据。实际上,很容易注意到只有两个类型包含强度成员,也就是PointXYZI和PointXYZINormal,因此替换掉PCL_XYZ_POINT_TYPES,最后bilateral.cpp文件见本章源码文件1.0文件夹下的该文件。注意:现在还没有为BilateralFilter声明PCL_INSTANTIATE模板类,实际上也没有实现抽象类pcl:Filter中的纯虚函数,因此如果试图编译代码将产生如下错误:filters/src/bilateral.cpp
24、:6:32:error:expected constructor,destructor,or type conversion before C token2.bilateral.h开始填充BilateralFilter类的内容,首先声明构造函数和它的成员变量。因为该双边滤波器算法有两个参数,存储起来作为类的成员,并按照PCL 1.X的API范例来为它们实现各种设值函数(setters)和取值函数(getters),代码如下:namespace pcltemplateclass BilateralFilter:public Filterpublic:BilateralFilter():sigma
25、_s_(0),sigma_r_(std:numeric_limits:max()voidsetSigmaS(const double sigma_s)sigma_s_=sigma_s;doublegetSigmaS()return(sigma_s_);voidsetSigmaR(const double sigma_r)sigma_r_=sigma_r;doublegetSigmaR()return(sigma_r_);private:double sigma_s_;double sigma_r_;#endif/PCL_FILTERS_BILATERAL_H_都现在为止都是最普通的C+代码,除
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 点云库PCL学习教程 点云库PCL学习教程第3章 PCL基础 点云库 PCL 学习 教程 基础

限制150内