一、在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) 如果数据类型为字符串,字符串不能以数字开头,否则读不出来(这个也许可以解决,只是没找着方法);