一、在ROS底下使用.yaml文件配置参数
在ROS底下用起来还是非常方便的,首先,写一个读参数的函数getParam(),由于参数类型不止一种,所以要使用模板。
具体语句如下:
template<typename T>
T getParam(const string& name,const T& defaultValue) //This name must be namespace+parameter_name
{
T v;
if(ros::param::get(name,v)) //get parameter by name depend on ROS.
{
ROS_INFO_STREAM("Found parameter: "<<name<<",\tvalue: "<<v);
return v;
}
else
ROS_WARN_STREAM("Cannot find value for parameter: "<<name<<",\tassigning default: "<<defaultValue);
return defaultValue; //if the parameter haven't been set,it's value will return defaultValue.
}
//How use.
int main(int argc,char** argv)
{
ros::init(argc,argv,"readyaml");
ros::NodeHandle nh;
getParam<int>("readyaml/int",0);
getParam<float>("readyaml/float",0.5);
getParam<string>("readyaml/string","NotFound");
getParam<bool>("readyaml/bool",false);
return 0;
}
那么怎么设置参数?看代码。
<launch>
<node pkg="readyaml" type="readyaml" name="readyaml" clear_params="true" output="screen">
<!-- First way: direct set-->
<param name="int" value="32760"/>
<!-- Second way: use .yaml file-->
<rosparam file="$(find readyaml)/rosYaml.yaml"/>
</node>
</launch>
rosYaml.yaml文件里写的什么?
#parameter_name: value
string: HaveFound
float: 3.14159
bool: true
程序运行结果:
二、使用Ubuntu下的yaml-cpp
只要在CMakeLists.txt文件中添加相应声明,就可以在程序中使用Ubuntu下一个关于yaml文件的一个库,也是非常方便。
要添进去的语句如下:
FIND_LIBRARY(YAML_CPP_LIBRARIES yaml-cpp)
笔者装的是yaml的库,也可以安装package版本,CMakeLists.txt中添加的语句可以改成:
FIND_LIBRARY(YAML_CPP_LIBRARIES yaml-cpp)
if(NOT YAML_CPP_LIBRARIES)
# If yaml-cpp not found in the system, try finding it as a user CMake-generated project
FIND_PACKAGE(yaml-cpp REQUIRED)
INCLUDE_DIRECTORIES(${YAML_CPP_INCLUDE_DIRS})
endif(NOT YAML_CPP_LIBRARIES)
然后,在构建可执行文件时添加相应的依赖
target_link_libraries(use_yaml ${YAML_CPP_LIBRARIES})
下面说怎么使用,
第一步,使用YAML::LoadFile()函数加载yaml文件;
如果参数没有“归属”(自己的理解,下面会解释),直接使用as()函数读取该参数;
如果参数有“归属”,先找到参数的主体,再使用as()读取该参数;
说的不清楚,看程序吧。
//自己重写的读参数的函数,形参依次是,参数的主体(YAML::Node)、参数名(string)、默认值(和参数的类型一致)
template<typename T>
T getParam(const YAML::Node& node,const string& name,const T& defaultValue)
{
T v;
try {
v=node[name].as<T>(); //读取参数
std::cout<<"Found parameter: "<<name<<",\tvalue: "<<v<<std::endl; //终端提示读取成功
} catch (std::exception e) {
//找不到该参数的话,将返回默认值
v=defaultValue;
std::cout<<"Cannot find parameter: "<<name<<",\tassigning default: "<<v<<std::endl;
}
return v;
}
int main()
{
//加载参数文件
YAML::Node dset_config = YAML::LoadFile("/home/liban/cfiles/Learn_basic/data/test.yaml");
//这里的title0,title1就可以看作其参数的主体
YAML::Node title0=dset_config["title0"];
YAML::Node title1=dset_config["title1"];
//参数single没有“归属“,所以第一个形参为dset_config
getParam<string>(dset_config,"single","cannot");
//Int,Str可以看作title0的属性,Int_,Str_看作title1的属性。
getParam<int>(title0,"Int",0);
getParam<string>(title0,"Str","Null");
getParam<int>(title1,"Int_",0);
getParam<string>(title1,"Str_","Null");
return 0;
}
yaml文件里怎么写的?
title0:
Int: 360
Str: helloworld!
title1:
Int_: 480
Str_: success!
single: can
注意事项:
不要用Tab,用空格!用空格!用空格!
程序运行结果截图:
三、想不到OpenCV库里也有读取yaml参数的功能
主要是使用一个cv::FileStorage()函数用来加载参数文件
还是和前面一样,自己重写一个函数读参数 。 。 。
不再细说,直接看demo
template<typename T>
T getParam(const cv::FileStorage& file,const string& key)
{
T v=T(file[key]); // Core sentence,read parameter.
std::cout<<"Found parameter: "<<key<<",\tvalue: "<<v<<std::endl;
return v;
}
int main()
{
string filename="Path to yaml-file";
// Load yaml-file.
cv::FileStorage file_=cv::FileStorage(filename,cv::FileStorage::READ);
// If cannot find yaml-file.
if(file_.isOpened()==false)
{
std::cerr<<"yaml-file "<<filename<<" does not exist."<<std::endl;
file_.release();
return 1;
}
getParam<string>(file_,"#data"); // Test '#'.
getParam<string>(file_,"Str");
getParam<int>(file_,"Int");
getParam<float>(file_,"Float");
...
return 0;
}
yaml-file里的数据
%YAML:1.0
#data: cannot
Int: 120
Float: 3.145926
Str: helloworld!
执行结果:
注意事项:
(1) yaml文件开头一定要加上"%YAML:1.0";
(2) 可以使用'#'注释文件内容,效果如上截图;
(3) 如果数据类型为字符串,字符串不能以数字开头,否则读不出来(这个也许可以解决,只是没找着方法);