首页 文章详情

技术分享 | SLAM工程中使用配置文件加载程序参数的实现方法

新机器视觉 | 176 2022-04-11 03:03 0 0 0
UniSMS (合一短信)

点击下方卡片,关注“新机器视觉”公众号

重磅干货,第一时间送达

我们在SLAM工程中有许多用于调试结果的参数,但每次修改后的编译都会占用很多时间和资源,当工程较大的时候,工作效率也会明显下降,因此,从配置文件中读取程序参数便是一个很方便的功能。而配置文件有许多种,并且在不同的系统上配置成了不同的库或源。在工程后期成型时,把这样的一系列内容做成tools,用的方法也会比较相似。个人认为YAML比XML在中小规模的开发中更优,在多人合作的大项目中,使用XML是比较好的选择。

本篇记录的是YAML文件的使用(Yet Another Markup Language,直译为另一种标记语言),还有XML(Extensible Markup Language,可扩展标记语言)。XML是一种具备自己结构的语言文件,其在信息的可表达度上更为丰富,应用方面也更为广泛,适配许多种语言交互(例如C++,JS,PHP等),信息传递以及系统调用,但同样的在表现上相对会比较冗长;而YAML虽然也是一种语言型文件,但其更像是一种数据形式,其表达简单的数据比较好,且其良好的可读性与易于实现的特性,在工程中效率非常高。


XML文件的基本写法与调用方法

C++中读取XML文件主要是针对不同节点来配置不同的参数,功能针对性比较强,其对应的数据在代码中可以直接写成一成不变的量,俗称“写死”,然后通过修改XML时来改变其具体的数值。常用的包括配置tinyXML库。

1、XML文件的基本写法:

<!-- 应用的时候主要是:节点名称、节点属性、节点内容及参数 --><!-- 如下标准形式 --><?xml version = "1.0"?><event1>    <variable1>variable_value1</variable1>    <variable2>variable_value2</variable2></event1><event2>    <variable3>variable_value3</variable3>    <variable4>variable_value4</variable4></event2>
<!-- 举个例子,node定义了一个2.5*2.5*2.5的box --><?xml version="1.0" encoding="UTF-8"?><box> <node id="0" type="0"> <width>2.5</width> <height>2.5</height> <depth>2.5</depth> </node> <!-- 有N+1个这样的node节点 --></box><!-- 在需要修改的时候就可以直接将2.5的值修改掉 -->


2、XML文件的调用方法

调用的时候,按照上述举例的XML部分进行读入解析,有如下C++代码参考:

#include "tinystr.h"  #include "tinyxml.h"
int main(){ double w,h,d; BOX* box;//自行定义的box结构指针 //box初始化,假定有n个box,得到的数组长度为BOX_SET iXmlDocument doc(FILENAME); // 读入XML文件 if(!doc.LoadFile()) return -1; // 如果无法读取文件,则返回 TiXmlHandle hDoc(&doc); // hDoc是&doc指向的对象 TiXmlElement* pElem; // 指向元素的指针 pElem = hDoc.FirstChildElement().Element(); //指向根节点 TiXmlHandle hRoot(pElem); // hRoot是根节点
TiXmlElement* nodeElem = hRoot.FirstChild("box").FirstChild("node").Element(); //当前指向了node节点 count = 0;//node的角标,记录当前到哪一个 for(nodeElem; nodeElem; nodeElem = nodeElem->NextSiblingElement()) // 挨个读取node节点的信息 { box= BOX_SET[count]; // box节点,用count来记录 TiXmlHandle node(nodeElem); // nodeElem所指向的节点 TiXmlElement* width = node.FirstChild("width").Element(); // width节点 TiXmlElement* height = node.FirstChild("height").Element(); // height节点 TiXmlElement* depth = node.FirstChild("depth").Element(); // depth节点 //可以根据node的属性值,例如id进行移位读取 //例如nodeElem->QueryIntAttribute("id", &temp); box->setID(temp);temp代表的就是其属性 w = atof(width ->GetText()); // char转double,记录数据,后面根据自己需要可直接调用 h = atof(height ->GetText()); d = atof(depth->GetText()); count ++; } return 1;}


YAML文件的基本写法与调用方法

C++中读取YAML方法也借助于yaml库,其安装可以直接使用apt工具。

1、YAML的基本写法

这里写一个非常简单的YAML文件,比起XML的规则来说,实在是方便太多了。直接“变量名“ + “:”+“ ‘变量值’”就行,需要注意的是这里的变量值保存的是string,如果与代码中应用的类型不同,则应该存在类型转换的步骤。

#data pathdata_path: '/home/data/'#记录了数据的读取路径

2、YAML的调用方法

根据上面的data_path,直接用如下方式调用就可以了,非常方便,读进去的data_path值在data_root中。

#include "yaml-cpp/yaml.h"
int main(int argc, char const *argv[]){ std::string data_root; std::string yaml_path = "../data_path.yaml"; YAML::Node basenode = YAML::LoadFile(yaml_path); data_root = basenode["data_path"].as<std::string>(); if (data_root.empty()) std::cout << BOLDRED << "[Error]" << RESET << " : param data_root is empty" << std::endl; //Operations return 1;}


另外需要注意的就是编译时,如果采用Cmake工具,则在CmakeLists.txt中应该有如下的写法:

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)project(project)include_directories(include)find_package(yaml-cpp REQUIRED)link_directories(src)aux_source_directory(src SOURCE)add_executable(project${SOURCE} main.cpp)target_link_libraries(project yaml-cpp)

find_package,target_link_libraries时包含yaml的库,写时注意其为yaml-cpp。

转自知乎作者:佳浩(SLAM算法工程师)
链接:https://zhuanlan.zhihu.com/p/467707462

本文仅做学术分享,如有侵权,请联系删文。

—THE END—
good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter