《点云库PCL学习教程》PCL基础PPT课件_第1页
《点云库PCL学习教程》PCL基础PPT课件_第2页
《点云库PCL学习教程》PCL基础PPT课件_第3页
《点云库PCL学习教程》PCL基础PPT课件_第4页
《点云库PCL学习教程》PCL基础PPT课件_第5页
已阅读5页,还剩99页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第3章PCL基础 1 本章首先简述了PCLC 编程规范 为以后章节的阅读和读者编写出PCL风格的代码做一定铺垫 为了让用户基于PCL开发出自己的扩展 紧接着通过实例详细介绍了在PCL框架下如何建立用户自定义类 最后介绍了PCL中点的已有类型以及如何自定义点类型以满足扩展需求 掌握第3章的内容之后 读者可轻松阅读PCL源码和后续章节中的例子程序 也为读者后续自行开发奠定了基础 2 本章各小节目录 3 1PCLC 编程规范3 2如何编写新的PCL类3 3PCL已有点类型介绍和增加自定义的点类型3 4PCL中异常处理机制 3 3 1PCLC 编程规范 架构师为了确保在PCL中所有代码风格的一致性 使得其他开发者及用户容易理解源码 PCL开发者制定并遵循着一套严格的编写规范 PCL的开发者都默认此规范 除非有充足的理由才可以不遵循这些规范 当然这些规范也并不是一成不变的 但提出和更改规则的人需要考虑兼容性 那就是让新加的规则与现有的所有代码相适应 4 3 1 1PCL推荐的命名规范1 文件命名 1 所有的文件名单词之间应该用下划线隔开 例如unordered map hpp 2 头文件的扩展名为 h 3 模板类实现文件的扩展名是 hpp 4 源文件的扩展名是 cpp 2 目录命名所有的目录及其子目录命名应该符合 如果由多个单词组成 其之间用下划线隔开 PCL中各个目录遵循以下规则 1 头文件都应放在源码目录树中的include 下 2 模板类实现文件都应放在目录树中的include 5 impl 下 3 源文件都应放在目录树中的src 下 3 Include语句当文件在同一目录下时Include指示语句用双引号 在其他情况下则用尖括号 例如 include include include file name cpp 在同一目录下4 宏定义命名宏定义中字母都采用大写格式 为头文件所定义的宏最后面还需要加上下划线 并且名称从include下目录开始 例如pcl filters bilateral h对应PCL FILTERS BILATERL H ifndef和 define定义放在 6 BSD协议后面代码前面 endif定义一直在文件结尾 并且加上一句注释掉的宏对应头文件的宏定义 例如 theBSDlicense ifndefPCL MODULE NAME IMPL FILE NAME HPP 为避免重复包含头文件而定义的宏 definePCL MODULE NAME IMPL FILE NAME HPP thecode endif PCL MODULE NAME IMPL FILE NAME HPP 5 命名空间命名命名空间多于一个单词的 单词之间应该用下划线连接 例如 namespacepcl io 7 6 类 结构命名类名 和其他自定义类型的名称 应该是CamelCased 驼峰命名 命名规范 也就是连写单词组成命名 每个单词首字母大写 但是有例外 如果类名包含一个缩写 这个缩写应该全部大写 类名和结构名最好是名词组成的名字 例如PFHEstimation代替了EstimatePFH 下面是正确的命名代码例子 classExampleClass classPFHEstimation 7 函数 成员函数命名函数和类的成员函数的命名应该采用camelCased 也就是连写单词组成命名 除了首个单词首字母小写其他单词首字母大写 它们的参数命名单词之间用下划线隔开 函数和类的成员函数命名最好采用动词 应该 8 确保这些名字能清楚的表达函数和类成员函数的功能 例如 checkForErrors 而不是errorCheck dumpDataToFile 而不是dataFiledump 正确的用法 intapplyExample intexample arg 8 变量命名变量的命名应该单词之间用下划线隔开例如 intmy variable 1 迭代子变量命名 迭代子变量应该反应出它们迭代的对象 例如 std listpid list std list iteratorpid it 指示迭代的对象为点的索引 2 常量命名 常量的名字应该是全大写 例如 conststaticintMY CONSTANT 1000 9 3 成员变量命名 类的成员变量命名单词之间用下划线隔开并且以下划线结尾 例如 intexample int 对阅读PCL源码很有帮助 可明显区分成员变量与局部变量9 Return语句return语句需要在圆括号中设返回值 即规定return语句必须有返回值 大家知道 return如果没有返回值也会编译 例如 intmain return 0 10 3 1 2PCL推荐的缩进与格式在PCL中每个代码块的标准缩进是两个空格 在任何情况下可以用制表符或者其他空格间隔的方式进行格式化代码 PCL利用多样化的GNU类型的格式 命名空间缩进格式在头文件里 命名空间的内容应该缩进两个空格 例如 namespacepcl classFoo 11 在一个实现文件里 对每一个类成员函数或函数的命名必须添加命名空间限定 例如 voidpcl Foo bar 2 类格式一个模板类的模板参数必须与类定义在不同行 例如 templateclassFoo 3 函数 类成员函数格式 12 每一个函数的返回类型声明必须与函数声明放在不同的行 例如 voidbar 在函数实现的时候也一样 返回类型声明必须与函数声明放在不同的行 例如 voidbar 或者 voidFoo bar 13 或者 templatevoidFoo bar 4 花括号花括号成对出现 与上一句代码另起一行定义 必须闭合才组成合理的程序块 例如 if a b else 14 下面的情况花括号可以省略 例如 if a b x 2 a 5 空格格式让我们再来强调一次 在PCL中的每一个代码块的标准缩进是两个空格 这里用单个空格来隔开函数 类成员函数名字与其参数列表 例如 intexampleMethod intexample arg 如果在头文件内嵌套应用了命名空间名 需要将其缩进两个空格 例如 namespacefoo namespacebar 15 voidmethod intmy var 类和结构成员采用两个空格进行缩进 访问权限限定 public privateandprotected 与类成员一级 而在其限定下的成员则需要缩进两个空格 例如 namepsacefoo classBar inti public void 16 baz 6 自动格式化代码PCL提供下面一套规则文件通过多种不同的集成开发环境 编辑器等可以自动格式化编码 1 Emacs 可以利用PCLC C 配置文件 http dev pointclouds org attachments download 748 pcl c style el 下载并存储此文件 再按如下操作进行 17 3 1 3设计结构1 类和应用程序接口对于PCL的大多数类而言 调用接口 所有public成员 是不含公开成员变量而只有采用两种成员方法 不排除有部分类公开成员 1 固定的类型 它允许通过get set修改或添加参数以及输入数据 2 实际实现功能的函数 例如运算 滤波 分割 配准等处理功能 2 参数传递get set类型的方式遵循下面的规则 1 如果大量的数据需要传送 常见的例子是在PCL中 18 输入数据 优先采用boost共享指针 而不是传送实际的数据 2 成对的get与set类型成员函数总是需要采用一致的数据类型 3 对于get类型成员函数而言 如果只有一个参数需要被传递则会通过返回值 如果是两个或两个以上的参数需要传递 则通过引用方式进行传递 对于运算 滤波 分割等类型的参数遵循以下规则 1 无论传递数据的大小 返回参数最好是非指针型参数 2 总是通过引用方式来传递输出参数 19 3 2如何编写新的PCL类 把代码转换成符合PCL思路和句法的代码 对于第一次接触该基础架构的人会显得比较困难 会提出若干疑问 本小节介绍如何编写新的PCL类以及经常碰到的问题 也解释了在PCL目录树下与全球PCL用户共享你的代码有哪些优势 这里提倡共享 读者也可以把这种观念应用于其他类似的项目中 无论读者是自己直接写还是改写已有代码 本节的内容都很有帮助 最重要的是可以帮助读者快速阅读了解PCL中的源码 20 3 2 1优势 为什么加入PCL开源开发模式开发者不可能事先考虑他们编写的代码片段可能所有的用途 但也奠定了一定基础 由于有限的资源和时间 发现解决方案以及应用程序中所有可能出现的漏洞是困难的 由于资源的限制 可能开始的时候进行处理也是不合适的 除了上面介绍到的 用户的贡献可能会有以下众多的作用 1 别人以用户的代码为基础建立新的项目 2 学习其他人新的用法 3 无忧无虑的维护者身份 4 在社区名声会提高 21 为了举例说明代码转换过程 我们选择下面的例子实现对给定点云中的强度数据应用双边滤波器 把结果保存到磁盘 首先 在本书提供光盘的第3章例1文件夹中 打开名为mainBilateralFilter cpp的代码文件 这里打开的源代码段包括以下步骤 1 输入 输出代码块 从磁盘读数据 向磁盘写数据 2 初始化代码块 用kd树建立一种搜索最近邻的方法 3 实际算法代码块 对每个点进行双边滤波处理 我们的目的是把给出的源码程序转换成PCL的类 以便能够在其他地方重复使用 22 3 2 2建立文件结构有两种不同的方法来建立文件结构 分别编写代码 作为独立的PCL类在PCL代码树之外 直接把文件建立的PCL代码目录树中 我们来阐述后者的操作方式 因为后者是最终结果有利于PCL库发展壮大 也是因为它有一点复杂 也就是 它包含几个附加的步骤 对于前者 可以同样操作 只是不需要在PCL代码目录树中建立对应的文件组织形式 也不需要了解CMake的使用 假设我们想要新的算法成为PCL滤波库的一部分 我们开始先在代码树目录filters下新建3个不同的文件 1 include pcl filters bilateral h 包含所有的定义和声明 23 2 include pcl filters impl bilateral hpp 包含模板类的具体实现 3 src bilateral cpp 包含具体的不同点类型的模板类实例化 我们需要给新的类命名 把它称做BilateralFilter PCL滤波器接口规定每个算法必须有两个声明和实现可供使用 一个操作PointCloud 一个操作PointCloud2 本小节只讲前者操作PointCloud的实现 1 bilateral h前面提到过 bilateral h头文件包含所有和BilateralFilter类相关的声明 下面是最小的框架 ifndefPCL FILTERS BILATERAL H definePCL FILTERS BILATERAL H 24 includenamespacepcl templateclassBilateralFilter publicFilter Filter类 endif PCL FILTERS BILATERAL H 2 bilateral hpp新建bilateral hpp和bilateral cpp两个文件 首先是bilateral hpp ifndefPCL FILTERS BILATERAL IMPL H definePCL FILTERS BILATERAL IMPL H include endif PCL FILTERS BILATERAL H 25 这个应该是明确的 还没有给BilateralFilter声明任何方法 因此它没有任何具体实现 3 bilateral cpp再编写bilateral cpp文件 include include因为在PCL 1 X 中编写模板代码 这里模板参数是点的类型 我们要显式地在bilateral cpp中说明所有点类型对应模板类的定义 因此用户在使用我们定义的BilateralFilter编译代码的时候不必花费额外的编译时间 为此 我们需要添加include模板类实例化头文件 bilateral hpp 4 CMakeLists txt把所有新建的文件增加到PCL滤波器的CMakeLists txt 在 26 PCL源码根目录 filters 下 文件中 就可以开始编译链接过程 对于CMakeLists txt的更改就完成了 剩下就是下面对类相关文件内容的填充了 Find set srcs andaddanewentrythere e g set srcssrc conditional removal cpp src bilateral cpp 为该类而添加的语句 Find set incs andaddanewentrythere e g set incsincludepcl SUBSYS NAME conditional removal h includepcl SUBSYS NAME bilateral h 为该类而添加的语句 将编写的类添加进源码 27 Find set impl incs andaddanewentrythere e g set impl incsinclude pcl SUBSYS NAME impl conditional removal hpp include pcl SUBSYS NAME impl bilateral hpp 为该类而添加的语句 28 3 2 3填写类的内容如果用户正确无误地编辑了以上所有文件 在适当的地方使用新的滤波器类重编译PCL源码应该没有问题 这一小节中开始填充每一个文件中的代码 我们从bilateral cpp文件开始 因为它的内容是最短的 1 bilateral cpp如前所述 我们准备为BilateralFilter类实例化并预编译实例化若干模板 尽管这可能增加PCL滤波库的编译时间 但是在用户编写的代码中使用该类的时候 能够使编译模板速度提高 为此最简单的做法像下面的在bilateral cpp文件中手工添加模板实例化代码 每行对应一个需要手工预编译的模板实例 include include include 29 templateclassPCL EXPORTSpcl BilateralFilter templateclassPCL EXPORTSpcl BilateralFilter templateclassPCL EXPORTSpcl BilateralFilter 然而 随着PCL支持的点的类型增加 上面一一对应的定义方式会使文件迅速增大 随后在维护PCL更新时变的更麻烦 因此 我们准备使用一个特殊的叫做PCL INSTANTIATE的宏 并对以上代码做如下改变 include include include includePCL INSTANTIATE BilateralFilter PCL XYZ POINT TYPES 这个例子可以对所有在point types h文件中定义的XYZ点类型对应的BilateralFilter模板类进行实例化 继而在 30 编译类的时候就省去了PCL用户使用时的编译时间 仔细看例子中的代码 我们注意到像cloud points point id intensity这样的引用表明滤波器需要在点类型中有强度成员 因此 使用PCL XYZ POINT TYPES就不起作用 因为不是所有声明了的类型都有强度数据 实际上 很容易注意到只有两个类型包含强度成员 也就是PointXYZI和PointXYZINormal 因此替换掉PCL XYZ POINT TYPES 最后bilateral cpp文件见本章源码文件1 0文件夹下的该文件 注意 现在还没有为BilateralFilter声明PCL INSTANTIATE模板类 实际上也没有实现抽象类pcl Filter中的纯虚函数 因此如果试图编译代码将产生如下错误 filters src bilateral cpp 6 32 error expectedconstructor destructor ortypeconversionbefore C token 31 2 bilateral h开始填充BilateralFilter类的内容 首先声明构造函数和它的成员变量 因为该双边滤波器算法有两个参数 存储起来作为类的成员 并按照PCL1 X的API范例来为它们实现各种设值函数 setters 和取值函数 getters 代码如下 namespacepcl templateclassBilateralFilter publicFilter public BilateralFilter sigma s 0 sigma r std numeric limits max 32 voidsetSigmaS constdoublesigma s sigma s sigma s doublegetSigmaS return sigma s voidsetSigmaR constdoublesigma r sigma r sigma r doublegetSigmaR return sigma r 33 private doublesigma s doublesigma r endif PCL FILTERS BILATERAL H 都现在为止都是最普通的C 代码 除了构造函数BilateralFilter 这里给了两个参数默认值 因为我们的类是从pcl Filter继承的 而pcl Filter是从pcl PCLBase继承的 可以用setInputCloud 方法给算法传递输入数据 作为input 存储 因此下面增加了一个using声明 templateclassBilateralFilter publicFilter 34 usingFilter input public BilateralFilter sigma s 0 使用using声明确保我们的类能够不需输入完整引用方式就可以访问成员其父类的成员变量input 下面我们定义applyFilter函数 由于其是纯虚函数 所有从pcl Filter继承的类都必须实现该方法成员 因此有如下声明 usingFilter input typedeftypenameFilter PointCloudPointCloud public BilateralFilter sigma s 0 sigma r std numeric limits max 35 voidapplyFilter PointCloud 36 此外 我们注意到例子中构造了一个Kd树对象用于获取给定点的近邻 因此我们增加下面的内容 include usingFilter input typedeftypenameFilter PointCloudPointCloud typedeftypenamepcl KdTree PtrKdTreePtr public voidsetSearchMethod constKdTreePtr private 37 KdTreePtrtree 最后 增加核心计算函数G floatx floatsigma 为内联 inline 函数 以便能够加速滤波的计算 因为该方法仅仅在该算法的环境里有用 我们把它设置为私有 完整的头文件见本章源码文件1 0文件夹下bilateral h 3 bilateral hpp最后需要编写的是 hpp文件 完成对声明函数的具体实现 这里需要实现两个方法 就是applyFilter和computePointWeight templatedoublepcl BilateralFilter computePointWeight constintpid conststd vector indices conststd vector distances 38 doubleBF 0 W 0 Foreachneighborfor size tn id 0 n idpoints pid intensity input points id intensity doubleweight kernel dist sigma s kernel intensity dist sigma r BF weight input points id intensity W weight return BF W 39 templatevoidpcl BilateralFilter applyFilter PointCloud 40 computePointWeight方法应该很简单因为它几乎和实例计算代码一样 通过传递一个要计算强度重量的point索引 索引所指示的点是由欧氏空间的邻域组成 在applyFilter中 我们首先利用输入数据构建Kd树 把所有输入数据复制到输出 然后开始计算新的点的强度 赋值于输出点云数据output 是时候为该类声明PCL INSTANTIATE来实例化模板类了 ifndefPCL FILTERS BILATERAL IMPL H definePCL FILTERS BILATERAL IMPL H include definePCL INSTANTIATE BilateralFilter T templateclassPCL EXPORTSpcl BilateralFilter endif PCL FILTERS BILATERAL H 需要做的另一件事就是检查错误 41 1 是否给定了sigma s 和sigma r 两个参数 2 是否设置了搜索方法的对象 例如 tree 对于前者 检查sigma s 的值 它默认被设置成0 它对算法的行为有十分重要的意义 它实际上是定义了算法所支持滤波的范围大小 因此 如果代码执行的时候其值仍然是0 我们就用宏PCL ERROR打印一个错误并返回 就搜索方法来说 我们可以做同样的操作或者为用户提供默认的选项 最好的默认选项如下 1 如果点云是有序的 通过pcl OrganizedDataIndex使用有序搜索方法 2 如果点云是无序的 通过pcl KdTreeFLANN使用通用的Kd树 42 include include templatevoidpcl BilateralFilter applyFilter PointCloud 43 elsetree reset newpcl KdTreeFLANN false tree setInputCloud input 这样该模板类完整的实现头文件见本章源码文件1 0文件夹下的bilateral hpp 4 利用PCL其他机制点索引机制向PCL算法传递点云数据的标准方法是通过访问setInputCloud 另外 PCL也可通过setIndices 传递用户感兴趣区域或点云集 而不是整个点云 所有的类都从PCLBase继承了以下行为 如果用户没有给出一点的索引 类就会建立一个虚的索引并且在算法的整个运行期间使用 这意味着我们能够很容易地改变上面的实现代码来对元组 44 进行操作 这样的好处就是如果用户确实传递了点的索引 将会使用传递索引对应的点云 如果没有传递将使用整个点云 新的bilateral hpp类就成为下面这样子 include include templatevoidpcl BilateralFilter applyFilter PointCloud 45 if tree if input isOrganized tree reset newpcl OrganizedDataIndex elsetree reset newpcl KdTreeFLANN false tree setInputCloud input 模板类实现头文件就编写如本章源码文件2 0文件夹下bilateral hpp 为了使indices 不用输入整个约束就能运行 需要给bilateral h文件增加一行using语句来指示indices 的位置 46 templateclassBilateralFilter publicFilter usingFilter input usingFilter indices public BilateralFilter sigma s 0 47 3 2 4许可建议每一个文件包含一个描述代码作者的许可 这对于用户了解使用该代码会受到何种约束是十分有用的 PCL是100 的BSD许可的 我们在文件中以C 注释的形式嵌入该许可证 详细见本章源码文件夹下License txt 如果需要声明其他的版权 添加其他类似的内容就行了 或者原始著作权被改变 Copyright c XXX respectiveauthors 48 3 2 5合理命名到目前为止 我们在例程中使用诸如setSigmaS或setSigmaR等简单的词汇来命名set和get功能的函数 在实际中应该使用更好的命名方法 以便能够真正表示对应参数的功能 在代码的最终版本中将重新把setters和getters命名成set getHalfSize和set getStdDev以及类似的名字 49 3 2 6代码注释PCL试图在用户和API文档方面保持高标准 支持Doxygen的文档生成的注释已经在上面的例子中删减掉 实际中 bilateral h头文件类部分如下 briefcomputetheintensityaverageforasinglepoint param in pid doublecomputePointWeight constintpid conststd vector briefSetthehalfsizeoftheGaussianbilateralfilterwindow 50 inlinevoidsetHalfSize constdoublesigma s sigma s sigma s endif PCL FILTERS BILATERAL H 很明显比上面的代码中的注释多了不少 并且都符合一定的格式 这样就是标准的PCL编码风格了 即方便代码的维护 又方便用户的使用和学习 bilateral hpp文件部分如下 Copytheinputdataintotheoutputoutput input Foralltheindicesgiven equaltotheentirecloudifnonegiven 51 for size ti 0 isize i Performaradiussearchtofindthenearestneighborstree radiusSearch indices i sigma s 2 k indices k distances endif PCL FILTERS BILATERAL H 完成的bilateral h和bilateral hpp文件见本章源码文件夹下3 0文件夹 52 3 2 7测试新建的类测试新的类很容易 我们用上面提到的第一个代码段作为例子 转而使用pcl BilateralFilter类利用光盘提供的CMakeLists txt和testfilter cpp文件 在cmake中建立工程文件 并生成相应的可执行文件 生成执行文件后就可以运行测试前面定义的类 需要重新编译Filter模块 将前面修改后的类包含进CMakeLists文件后重新编译 不然会提示errorC2664 pcl BilateralFilter setSearchMethod 不能将参数1从 boost shared ptr 转换 重新编译 单独编译某一个模块即可 但是可能依然需要依赖库 之后 将编译生成的库文件替换原来的lib库文件 Why 53 3 3PCL已有点类型介绍和增加自定义的点类型 本小节不仅解释如何增加用户自己的PointT点类型 也介绍了PCL中的模板point类型以及它们的用户和定义 PCL从开始就伴随着各种预定义的point类型 从用于XYZ数据到更复杂的n维直方图表示法 例如PFH 点特征直方图 这些类型应该足够支持在PCL中应用的算法及方法 然而 也有情况下用户希望定义新的类型 注意 由于PCL的快速更新 本节内容仅仅对PCL0 x和1 x版本兼容 撰写本文档的时候预期在PCL2 X中会有新的改变 但大的架构不变 只是添加些 54 新定义的描述子等点类型之类的 55 3 3 1为什么用PointT类型PCL的PointT可以追溯到它在ROS中作为开源库被开发的时候 大家一致认为 点云是复杂的n维结构 它需要能表示不同类型的信息 然而用户应该知道并理解需要传送什么样的信息 为了使代码更易于调试 考虑优化等 下面给出一个例子 是对XYZ数据的简单操作 对带SSE功能的处理器最高效的方法是存储三维坐标为浮点型 紧跟着一个浮点型数据作为填补位数以满足存储对齐要求 structPointXYZ floatx floaty floatz floatpadding 56 然而 例如当用户在嵌入式平台上寻找编译PCL的时候 增加额外的填补就是浪费存储空间了 因此 可以用一个简单的不带最后浮点数的PointXYZ结构来替代 此外 如果应用程序需要一个包含XYZ三维数据 RGB信息 颜色 和每个点的估计法线的PointXYZRGBNormal类型 定义包含以上所有内容的结构是很简单的 由于PCL中所有算法都是模板化的 除了更改的自定义结构之外不需要做其他的更改 增加了代码的重用性和可读性 57 3 3 2PCL中有哪些可用的PointT类型为了涵盖能想到的所有可能的情况 PCL中定义了大量的point类型 下面是一小段 在point types hpp中有完整目录 这个列表很重要 因为在定义用户自己的类型之前需要了解已有的类型 如果需要的类型已经存在于PCL 那么就不需要重复定义了 PointXYZ 成员变量 floatx y z PointXYZ是使用最常见的一个点数据类型 因为它只包含三维XYZ坐标信息 这三个浮点数附加一个浮点数来满足存储对齐 用户可利用points i data 0 或者points i x访问点的x坐标值 union 58 floatdata 4 struct floatx floaty floatz 2 PointXYZI 成员变量 floatx y z intensity PointXYZI是一个简单的XYZ坐标加上intensity的point类型 理想情况下 这4个变量将新建单独一个结构体 并且满足存储对齐 然而 由于point的大部分操作会把data 4 元素设置成0或1 用于变换 不能让intensity与XYZ在同一个结构体中 如果这样的话其内容将会被覆盖 例如 两个点的点积会把他们的 59 第4个元素设置成0 否则该点积没有意义 等等 因此 对于兼容存储对齐用3个额外的浮点数来填充intensity 这样在存储方面效率较低 但是符合存储对齐要求 运行效率较高 union floatdata 4 struct floatx floaty floatz union 60 struct floatintensity floatdata c 4 3 PointXYZRGBA 成员变量 floatx y z uint32 trgba 除了RGBA信息被包含在一个整型变量中 其他的和PointXYZI类似 union floatdata 4 struct floatx floaty floatz 61 union struct uint32 trgba floatdata c 4 4 PointXYZRGB floatx y z rgb 除了RGB信息被包含在一个浮点型变量中 其他的和PointXYZRGBA类似 RGB数据被压缩到一个浮点数里的原因在于早期PCL是作为ROS项目的一部分来开发的 那里RGB数据是用浮点数来传送的 PCL设计者 62 希望所有遗留代码会重新更改 在PCL2 x中很可能这样做 可能取消此数据类型 union floatdata 4 struct floatx floaty floatz union struct 63 floatrgb floatdata c 4 5 PointXY floatx y 简单的二维x ypoint结构代码如下 struct floatx floaty 6 InterestPoint floatx y z strength 除了strength表示关键点的强度的测量值 其他的和PointXYZI类似 64 union floatdata 4 struct floatx floaty floatz union struct floatstrength floatdata c 4 65 7 Normal floatnormal 3 curvature 另一个最常用的数据类型 Normal结构体表示给定点所在样本曲面上的法线方向 以及对应曲率的测量值 通过曲面块特征值之间关系获得 查看NormalEstimation类API以便获得更多信息 后续章节有介绍 由于在PCL中对曲面法线的操作很普遍 还是用第4个元素来占位 这样就兼容SSE和高效计算 例如 用户访问法向量的第一个坐标 可以通过points i data n 0 或者points i normal 0 或者points i normal x 在此再一次强调 曲率不能被存储在用同一个结构体中 因为它会被普通的数据操作覆盖掉 union floatdata n 4 66 floatnormal 3 struct floatnormal x floatnormal y floatnormal z union struct floatcurvature floatdata c 4 67 8 PointNormal floatx y z floatnormal 3 curvature PointNormal是存储XYZ数据的point结构体 并且包括采样点对应法线和曲率 union floatdata 4 struct floatx floaty floatz union 68 floatdata n 4 floatnormal 3 struct floatnormal x floatnormal y floatnormal z union struct floatcurvature floatdata c 4 69 9 PointXYZRGBNormal floatx y z rgb normal 3 curvature PointXYZRGBNormal存储XYZ数据和RGB颜色的point结构体 并且包括曲面法线和曲率 union floatdata 4 struct floatx floaty floatz union 70 floatdata n 4 floatnormal 3 struct floatnormal x floatnormal y floatnormal z union struct 71 floatrgb floatcurvature floatdata c 4 10 PointXYZINormal floatx y z intensity normal 3 curvature PointXYZINormal存储XYZ数据和强度值的point结构体 并且包括曲面法线和曲率 union floatdata 4 struct floatx floaty 72 floatz union floatdata n 4 floatnormal 3 struct floatnormal x floatnormal y floatnormal z union 73 struct floatintensity floatcurvature floatdata c 4 11 PointWithRange floatx y z unionwithfloatpoint 4 range PointWithRange除了range包含从所获得的视点到采样点的距离测量值之外 其他与PointXYZI类似 union floatdata 4 struct floatx floaty floatz 74 union struct floatrange floatdata c 4 12 PointWithViewpoint floatx y z vp x vp y vp z PointWithViewpoint除了vp x vp y和vp z以三维点表示所获得的视点之外 其他与PointXYZI一样 union floatdata 4 struct 75 floatx floaty floatz union struct floatvp x floatvp y floatvp z floatdata c 4 76 13 MomentInvariants floatj1 j2 j3 MomentInvariants是一个包含采样曲面上面片的3个不变矩的point类型 描述面片上质量的分布情况 查看MomentInvariantsEstimation以获得更多信息 struct floatj1 j2 j3 14 PrincipalRadiiRSD floatr min r max PrincipalRadiiRSD是一个包含曲面块上两个RSD半径的point类型 查看RSDEstimation以获得更多信息 struct floatr min r max 77 15 Boundary uint8 tboundary point Boundary存储一个点是否位于曲面边界上的简单point类型 查看BoundaryEstimation以获得更多信息 struct uint8 tboundary point 16 PrincipalCurvatures floatprincipal curvature 3 pc1 pc2 PrincipalCurvatures包含给定点主曲率的简单point类型 查看PrincipalCurvaturesEstimation以获得更多信息 struct union floatprincipal curvature 3 78 struct floatprincipal curvature x floatprincipal curvature y floatprincipal curvature z floatpc1 floatpc2 17 PFHSignaturel25 floatpfh 125 PFHSignaturel25包含给定点的PFH 点特征直方图 的简单point类型 查看PFHEstimation以获得更多信息 struct floathistogram 125 79 18 FPFHSignature33 floatfpfh 33 FPFHSignature33包含给定点的FPFH 快速点特征直方图 的简单point类型 查看FPFHEstimation以获得更多信息 struct floathistogram 33 19 VFHSignature308 floatvfh 308 VFHSignature308包含给定点VFH 视点特征直方图 的简单point类型 查看VFHEstimation以获得更多信息 struct floathistogram 308 80 20 Narf36 floatx y z roll pitch yaw floatdescriptor 36 Narf36包含给定点NARF 归一化对齐半径特征 的简单point类型 查看NARFEstimation以获得更多信息 struct floatx y z roll pitch yaw floatdescriptor 36 21 BorderDescription intx y BorderTraitstraits BorderDescription包含给定点边界类型的简单point类型 看BorderEstimation以获得更多信息 struct 81 intx y BorderTraitstraits 22 IntensityGradient floatgradient 3 IntensityGradient包含给定点强度的梯度point类型 查看IntensityGradientEstimation以获得更多信息 struct union floatgradient 3 struct floatgradient x floatgradient y floatgradient z 82 23 Histogram floathistogram N Histogram用来存储一般用途的n维直方图 templatestructHistogram floathistogram N 24 PointWithScale floatx y z scale PointWithScale除了scale表示某点用于几何操作的尺度 例如 计算最近邻所用的球体半径 窗口尺寸等 其他的和PointXYZI一样 83 struct union floatdata 4 struct floatx floaty floatz floatscale 25 PointSurfel floatx y z normal 3 rgba radius confidence curvature 84 PointSurfel存储XYZ坐标 曲面法线 RGB信息 半径 可信度和曲面曲率的复杂point类型 union floatdata 4 struct floatx floaty floatz union floatdata n 4 floatnormal 3 85 struct floatnormal x floatnormal y floatnormal z union struct uint32 trgba floatradius floatconfidence floatcurvature floatdata c 4 86 3 3 3如何在模板类中使用这些point类型由于PCL模块较多 并且是一个模板库 在一个源文件里包含很多PCL算法会减慢编译过程 在撰写本文档的时候 大多数C 编译器仍然没有很好的优化来处理大量模板文件 尤其是涉及优化 O2或者 O3 问题的时候 为了使包含和链接到PCL库的用户代码编译速度提高 我们使用显示的模板实例化 最终编译链接的库包括了所有可能的模板实例 在这些组合中使PCL中已经定义的point类型所有的模板类都能够直接调用 不需要重新编译 这意味着一旦PCL编译成库 任何用户代码都不需要编译模板化代码 这样就加速了用户编译过程 这个是通过在头文件中首先声明了我们的类和方法 再在模板类实现头文件中进行实现 配置在源文件中进行显示的实例化 最后在编译链接时分别实例化 举一个例子 87 foo h ifndefPCL FOO definePCL FOO templateclassFoo p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论