技术分享 | SLAM工程中使用配置文件加载程序参数的实现方法
点击下方卡片,关注“新机器视觉”公众号
重磅干货,第一时间送达
我们在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文件的基本写法:
<event1>
<variable1>variable_value1variable1>
<variable2>variable_value2variable2>
event1>
<event2>
<variable3>variable_value3variable3>
<variable4>variable_value4variable4>
event2>
<box>
<node id="0" type="0">
<width>2.5width>
<height>2.5height>
<depth>2.5depth>
node>
box>
2、XML文件的调用方法
调用的时候,按照上述举例的XML部分进行读入解析,有如下C++代码参考:
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 path
data_path: '/home/data/'
#记录了数据的读取路径
2、YAML的调用方法
根据上面的data_path,直接用如下方式调用就可以了,非常方便,读进去的data_path值在data_root中。
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。
本文仅做学术分享,如有侵权,请联系删文。